feat(frontend): add React SPA with chat, auth, and admin pages
- Vite 6 + React 19 + TypeScript + Tailwind 4 + Zustand 5 - Login page with JWT auth - Chat interface: MessageList, ChatInput, ChatContainer - WebSocket hook with auto-reconnect and exponential backoff - Sidebar with new chat button + session navigation - Admin dashboard placeholder - 57 modules, 242KB JS, TypeScript zero errors
This commit is contained in:
1 parent
192144563b
commit
4a71965686
35 files changed
+3146
No files matched your search
@@ -0,0 +1,47 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { useChatStore } from '../../store/chatStore'
|
||||
import { useWebSocket } from '../../hooks/useWebSocket'
|
||||
import MessageList from './MessageList'
|
||||
import ChatInput from './ChatInput'
|
||||
|
||||
export default function ChatContainer() {
|
||||
const { send } = useWebSocket()
|
||||
const { messages, isStreaming, currentSessionId, inputText, setInput, addMessage, setStreaming } = useChatStore()
|
||||
const bottomRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
bottomRef.current?.scrollIntoView({ behavior: 'smooth' })
|
||||
}, [messages])
|
||||
|
||||
const handleSend = () => {
|
||||
if (!inputText.trim() || !currentSessionId) return
|
||||
|
||||
const userMsg = {
|
||||
id: crypto.randomUUID(), session_id: currentSessionId,
|
||||
role: 'user' as const, content: inputText, created_at: new Date().toISOString(),
|
||||
}
|
||||
addMessage(userMsg)
|
||||
setStreaming(true)
|
||||
|
||||
// Add placeholder for assistant response
|
||||
addMessage({ id: crypto.randomUUID(), session_id: currentSessionId, role: 'assistant', content: '', created_at: new Date().toISOString() })
|
||||
|
||||
send({ type: 'message', content: inputText, session_id: currentSessionId, timestamp: Date.now() })
|
||||
setInput('')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<div className="flex-1 overflow-auto px-4 py-4">
|
||||
<MessageList messages={messages} />
|
||||
<div ref={bottomRef} />
|
||||
</div>
|
||||
<ChatInput
|
||||
value={inputText}
|
||||
onChange={setInput}
|
||||
onSend={handleSend}
|
||||
disabled={isStreaming}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user