/* global React, DATA, mdToHtml, splitCharts, ChartFromSpec */ const Copilot = ({ open, onClose }) => { const m = DATA.meta; const [messages, setMessages] = useState([{ role: 'ai', t: `Good morning. I'm the flynas RM Copilot — I read the live warehouse directly. ` + `I can see ${fmtN(m.flights_12m)} flown sectors over the last 12 months across ${m.routes} city-pairs ` + `(${m.destinations} airports). Ask me anything: booking pace, yields, class closures, competitor fares, forecasts.` }]); const [input, setInput] = useState(''); const [thinking, setThinking] = useState(false); const endRef = useRef(); useEffect(() => { endRef.current && endRef.current.scrollTo({ top: 9e9, behavior: 'smooth' }); }, [messages, thinking]); const send = async (text) => { if (!text.trim() || thinking) return; const next = [...messages, { role: 'user', t: text }]; setMessages(next); setInput(''); setThinking(true); try { const apiMessages = next.filter(x => x.t).map(x => ({ role: x.role === 'ai' ? 'assistant' : 'user', content: x.t })); const base = (window.API_BASE_URL || ''); const res = await fetch(base + '/api/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ messages: apiMessages }) }); if (!res.ok) throw new Error('HTTP ' + res.status); const data = await res.json(); setMessages(mm => [...mm, { role: 'ai', t: data.reply || '(no reply)' }]); } catch (e) { setMessages(mm => [...mm, { role: 'ai', t: `_Desk unreachable:_ ${e.message}` }]); } finally { setThinking(false); } }; const quick = [ 'RUH-JED Y-class booking pace vs last year', 'Top 5 O&Ds by forward revenue next 30 days', 'Which Umrah routes are running tightest into Hajj?', 'Where is flyadeal undercutting us most?', 'Network load factor by market, last 30 days', 'Class-closure status on RUH-DXB next 14 days', ]; if (!open) return null; const Bubble = ({ msg }) => { if (msg.role === 'user') return React.createElement('div', { className: 'msg msg-user' }, msg.t); const { text, charts } = splitCharts(msg.t || ''); return React.createElement('div', { className: 'msg msg-ai' }, React.createElement('div', { dangerouslySetInnerHTML: { __html: mdToHtml(text) } }), charts.map((c, i) => React.createElement(ChartFromSpec, { key: i, spec: c }))); }; return React.createElement('section', { className: 'copilot' }, // masthead-style header React.createElement('div', { className: 'copilot-head' }, React.createElement('div', { className: 'row gap-3' }, React.createElement('div', null, React.createElement('div', { className: 'row gap-2' }, React.createElement('span', { className: 'dot dot-pos' }), React.createElement('span', { className: 'serif', style: { fontSize: 24, fontWeight: 600 } }, 'RM Copilot'), React.createElement('span', { className: 'pill pill-teal' }, 'C1 · Conversational Workbench')), React.createElement('div', { style: { fontSize: 11.5, color: 'var(--text-muted)', marginTop: 2 } }, 'Anthropic Claude · live text-to-SQL on the flynas warehouse'))), React.createElement('button', { className: 'btn', onClick: onClose, title: 'Close (⌘ /)' }, '✕ Close')), // scrollable conversation React.createElement('div', { className: 'copilot-scroll', ref: endRef }, React.createElement('div', { className: 'copilot-msgs' }, messages.map((msg, i) => React.createElement(Bubble, { key: i, msg })), thinking && React.createElement('div', { className: 'msg msg-ai', style: { color: 'var(--text-muted)', fontStyle: 'italic' } }, '· · · querying the warehouse'))), // footer: quick prompts + input, centred to the reading column React.createElement('div', { className: 'copilot-footer' }, React.createElement('div', { className: 'copilot-foot-inner' }, React.createElement('div', { className: 'copilot-quick' }, quick.map((q, i) => React.createElement('button', { key: i, className: 'filter-chip', onClick: () => send(q) }, q))), React.createElement('div', { className: 'copilot-input' }, React.createElement('input', { className: 'input', style: { flex: 1, height: 42, fontSize: 14 }, placeholder: 'Ask the desk anything…', value: input, onChange: e => setInput(e.target.value), onKeyDown: e => e.key === 'Enter' && send(input), disabled: thinking, autoFocus: true }), React.createElement('button', { className: 'btn btn-accent', style: { height: 42, padding: '0 22px' }, onClick: () => send(input), disabled: thinking }, thinking ? 'Working…' : 'Send'))))); }; window.Copilot = Copilot;