"use client"; import { useChat } from "@ai-sdk/react"; import { DefaultChatTransport, type UIMessage } from "ai"; import { Brain, Loader2, MessageSquare, Plus, Send, Trash2 } from "lucide-react"; import { Button } from "poyraz-ui/atoms"; import { useEffect, useRef, useState } from "react"; import { toast } from "poyraz-ui/molecules"; import { createChatSessionAction, deleteChatSessionAction, listChatMessagesAction, listChatSessionsAction, } from "./actions"; function formatMessageContent(text: string) { if (!text) return null; const lines = text.split("\n"); return lines.map((line, i) => ( {line.split(/(\*\*.*?\*\*|\*.*?\*)/g).map((part, j) => { if (part.startsWith("**") && part.endsWith("**")) { return ( {part.slice(2, -2)} ); } if (part.startsWith("*") && part.endsWith("*")) { return {part.slice(1, -1)}; } return {part}; })} {i !== lines.length - 1 &&
}
)); } type ChatSession = { id: string; title: string; created_at: string; }; export default function AIChatPage() { const [sessions, setSessions] = useState([]); const [activeSessionId, setActiveSessionId] = useState(null); const [input, setInput] = useState(""); const [isMobileSessionsOpen, setIsMobileSessionsOpen] = useState(false); const messagesEndRef = useRef(null); const { messages, sendMessage, setMessages, status, stop } = useChat({ transport: new DefaultChatTransport({ api: "/api/chat" }), onError: (error) => { console.error(error); toast.error(error.message || "Yapay zeka ile iletişim kurulurken bir hata oluştu."); }, }); const isLoading = status === "submitted" || status === "streaming"; useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); }, [messages]); useEffect(() => { async function fetchSessions() { try { const data = await listChatSessionsAction(); setSessions(data); setActiveSessionId(data[0]?.id || null); } catch (error) { toast.error(error instanceof Error ? error.message : "Sohbetler yüklenemedi."); } } void fetchSessions(); }, []); useEffect(() => { async function fetchMessages() { if (!activeSessionId) { setMessages([]); return; } try { const data = await listChatMessagesAction(activeSessionId); const formattedMessages: UIMessage[] = data.map((message) => ({ id: message.id, role: message.role as UIMessage["role"], parts: [{ type: "text", text: message.content }], })); setMessages(formattedMessages); } catch (error) { toast.error(error instanceof Error ? error.message : "Mesajlar yüklenemedi."); } } void fetchMessages(); }, [activeSessionId, setMessages]); async function handleNewChat() { setActiveSessionId(null); setMessages([]); } async function handleDeleteSession(id: string, event: React.MouseEvent) { event.stopPropagation(); try { await deleteChatSessionAction(id); } catch (error) { toast.error(error instanceof Error ? error.message : "Sohbet silinemedi."); return; } const nextSessions = sessions.filter((session) => session.id !== id); setSessions(nextSessions); if (activeSessionId === id) { setActiveSessionId(nextSessions[0]?.id || null); if (nextSessions.length === 0) setMessages([]); } } async function handleSubmit(event: { preventDefault: () => void }) { event.preventDefault(); const currentInput = input.trim(); if (!currentInput || isLoading) return; let sessionId = activeSessionId; setInput(""); if (!sessionId) { let newSession: ChatSession; try { newSession = await createChatSessionAction( currentInput.length > 32 ? `${currentInput.slice(0, 32)}...` : currentInput, ); } catch (error) { toast.error(error instanceof Error ? error.message : "Sohbet oluşturulamadı."); setInput(currentInput); return; } sessionId = newSession.id; setActiveSessionId(sessionId); setSessions((currentSessions) => [newSession, ...currentSessions]); } await sendMessage({ text: currentInput }, { body: { sessionId } }); } const SessionsSidebarContent = ( <>

Sohbetler

{sessions.length === 0 ? (
Henüz sohbet yok.
) : ( sessions.map((session) => (
)) )}
); return (
{/* Desktop Sidebar */} {/* Mobile Sidebar Overlay */} {isMobileSessionsOpen && (
setIsMobileSessionsOpen(false)} /> )} {/* Mobile Sidebar Drawer */}

AI Asistan

{messages.length === 0 ? (

Verilerine danış

Görevler, projeler, müşteriler, finans ve günlük kayıtların hakkında soru sorabilirsin.

) : ( messages.map((message) => { const text = getMessageText(message); return (
{formatMessageContent(text)}
); }) )} {isLoading ? (
Yanıt hazırlanıyor...
) : null}