"use client" import { useState, useRef, useEffect, Fragment } from "react" import { Send, Loader2, Bot, User, RefreshCw, AlertCircle } from "lucide-react" function linkifyText(text: string) { const urlRegex = /(https?:\/\/[^\s<]+[^\s<.,;:!?)\]}>])/ const parts = text.split(urlRegex) return parts.map((part, i) => { if (part.startsWith("http://") || part.startsWith("https://")) { return {part} } return {part} }) } interface ChatMessage { role: "user" | "assistant" content: string } export function AIChat() { const [messages, setMessages] = useState([]) const [input, setInput] = useState("") const [loading, setLoading] = useState(false) const [error, setError] = useState("") const [ollamaStatus, setOllamaStatus] = useState(null) const messagesEndRef = useRef(null) useEffect(() => { fetch(`${AI_API}/ai/jobs`) .then((r) => r.json()) .then((data) => { if (data.jobs?.length) { const names = data.jobs.map((j: { job_title: string }) => j.job_title) setMessages([ { role: "assistant", content: `Hi! I'm your Sales AI Assistant. I can help with tips for targeting:\n\n${names.map((n: string) => `• ${n}`).join("\n")}\n\nWhat would you like to know?`, }, ]) } else { setMessages([ { role: "assistant", content: "Hi! I'm your Sales AI Assistant. Ask me anything about sales strategies and prospect targeting.", }, ]) } }) .catch(() => { setMessages([ { role: "assistant", content: "Hi! I'm your Sales AI Assistant. Ask me anything about sales strategies and prospect targeting.", }, ]) }) }, []) useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }) }, [messages]) const AI_API = process.env.NEXT_PUBLIC_AI_URL || "http://127.0.0.1:3001" const checkOllama = async () => { try { const res = await fetch(`${AI_API}/health`) const data = await res.json() setOllamaStatus(data.status === "ok") } catch { setOllamaStatus(false) } } useEffect(() => { checkOllama() }, []) const sendMessage = async () => { const msg = input.trim() if (!msg || loading) return setInput("") setError("") setMessages((prev) => [...prev, { role: "user", content: msg }]) setLoading(true) try { const res = await fetch(`${AI_API}/ai/chat`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: msg }), }) if (!res.ok) { const data = await res.json().catch(() => ({})) throw new Error(data.error || `Error ${res.status}`) } const data = await res.json() setMessages((prev) => [...prev, { role: "assistant", content: data.response }]) } catch (err) { const errMsg = err instanceof Error ? err.message : "AI service unavailable" setError(errMsg) setMessages((prev) => [ ...prev, { role: "assistant", content: `⚠️ Error: ${errMsg}. Make sure Ollama is running with the model loaded.` }, ]) } finally { setLoading(false) } } const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault() sendMessage() } } return ( {ollamaStatus === false && ( Ollama not responding. Start it with ollama serve )} {messages.map((msg, i) => ( {msg.role === "assistant" && ( )} {linkifyText(msg.content)} {msg.role === "user" && ( )} ))} {loading && ( )} {error && ( {error} )} setInput(e.target.value)} onKeyDown={handleKeyDown} placeholder="Ask for sales tips..." rows={1} className="flex-1 bg-[#1a1a24] border border-[#2a2a35] rounded-lg px-3 py-2 text-sm text-[#e8e8ef] placeholder-[#6a6a75] resize-none outline-none focus:border-[#1BB0CE]/50" /> {loading ? : } ) }
ollama serve