11'use client' ;
22
3- import { Brain , CircleNotch , List , SidebarSimple , GlobeIcon } from '@phosphor-icons/react' ;
3+ import { Brain , CircleNotch , SidebarSimple , GlobeIcon , PlusCircle } from '@phosphor-icons/react' ;
44import { useParams , useRouter } from 'next/navigation' ;
55import { useCallback , useEffect , useState } from 'react' ;
66import { ChatSidebar } from '@/components/chat/chat-sidebar' ;
7- import { MemoryPanel } from '@/components/chat/memory-panel' ;
8- import { ModelPicker } from '@/components/chat/model-picker' ;
97import { AddModelsModal } from '@/components/chat/add-models-modal' ;
108import { KeyboardShortcuts } from '@/components/chat/keyboard-shortcuts' ;
119import { ContextMenuMessage } from '@/components/chat/context-menu-message' ;
@@ -87,7 +85,6 @@ export default function ChatPage() {
8785 const chatId = params . id as string ;
8886
8987 const [ sidebarOpen , setSidebarOpen ] = useState ( true ) ;
90- const [ memoryOpen , setMemoryOpen ] = useState ( false ) ;
9188 const [ chat , setChat ] = useState < Chat | null > ( null ) ;
9289 const [ chats , setChats ] = useState < Chat [ ] > ( [ ] ) ;
9390 const [ isLoadingChat , setIsLoadingChat ] = useState ( true ) ;
@@ -140,16 +137,6 @@ export default function ChatPage() {
140137
141138 const data = await res . json ( ) ;
142139 setChat ( data ) ;
143- // Initial messages are loaded by useStreamingChat via its own logic if we were using useChat fully,
144- // but here useStreamingChat manages messages state.
145- // The original code setInitialMessages separately.
146- // Assuming useStreamingChat handles the message list now or we load it here?
147- // The original code loaded initialMessages and combined them: const allMessages = [...initialMessages, ...messages];
148- // Wait, useStreamingChat in original code didn't load initial messages. It just exposed the new ones.
149- // So I need to keep the "load initial messages" logic, but merge it effectively.
150- // Actually, useStreamingChat hook in Step 16 has a "loadMessages" function.
151- // But typically useChat stores all messages.
152- // Let's stick to the previous pattern: "allMessages".
153140 } catch ( err ) {
154141 setError ( err instanceof Error ? err . message : 'Failed to load chat' ) ;
155142 } finally {
@@ -179,12 +166,11 @@ export default function ChatPage() {
179166 loadChats ( ) ;
180167 } , [ isLoaded , isSignedIn ] ) ;
181168
182- // Initial messages from chat load (re-implementing original logic because useStreamingChat is a wrapper)
169+ // Initial messages from chat load
183170 const [ initialMessages , setInitialMessages ] = useState < ChatMessage [ ] > ( [ ] ) ;
184171
185172 useEffect ( ( ) => {
186173 if ( chat ?. messages ) {
187- // Map chat.messages to the format we need
188174 const converted : ChatMessage [ ] = chat . messages . map ( ( m ) => ( {
189175 id : m . id ,
190176 role : m . role ,
@@ -196,11 +182,6 @@ export default function ChatPage() {
196182 }
197183 } , [ chat ] ) ;
198184
199- // Combine messages.
200- // Note: useStreamingChat messages are cumulative for the session.
201- // If we load old messages, we should probably initialize useStreamingChat with them if possible,
202- // or just display them.
203- // The previous code did: const allMessages = [...initialMessages, ...messages];
204185 const allMessages : ChatMessage [ ] = [ ...initialMessages , ...messages ] ;
205186
206187 const handleNewChat = useCallback ( async ( ) => {
@@ -269,7 +250,7 @@ export default function ChatPage() {
269250 if ( ! isLoaded ) {
270251 return (
271252 < div className = "h-screen flex items-center justify-center bg-background" >
272- < CircleNotch className = "w-8 h-8 animate-spin text-zinc-400 " />
253+ < CircleNotch className = "w-8 h-8 animate-spin text-muted-foreground " />
273254 </ div >
274255 ) ;
275256 }
@@ -280,17 +261,11 @@ export default function ChatPage() {
280261 }
281262
282263 return (
283- < div className = "h-screen bg-gradient-to-b from-white to-zinc-50 dark:from-zinc-950 dark:to-black overflow-hidden font-sans flex relative" >
284- { /* YULA Monolith Background - Amber glow only */ }
285- < div className = "absolute inset-0 pointer-events-none z-0" >
286- < div className = "absolute top-0 left-1/4 w-[500px] h-[500px] bg-gradient-to-br from-amber-100/10 to-transparent dark:from-amber-900/8 rounded-full blur-3xl opacity-50" />
287- < div className = "absolute bottom-0 right-1/4 w-[500px] h-[500px] bg-gradient-to-bl from-emerald-100/15 to-transparent dark:from-emerald-900/10 rounded-full blur-3xl opacity-50" />
288- </ div >
289-
264+ < div className = "h-screen bg-background overflow-hidden font-sans flex" >
290265 { /* Sidebar */ }
291266 < div
292267 className = { cn (
293- 'h-full bg-white/50 dark:bg-zinc-950/50 backdrop-blur border-r border-zinc-200 dark: border-zinc-900 transition-all duration-300 z-20' ,
268+ 'h-full bg-muted border-r border-border transition-all duration-300 z-20' ,
294269 sidebarOpen ? 'w-64' : 'w-0 overflow-hidden'
295270 ) }
296271 >
@@ -303,38 +278,26 @@ export default function ChatPage() {
303278 </ div >
304279
305280 { /* Main Chat Area */ }
306- < div className = "flex-1 h-full flex flex-col relative bg-transparent z-10 w-full min-w-0" >
307- { /* Header */ }
308- < div className = "flex items-center justify-between p-3 border-b border-zinc-200 dark:border-zinc-800 flex-none bg-white/50 dark:bg-zinc-950/50 backdrop-blur z-20 w-full" >
309- < div className = "flex items-center" >
310- < Button
311- variant = "ghost"
312- size = "icon"
313- onClick = { ( ) => setSidebarOpen ( ! sidebarOpen ) }
314- className = "h-8 w-8 text-muted-foreground hover:text-foreground mr-2"
315- >
316- < SidebarSimple className = "w-4 h-4" />
317- </ Button >
318- < div className = "hidden sm:block" >
319- < ModelPicker
320- selectedModel = { chat ?. modelPreference || 'openai/gpt-5.2' }
321- onSelectModel = { handleModelChange }
322- onOpenAddModels = { ( ) => setIsAddModelsOpen ( true ) }
323- enabledModels = { enabledModels }
324- />
325- </ div >
326- </ div >
327-
328- < div className = "flex items-center gap-2" >
329- < Button
330- variant = "ghost"
331- size = "icon"
332- onClick = { ( ) => setMemoryOpen ( ! memoryOpen ) }
333- className = "h-8 w-8 text-muted-foreground hover:text-foreground"
334- >
335- < List className = "w-4 h-4" />
336- </ Button >
337- </ div >
281+ < div className = "flex-1 h-full flex flex-col relative z-10 w-full min-w-0" >
282+ { /* Header - simplified: sidebar toggle + new chat */ }
283+ < div className = "flex items-center justify-between p-3 border-b border-border flex-none bg-background z-20 w-full" >
284+ < Button
285+ variant = "ghost"
286+ size = "icon"
287+ onClick = { ( ) => setSidebarOpen ( ! sidebarOpen ) }
288+ className = "h-8 w-8 text-muted-foreground hover:text-foreground"
289+ >
290+ < SidebarSimple className = "w-4 h-4" />
291+ </ Button >
292+
293+ < Button
294+ variant = "ghost"
295+ size = "icon"
296+ onClick = { handleNewChat }
297+ className = "h-8 w-8 text-muted-foreground hover:text-foreground"
298+ >
299+ < PlusCircle className = "w-4 h-4" />
300+ </ Button >
338301 </ div >
339302
340303 { /* Conversation Area */ }
@@ -345,7 +308,7 @@ export default function ChatPage() {
345308 < ConversationEmptyState
346309 icon = { < Brain className = "w-12 h-12 text-muted-foreground/50" weight = "duotone" /> }
347310 title = "Start a conversation"
348- description = "Ask anything, analyze data, or generate ideas. Aspendos is here to help."
311+ description = "Ask anything, analyze data, or generate ideas. YULA is here to help."
349312 />
350313 ) : (
351314 allMessages . map ( ( msg , index ) => (
@@ -354,7 +317,6 @@ export default function ChatPage() {
354317 message = { { id : msg . id , content : msg . content , role : msg . role } }
355318 >
356319 < Message from = { msg . role } >
357- { /* Show reasoning for assistant messages if available */ }
358320 { msg . role === 'assistant' && msg . decision ?. reasoning && (
359321 < Reasoning
360322 isStreaming = {
@@ -395,7 +357,7 @@ export default function ChatPage() {
395357 < div className = "p-4 flex-none z-20 max-w-3xl mx-auto w-full" >
396358 < PromptInput
397359 onSubmit = { handleSubmit }
398- className = "shadow-xl "
360+ className = "border border-border rounded-2xl "
399361 >
400362 < PromptInputHeader >
401363 < PromptInputAttachments >
@@ -411,7 +373,6 @@ export default function ChatPage() {
411373 < PromptInputActionMenuTrigger />
412374 < PromptInputActionMenuContent >
413375 < PromptInputActionAddAttachments />
414- { /* Add more actions like shortcuts later */ }
415376 </ PromptInputActionMenuContent >
416377 </ PromptInputActionMenu >
417378 < PromptInputButton
@@ -423,7 +384,7 @@ export default function ChatPage() {
423384 < GlobeIcon size = { 16 } />
424385 < span className = "text-xs" > Search</ span >
425386 </ PromptInputButton >
426- { /* Model Selector in input */ }
387+ { /* Model Selector in input footer */ }
427388 < PromptInputSelect
428389 value = { model }
429390 onValueChange = { handleModelChange }
@@ -444,21 +405,11 @@ export default function ChatPage() {
444405 </ PromptInputFooter >
445406 </ PromptInput >
446407 < div className = "text-center mt-2 text-xs text-muted-foreground" >
447- Aspendos can make mistakes. Check important info.
408+ YULA can make mistakes. Check important info.
448409 </ div >
449410 </ div >
450411 </ div >
451412
452- { /* Memory Panel */ }
453- < div
454- className = { cn (
455- 'h-full border-l border-zinc-200 dark:border-zinc-900 bg-white/50 dark:bg-zinc-950/50 backdrop-blur transition-all duration-300 z-20' ,
456- memoryOpen ? 'w-80' : 'w-0 overflow-hidden'
457- ) }
458- >
459- < MemoryPanel />
460- </ div >
461-
462413 { /* Keyboard Shortcuts Panel */ }
463414 < KeyboardShortcuts />
464415
0 commit comments