diff --git a/src/components/ai-ask-panel.tsx b/src/components/ai-ask-panel.tsx new file mode 100644 index 0000000..2a2e5dc --- /dev/null +++ b/src/components/ai-ask-panel.tsx @@ -0,0 +1,146 @@ +'use client'; + +import { useRef, useState, useEffect } from 'react'; +import { useMutation, useQuery } from '@tanstack/react-query'; +import { apiFetch } from '../lib/api'; +import { useSession } from './session-provider'; + +interface Message { role: 'user' | 'assistant'; content: string; } + +export function AiAskPanel() { + const { activeTenant } = useSession(); + const tenantId = activeTenant?.tenantId ?? ''; + const [open, setOpen] = useState(false); + const [input, setInput] = useState(''); + const [messages, setMessages] = useState([]); + const bottomRef = useRef(null); + + useEffect(() => { + bottomRef.current?.scrollIntoView({ behavior: 'smooth' }); + }, [messages]); + + const askMut = useMutation({ + mutationFn: (userMsg: string) => + apiFetch<{ reply: string }>('/v1/ai/ask', { + tenantId, + method: 'POST', + body: { + messages: [...messages, { role: 'user', content: userMsg }], + context: JSON.stringify({ tenantId, ts: new Date().toISOString() }), + }, + }), + onSuccess: (data, userMsg) => { + setMessages((prev) => [ + ...prev, + { role: 'user', content: userMsg }, + { role: 'assistant', content: data.reply }, + ]); + }, + }); + + const { data: brief } = useQuery({ + queryKey: ['daily-brief', tenantId], + queryFn: () => apiFetch<{ brief: string }>('/v1/ai/daily-brief', { tenantId }), + enabled: Boolean(tenantId) && open && messages.length === 0, + staleTime: 600_000, // 10 min + }); + + function send() { + const msg = input.trim(); + if (!msg || askMut.isPending) return; + setInput(''); + askMut.mutate(msg); + } + + const SUGGESTIONS = [ + 'Ce ar trebui să prioritizez azi?', + 'Rezumă săptămâna trecută.', + 'Care sunt obiectivele cu risc de nefinalizare?', + 'Generează un brief pentru echipă.', + ]; + + if (!tenantId) return null; + + return ( + <> + {/* Floating button */} + + + {/* Panel */} + {open && ( +
+ {/* Header */} +
+ +

CEO OS AI

+ via Hermes +
+ + {/* Messages */} +
+ {messages.length === 0 && brief?.brief && ( +
+

Brief zilnic

+

{brief.brief}

+
+ )} + {messages.length === 0 && !brief && ( +
+

Întreabă-mă orice despre CEO OS:

+ {SUGGESTIONS.map((s) => ( + + ))} +
+ )} + {messages.map((m, i) => ( +
+
+ {m.content} +
+
+ ))} + {askMut.isPending && ( +
+
+ Hermes gândește… +
+
+ )} + {askMut.isError && ( +

+ Hermes indisponibil. Verifică HERMES_BASE_URL în Coolify. +

+ )} +
+
+ + {/* Input */} +
+ setInput(e.target.value)} + onKeyDown={(e) => e.key === 'Enter' && !e.shiftKey && send()} + placeholder="Întreabă ceva… (Enter)" + className="flex-1 rounded-xl border bg-background px-3 py-2 text-xs text-ink focus:outline-none focus:ring-2 focus:ring-ring" + /> + +
+
+ )} + + ); +}