1- import { useSendMessage , useSubmitClarification } from '../../hooks/useChat' ;
1+ import { useEffect } from 'react' ;
2+ import { useSendMessage , useSubmitClarification , useChatSession } from '../../hooks/useChat' ;
23import { useChatStore } from '../../stores/chatStore' ;
34import { getErrorMessage } from '../../lib/api' ;
45import type { ChatResponse } from '../../types/chat' ;
56import { MessageList } from './MessageList' ;
67import { ChatInput } from './ChatInput' ;
8+ import { Button } from '../ui/button' ;
9+ import { RefreshCcw } from 'lucide-react' ;
10+ import type { AxiosError } from 'axios' ;
711
812export function ChatInterface ( ) {
9- const { addMessage, sessionId, setSessionId } = useChatStore ( ) ;
13+ const { addMessage, sessionId, setSessionId, clearMessages, messages } = useChatStore ( ) ;
14+
15+ // Use the session query to verify if the backend still remembers this session
16+ const {
17+ isError : isSessionError ,
18+ isFetching : isFetchingSession ,
19+ error : sessionError ,
20+ } = useChatSession ( sessionId ) ;
21+
22+ // If the backend session doesn't exist (example: server restarted), wipe the local storage and start fresh
23+ useEffect ( ( ) => {
24+ if ( ! isSessionError ) return ;
1025
26+ const status = ( sessionError as AxiosError | null | undefined ) ?. response ?. status ;
27+ if ( status === 404 ) {
28+ clearMessages ( ) ;
29+ addMessage ( {
30+ role : 'assistant' ,
31+ content : "Oops! It looks like your previous session expired. Let's start a brand new plan! Where would you like to go?"
32+ } ) ;
33+ }
34+ } , [ isSessionError , sessionError , clearMessages , addMessage ] ) ;
35+
1136 const sendMessageMutation = useSendMessage ( ) ;
1237 const submitClarificationMutation = useSubmitClarification ( ) ;
1338
39+ const handleResetSession = ( ) => {
40+ const hasPendingRequest = sendMessageMutation . isPending || submitClarificationMutation . isPending ;
41+ if ( hasPendingRequest ) {
42+ window . alert ( 'Please wait for the current response to finish before starting a new trip plan.' ) ;
43+ return ;
44+ }
45+
46+ if ( window . confirm ( "Are you sure you want to start a new trip plan? This will clear your current conversation." ) ) {
47+ clearMessages ( ) ;
48+ }
49+ } ;
50+
1451 const formatAnswer = ( answer : unknown ) : string => {
1552 if ( typeof answer === 'string' ) return answer ;
1653 if ( typeof answer === 'number' || typeof answer === 'boolean' ) return String ( answer ) ;
@@ -33,15 +70,15 @@ export function ChatInterface() {
3370
3471 const handleSend = async ( userMessage : string ) => {
3572 addMessage ( { role : 'user' , content : userMessage } ) ;
36-
73+
3774 try {
3875 const response = await sendMessageMutation . mutateAsync ( {
3976 message : userMessage ,
4077 session_id : sessionId || undefined ,
4178 } ) ;
4279 handleProcessResponse ( response ) ;
4380 } catch ( error : unknown ) {
44- addMessage ( { role : 'assistant' , content : `Sorry, an error occurred: ${ getErrorMessage ( error ) } ` } ) ;
81+ addMessage ( { role : 'assistant' , content : `Sorry, an error occurred: ${ getErrorMessage ( error ) } ` } ) ;
4582 }
4683 } ;
4784
@@ -57,25 +94,40 @@ export function ChatInterface() {
5794 } ) ;
5895 handleProcessResponse ( response ) ;
5996 } catch ( error : unknown ) {
60- addMessage ( { role : 'assistant' , content : `Sorry, an error occurred: ${ getErrorMessage ( error ) } ` } ) ;
97+ addMessage ( { role : 'assistant' , content : `Sorry, an error occurred: ${ getErrorMessage ( error ) } ` } ) ;
6198 }
6299 } ;
63100
64- const isPending = sendMessageMutation . isPending || submitClarificationMutation . isPending ;
65- const error = ( sendMessageMutation . isError || submitClarificationMutation . isError )
66- ? getErrorMessage ( sendMessageMutation . error ?? submitClarificationMutation . error )
101+ const isPending = sendMessageMutation . isPending || submitClarificationMutation . isPending || isFetchingSession ;
102+ const error = ( sendMessageMutation . isError || submitClarificationMutation . isError )
103+ ? getErrorMessage ( sendMessageMutation . error ?? submitClarificationMutation . error )
67104 : null ;
68105
69106 return (
70107 < >
71- < MessageList
108+ { /* Temporary place of Start New Plan btn until we have a finalized UI/UX design for session management */ }
109+ { messages . length > 0 && (
110+ < div className = "absolute top-4 right-4 z-20" >
111+ < Button
112+ variant = "ghost"
113+ size = "sm"
114+ onClick = { handleResetSession }
115+ className = "text-muted-foreground hover:text-destructive text-xs flex items-center gap-1.5"
116+ >
117+ < RefreshCcw className = "w-3.5 h-3.5" />
118+ Start New Plan
119+ </ Button >
120+ </ div >
121+ ) }
122+
123+ < MessageList
72124 isPending = { isPending }
73- error = { error }
74- onAnswerQuestion = { handleAnswerQuestion }
125+ error = { error }
126+ onAnswerQuestion = { handleAnswerQuestion }
75127 />
76- < ChatInput
77- onSend = { handleSend }
78- isPending = { isPending }
128+ < ChatInput
129+ onSend = { handleSend }
130+ isPending = { isPending }
79131 />
80132 </ >
81133 ) ;
0 commit comments