32 lines
1.7 KiB
TypeScript

import { useEffect, useRef, useState } from "react";
export interface Msg { id: number; role: "user" | "bot" | "sys"; text: string }
/** Chat popup. Typed messages go to the model via /api/chat; position/size/colours come from the theme. */
export function Chat({ open, setOpen, mode, msgs, onSend }: {
open: boolean; setOpen: (o: boolean) => void; mode: string; msgs: Msg[]; onSend: (text: string) => void;
}) {
const [value, setValue] = useState("");
const logRef = useRef<HTMLDivElement>(null);
useEffect(() => { if (logRef.current) logRef.current.scrollTop = logRef.current.scrollHeight; }, [msgs, open]);
return (
<>
<button id="chatLauncher" className="launcher" aria-label="Open the market agent" style={{ display: open ? "none" : undefined }}
onClick={() => setOpen(true)}>💬 Ask the agent</button>
<aside id="chat" className={"chat" + (open ? "" : " hidden")} aria-label="Market agent chat">
<div className="chat-head">
<div><b>Market Guide</b><div className="sub" id="chatMode">{mode}</div></div>
<button id="chatClose" aria-label="Close" onClick={() => setOpen(false)}>✕</button>
</div>
<div id="log" className="log" ref={logRef}>
{msgs.map((m) => <div key={m.id} className={"msg " + m.role}>{m.text}</div>)}
</div>
<form id="chatForm" className="chat-form" onSubmit={(e) => { e.preventDefault(); const v = value.trim(); if (!v) return; setValue(""); onSend(v); }}>
<input id="chatInput" autoComplete="off" placeholder="e.g. find a bike, or: make it look retro" value={value} onChange={(e) => setValue(e.target.value)} />
<button>Send</button>
</form>
</aside>
</>
);
}