diff --git a/apps/tasks/app/chat/page.tsx b/apps/tasks/app/chat/page.tsx new file mode 100644 index 0000000..7e42e4d --- /dev/null +++ b/apps/tasks/app/chat/page.tsx @@ -0,0 +1,190 @@ +"use client"; + +import { useState, useRef, useEffect } from "react"; +import { useRouter } from "next/navigation"; +import { useAuth } from "@/lib/auth"; + +interface ChatMessage { + id: string; + role: "user" | "assistant"; + content: string; + timestamp: Date; +} + +export default function ChatPage() { + const { token, user } = useAuth(); + const router = useRouter(); + const [messages, setMessages] = useState([]); + const [input, setInput] = useState(""); + const [loading, setLoading] = useState(false); + const messagesEndRef = useRef(null); + const inputRef = useRef(null); + + useEffect(() => { + if (!token) { + router.replace("/login"); + } + }, [token, router]); + + useEffect(() => { + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); + }, [messages]); + + async function handleSend() { + const text = input.trim(); + if (!text || loading || !token) return; + + const userMsg: ChatMessage = { + id: Date.now().toString(), + role: "user", + content: text, + timestamp: new Date(), + }; + + setMessages((prev) => [...prev, userMsg]); + setInput(""); + setLoading(true); + + try { + const res = await fetch("/api/v1/chat", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({ message: text }), + }); + + if (!res.ok) { + throw new Error(`HTTP ${res.status}`); + } + + const data = await res.json(); + const assistantMsg: ChatMessage = { + id: (Date.now() + 1).toString(), + role: "assistant", + content: data.reply || data.message || "Omlouv\u00e1m se, nemohl jsem zpracovat va\u0161i zpr\u00e1vu.", + timestamp: new Date(), + }; + setMessages((prev) => [...prev, assistantMsg]); + } catch { + const errorMsg: ChatMessage = { + id: (Date.now() + 1).toString(), + role: "assistant", + content: "Chat asistent je momentáln\u011b nedostupný. Zkuste to prosím pozd\u011bji.", + timestamp: new Date(), + }; + setMessages((prev) => [...prev, errorMsg]); + } finally { + setLoading(false); + inputRef.current?.focus(); + } + } + + function handleKeyDown(e: React.KeyboardEvent) { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + handleSend(); + } + } + + if (!token) return null; + + return ( +
+ {/* Chat header */} +
+
+ + + +
+
+

AI Asistent

+

Zeptejte se na cokoliv ohledn\u011b va\u0161ich úkol\u016f

+
+
+ + {/* Messages area */} +
+ {messages.length === 0 && ( +
+
+ + + +
+

Za\u010dn\u011bte konverzaci

+

+ Napi\u0161te zpr\u00e1vu a AI asistent v\u00e1m pom\u016f\u017ee s úkoly +

+
+ )} + + {messages.map((msg) => ( +
+
+

{msg.content}

+

+ {msg.timestamp.toLocaleTimeString("cs-CZ", { hour: "2-digit", minute: "2-digit" })} +

+
+
+ ))} + + {loading && ( +
+
+
+
+
+
+
+
+
+ )} + +
+
+ + {/* Input area */} +
+
+