// Ask tab — chat against /api/chat. Empty state with suggestion pills, // user (right blue bubble) / assistant (left white card) bubbles, pulsing // "analyzing…" loader, sticky rounded input pill at the bottom. const { api: askApi } = window.HC_DATA; function AskTab() { const theme = window.HC_THEME.useHCTheme(); const p = theme.palette; const [messages, setMessages] = React.useState([]); const [input, setInput] = React.useState(''); const [loading, setLoading] = React.useState(false); const scrollRef = React.useRef(null); React.useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [messages, loading]); const suggestions = [ 'what happened this week', 'how are drinks affecting my sleep', 'am I ready to train again', 'compare this week to last week', ]; // Heuristic: questions that span longer windows should pull more history. function inferDays(q) { const t = q.toLowerCase(); if (/since (jan|feb|march|april|new year)|month|year/.test(t)) return 150; if (/last 4 weeks|past month/.test(t)) return 30; return 14; } const send = async (text) => { const q = (text ?? input).trim(); if (!q || loading) return; setInput(''); const next = [...messages, { role: 'user', content: q }]; setMessages(next); setLoading(true); try { const res = await askApi('/api/chat', { method: 'POST', body: JSON.stringify({ message: q, history: next.slice(0, -1), days: inferDays(q), }), }); setMessages([...next, { role: 'assistant', content: res.reply || '' }]); } catch (e) { setMessages([...next, { role: 'assistant', content: "— couldn't reach the analyst. try again.", }]); } finally { setLoading(false); } }; const onKey = (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }; const hasConversation = messages.length > 0 || loading; return (