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

88 lines
3.0 KiB
TypeScript

"use client";
import { useState } from "react";
import { MessageCircle } from "lucide-react";
import { ChatMessageList, ChatComposer, type ChatBubbleMessage } from "@/components/ai/chat-thread";
import { colorModeFromTheme } from "@/components/theme/use-dark-theme";
import { useSpeechRecognition } from "@/hooks/use-speech-recognition";
import { sendChatMessage, type ChatMessage } from "@/lib/actions/chat-ai";
export function ChatPageClient({ aiConfigured }: { aiConfigured: boolean }) {
const colorMode = colorModeFromTheme();
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 className="flex items-center gap-3 px-1">
<span className="flex size-10 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary">
<MessageCircle className="size-5" />
</span>
<div className="min-w-0">
<h1 className="truncate font-heading text-xl font-bold tracking-tight">Chat</h1>
<p className="truncate text-[13px] text-muted-foreground">
Ask about anything across your boards notes, open to-dos, and things you&apos;ve
already finished.
</p>
</div>
</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>
);
}