From e9de6ba62c4649c0094451eb321c713b4c1af115 Mon Sep 17 00:00:00 2001 From: SinachPat Date: Mon, 17 Aug 2026 21:16:43 +0100 Subject: [PATCH] fix: store session token on signup and send it to /chat - web: App stores sessionToken and passes to useChat; useChat sends Authorization header - web: ChatPanel adds wursor-message-user/agent test hooks - verified full UI flow (signup -> chat -> working -> reply -> approve -> preview) --- web/src/App.tsx | 26 ++++++++++++---- web/src/components/ChatPanel.tsx | 2 +- web/src/hooks/useChat.ts | 52 ++++++++++++++++++-------------- 3 files changed, 50 insertions(+), 30 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 2ca6a4c..65f5012 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -5,15 +5,29 @@ import { Preview } from './components/Preview.tsx'; import { SignUp } from './components/SignUp.tsx'; import { useChat } from './hooks/useChat.ts'; -export function App() { - const [signedUp, setSignedUp] = useState(false); - const [applied, setApplied] = useState(false); - const chat = useChat(); +async function signUp(email: string, password: string): Promise { + const res = await fetch('/auth/signup', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email, password }), + }); + if (!res.ok) { + const body = (await res.json().catch(() => null)) as { error?: string } | null; + throw new Error(body?.error ?? 'Sign up failed'); + } + const body = (await res.json()) as { sessionToken: string }; + return body.sessionToken; +} - if (!signedUp) { +export function App() { + const [sessionToken, setSessionToken] = useState(null); + const [applied, setApplied] = useState(false); + const chat = useChat(sessionToken); + + if (sessionToken === null) { return (
- setSignedUp(true)} /> + setSessionToken(await signUp(email, password))} />
); } diff --git a/web/src/components/ChatPanel.tsx b/web/src/components/ChatPanel.tsx index 92c6426..829ff67 100644 --- a/web/src/components/ChatPanel.tsx +++ b/web/src/components/ChatPanel.tsx @@ -30,7 +30,7 @@ export function ChatPanel({ messages, status, onSend }: ChatPanelProps) { ) : (
    {messages.map((message) => ( -
  • +
  • {message.text}
  • ))} diff --git a/web/src/hooks/useChat.ts b/web/src/hooks/useChat.ts index db80408..70574fc 100644 --- a/web/src/hooks/useChat.ts +++ b/web/src/hooks/useChat.ts @@ -14,35 +14,41 @@ function mockReply(text: string, heading: string | undefined): string { : 'Done — your change is ready to preview.'; } -export function useChat() { +export function useChat(sessionToken: string | null) { const [messages, setMessages] = useState([]); const [status, setStatus] = useState('idle'); const [heading, setHeading] = useState('Welcome to our site'); - const send = useCallback(async (text: string) => { - const nextHeading = extractHeading(text); - setMessages((prev) => [...prev, { id: crypto.randomUUID(), role: 'user', text }]); - setStatus('working'); + const send = useCallback( + async (text: string) => { + const nextHeading = extractHeading(text); + setMessages((prev) => [...prev, { id: crypto.randomUUID(), role: 'user', text }]); + setStatus('working'); - try { - const res = await fetch('/chat', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ message: text }), - }); - if (!res.ok) throw new Error('chat unavailable'); - const body = (await res.json()) as { reply?: string }; - setMessages((prev) => [...prev, { id: crypto.randomUUID(), role: 'agent', text: body.reply ?? 'Done' }]); - } catch { - await new Promise((resolve) => setTimeout(resolve, 1200)); - setMessages((prev) => [...prev, { id: crypto.randomUUID(), role: 'agent', text: mockReply(text, nextHeading) }]); - } + try { + const res = await fetch('/chat', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + ...(sessionToken !== null ? { Authorization: `Bearer ${sessionToken}` } : {}), + }, + body: JSON.stringify({ message: text }), + }); + if (!res.ok) throw new Error('chat unavailable'); + const body = (await res.json()) as { reply?: string }; + setMessages((prev) => [...prev, { id: crypto.randomUUID(), role: 'agent', text: body.reply ?? 'Done' }]); + } catch { + await new Promise((resolve) => setTimeout(resolve, 1200)); + setMessages((prev) => [...prev, { id: crypto.randomUUID(), role: 'agent', text: mockReply(text, nextHeading) }]); + } - if (nextHeading !== undefined) { - setHeading(nextHeading); - } - setStatus('done'); - }, []); + if (nextHeading !== undefined) { + setHeading(nextHeading); + } + setStatus('done'); + }, + [sessionToken], + ); return { messages, status, heading, send }; }