Organize/components/chat/chat-page-client.tsx

87 lines
2.9 KiB
TypeScript

"use client";
import { useState } from "react";
import { useTheme } from "next-themes";
import { MessageCircle } from "lucide-react";
import { ChatMessageList, ChatComposer, type ChatBubbleMessage } from "@/components/ai/chat-thread";
import { useSpeechRecognition } from "@/hooks/use-speech-recognition";
import { sendChatMessage, type ChatMessage } from "@/lib/actions/chat-ai";
export function ChatPageClient({ aiConfigured }: { aiConfigured: boolean }) {
const { resolvedTheme } = useTheme();
const colorMode = resolvedTheme === "dark" ? "dark" : "light";
const [messages, setMessages] = useState<ChatMessage[]>([]);
const [input, setInput] = useState("");
const [sending, setSending] = useState(false);
const [error, setError] = useState<string | null>(null);
const { supported: micSupported, listening, start, stop } = useSpeechRecognition({
onFinalResult: (transcript) =>
setInput((prev) => (prev ? `${prev} ${transcript}` : transcript)),
onError: setError,
});
async function handleSend() {
const text = input.trim();
if (!text || sending) return;
if (listening) stop();
const next: ChatMessage[] = [...messages, { role: "user", content: text }];
setMessages(next);
setInput("");
setError(null);
setSending(true);
const result = await sendChatMessage(next);
setSending(false);
if ("error" in result) {
setError(result.error);
return;
}
setMessages([...next, { role: "assistant", content: result.content }]);
}
return (
<div className="mx-auto flex h-full max-w-2xl flex-col gap-4 p-4">
<div>
<h1 className="flex items-center gap-2 text-2xl font-bold">
<MessageCircle className="size-6 text-primary" />
Chat
</h1>
<p className="text-sm text-muted-foreground">
Ask about anything across your boards notes, open to-dos, and things you&apos;ve
already finished.
</p>
</div>
{!aiConfigured ? (
<p className="rounded-md border border-dashed p-8 text-center text-sm text-muted-foreground">
AI generation isn&apos;t configured yet. Ask an administrator to set it up.
</p>
) : (
<div className="flex flex-1 flex-col gap-3 overflow-hidden">
<ChatMessageList
messages={messages as ChatBubbleMessage[]}
sending={sending}
error={error}
emptyHint="Ask a question about your projects, groups, notes, or to-dos — done or still open."
colorMode={colorMode}
/>
<ChatComposer
value={input}
onChange={setInput}
onSend={handleSend}
sending={sending}
listening={listening}
micSupported={micSupported}
onStartListening={start}
onStopListening={stop}
/>
</div>
)}
</div>
);
}