'use client'; import { useState, useRef, useEffect, KeyboardEvent } from 'react'; import { Search, X, Sparkles, ChevronRight, MessageSquareWarning } from 'lucide-react'; import Link from 'next/link'; import { useAnalytics } from '../analytics/useAnalytics'; import { AnalyticsEvents } from '../analytics/analytics-events'; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; import AIOrb from './AIOrb'; interface ProductMatch { id: string; title: string; sku: string; slug: string; } interface Message { role: 'user' | 'assistant'; content: string; products?: ProductMatch[]; } interface ComponentProps { isOpen: boolean; onClose: () => void; initialQuery?: string; triggerSearch?: boolean; // If true, immediately searches on mount with initialQuery } export function AISearchResults({ isOpen, onClose, initialQuery = '', triggerSearch = false, }: ComponentProps) { const { trackEvent } = useAnalytics(); const [query, setQuery] = useState(''); const [messages, setMessages] = useState([]); const [honeypot, setHoneypot] = useState(''); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const inputRef = useRef(null); const modalRef = useRef(null); const messagesEndRef = useRef(null); useEffect(() => { if (isOpen) { document.body.style.overflow = 'hidden'; setTimeout(() => inputRef.current?.focus(), 100); if (triggerSearch && initialQuery && messages.length === 0) { setQuery(initialQuery); handleSearch(initialQuery); } else if (!triggerSearch) { setQuery(''); } } else { document.body.style.overflow = 'unset'; setQuery(''); setMessages([]); setError(null); setIsLoading(false); } return () => { document.body.style.overflow = 'unset'; }; }, [isOpen, triggerSearch]); useEffect(() => { if (isOpen && initialQuery && messages.length === 0) { setQuery(initialQuery); } }, [initialQuery, isOpen]); useEffect(() => { // Auto-scroll to bottom of chat messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages, isLoading]); const handleSearch = async (searchQuery: string = query) => { if (!searchQuery.trim() || isLoading) return; const newUserMessage: Message = { role: 'user', content: searchQuery }; const newMessagesContext = [...messages, newUserMessage]; setMessages(newMessagesContext); setQuery(''); setIsLoading(true); setError(null); trackEvent(AnalyticsEvents.FORM_SUBMIT, { type: 'ai_search', query: searchQuery, }); try { const res = await fetch('/api/ai-search', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ messages: newMessagesContext, _honeypot: honeypot, }), }); const data = await res.json(); if (!res.ok) { throw new Error(data.error || 'Failed to fetch search results'); } setMessages((prev) => [ ...prev, { role: 'assistant', content: data.answerText, products: data.products, }, ]); // Re-focus input after response so user can continue typing easily setTimeout(() => inputRef.current?.focus(), 100); } catch (err: any) { console.error(err); setError(err.message || 'An error occurred while chatting. Please try again.'); trackEvent(AnalyticsEvents.ERROR, { location: 'ai_search_results', message: err.message, query: searchQuery, }); } finally { setIsLoading(false); } }; const onKeyDown = (e: KeyboardEvent) => { if (e.key === 'Enter') { e.preventDefault(); handleSearch(); } if (e.key === 'Escape') { onClose(); } }; if (!isOpen) return null; // Handle clicking outside to close const handleBackdropClick = (e: React.MouseEvent) => { if (e.target === e.currentTarget) { onClose(); } }; return (
{/* Header */}

KLZ AI Consultant

{/* Chat History Area */}
{messages.length === 0 && !isLoading && !error && (

I am your technical consultant.

Describe your project, ask for specific cables, or tell me your requirements.

)} {messages.map((msg, index) => (
{msg.role === 'assistant' && (

AI Assistant

)}
{msg.role === 'assistant' ? ( {msg.content} ) : (

{msg.content}

)}
{/* Product Matches inside Assistant Message */} {msg.role === 'assistant' && msg.products && msg.products.length > 0 && (

Empfohlene Produkte

{msg.products.map((product, idx) => ( { onClose(); trackEvent(AnalyticsEvents.BUTTON_CLICK, { target: product.slug, location: 'ai_search_results', }); }} className="group flex flex-col justify-between bg-white text-primary rounded-lg p-4 hover:shadow-lg hover:-translate-y-1 transition-all duration-300" >

{product.sku}

{product.title}
Details
))}
)}
))} {isLoading && (
)} {error && (

System Error

{error}

)}
{/* Input Area */}
setQuery(e.target.value)} onKeyDown={onKeyDown} placeholder="Type your question or requirements..." className="flex-1 bg-transparent border-none text-white text-base md:text-lg p-4 focus:outline-none placeholder:text-white/30" disabled={isLoading} /> setHoneypot(e.target.value)} tabIndex={-1} autoComplete="off" aria-hidden="true" />
Press Enter to send • Esc to close
); }