"use client"; import { useState, useRef, useEffect } from "react"; import { useTranslations } from "next-intl"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/components/ui/sheet"; import { MessageCircle, Send, Bot, User } from "lucide-react"; import ReactMarkdown from "react-markdown"; import { cn } from "@/lib/utils"; import { ChatHistorySearch } from "./chat-history-search"; import { ClearChatHistoryButton } from "./clear-chat-history-button"; type Message = { role: "user" | "assistant"; content: string; }; type HistoryEntry = { role: "user" | "assistant"; content: string }; type Props = { recipeId: string; recipeTitle: string; }; export function RecipeChatPanel({ recipeId, recipeTitle }: Props) { const t = useTranslations("recipeChat"); const [open, setOpen] = useState(false); const [messages, setMessages] = useState([]); const [input, setInput] = useState(""); const [loading, setLoading] = useState(false); const bottomRef = useRef(null); const historyLoadedRef = useRef(false); useEffect(() => { if (!open || historyLoadedRef.current) return; historyLoadedRef.current = true; fetch(`/api/v1/ai/chat-history?recipeId=${recipeId}&limit=50`) .then((res) => (res.ok ? res.json() : null)) .then((json: { data?: HistoryEntry[] } | null) => { if (json?.data?.length) setMessages(json.data.map((m) => ({ role: m.role, content: m.content }))); }) .catch(() => {}); }, [open, recipeId]); useEffect(() => { if (open && bottomRef.current) { bottomRef.current.scrollIntoView({ behavior: "smooth" }); } }, [messages, open]); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); const question = input.trim(); if (!question || loading) return; setInput(""); setMessages((prev) => [...prev, { role: "user", content: question }]); setLoading(true); try { const res = await fetch("/api/v1/ai/recipe-chat", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ recipeId, question }), }); const data = await res.json() as { answer?: string; error?: string }; setMessages((prev) => [ ...prev, { role: "assistant", content: data.answer ?? t("sorry") }, ]); } catch { setMessages((prev) => [ ...prev, { role: "assistant", content: t("error") }, ]); } finally { setLoading(false); } }; const suggestions = [ t("suggestion1"), t("suggestion2"), t("suggestion3"), t("suggestion4"), ]; return ( <>
{t("title")}
setMessages([])} />

{recipeTitle}

{messages.length === 0 && (

{t("intro")}

{suggestions.map((s) => ( ))}
)} {messages.map((msg, i) => (
{msg.role === "user" ? : }
{msg.role === "assistant" ? ( {msg.content} ) : ( msg.content )}
))} {loading && (
)}
setInput(e.target.value)} placeholder={t("inputPlaceholder")} disabled={loading} className="flex-1" autoComplete="off" />
); }