src/screens/ChatInterfaceScreen/ChatInterfaceScreen.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import React, { useEffect } from 'react';
2
  import { Send, User, Bot } from 'lucide-react';
3
  import InsuCompassLogo from '../../assets/InsuCompass_Logo.png';
4
  import ReactMarkdown from 'react-markdown';
@@ -26,6 +26,7 @@ interface ChatInterfaceScreenProps {
26
  }
27
 
28
  const ChatInterfaceScreen: React.FC<ChatInterfaceScreenProps> = ({ userProfile }) => {
 
29
  const {
30
  chatHistory,
31
  isLoading,
@@ -34,14 +35,9 @@ const ChatInterfaceScreen: React.FC<ChatInterfaceScreenProps> = ({ userProfile }
34
  handleSendMessage,
35
  showPlanRecs,
36
  chatEndRef,
37
- sendChatMessage
38
  } = useChatInterface(userProfile);
39
 
40
- useEffect(() => {
41
- if (chatHistory.length === 0) {
42
- sendChatMessage('START_PROFILE_BUILDING', userProfile);
43
- }
44
- }, [userProfile])
45
  return (
46
  <div className="min-h-screen bg-gradient-to-br from-blue-50 via-white to-indigo-50 flex flex-col">
47
  {/* Header */}
@@ -133,6 +129,7 @@ const ChatInterfaceScreen: React.FC<ChatInterfaceScreenProps> = ({ userProfile }
133
  <div className="flex items-center space-x-4">
134
  <div className="flex-1 relative">
135
  <input
 
136
  type="text"
137
  value={currentMessage}
138
  onChange={(e) => setCurrentMessage(e.target.value)}
 
1
+ import React from 'react';
2
  import { Send, User, Bot } from 'lucide-react';
3
  import InsuCompassLogo from '../../assets/InsuCompass_Logo.png';
4
  import ReactMarkdown from 'react-markdown';
 
26
  }
27
 
28
  const ChatInterfaceScreen: React.FC<ChatInterfaceScreenProps> = ({ userProfile }) => {
29
+
30
  const {
31
  chatHistory,
32
  isLoading,
 
35
  handleSendMessage,
36
  showPlanRecs,
37
  chatEndRef,
38
+ inputRef
39
  } = useChatInterface(userProfile);
40
 
 
 
 
 
 
41
  return (
42
  <div className="min-h-screen bg-gradient-to-br from-blue-50 via-white to-indigo-50 flex flex-col">
43
  {/* Header */}
 
129
  <div className="flex items-center space-x-4">
130
  <div className="flex-1 relative">
131
  <input
132
+ ref={inputRef}
133
  type="text"
134
  value={currentMessage}
135
  onChange={(e) => setCurrentMessage(e.target.value)}
src/screens/ChatInterfaceScreen/useChatInterface.ts CHANGED
@@ -8,13 +8,37 @@ export function useChatInterface(userProfile: UserProfile, isProfileComplete?: b
8
  const [currentMessage, setCurrentMessage] = useState('');
9
  const [showPlanRecs, setShowPlanRecs] = useState<boolean>(false);
10
  const chatEndRef = useRef<HTMLDivElement>(null);
 
11
  // threadId is generated once per chat session and persists for the hook's lifetime
12
  const [threadId] = useState(() => crypto.randomUUID());
13
 
14
  useEffect(() => {
15
  chatEndRef.current?.scrollIntoView({ behavior: 'smooth' });
 
 
 
 
16
  }, [chatHistory]);
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  const sendChatMessage = async (
19
  message: string,
20
  profileOverride?: UserProfile
@@ -35,22 +59,16 @@ export function useChatInterface(userProfile: UserProfile, isProfileComplete?: b
35
  });
36
  if (!response.ok) throw new Error('Failed to send message');
37
  const data: ApiResponse = await response.json();
38
- // Update state from backend response
39
- // let newHistory: ChatMessage[] = data.updated_history.map(msg => {
40
- // const [role, ...contentParts] = msg.split(':');
41
- // return {
42
- // role: role.toLowerCase() as 'user' | 'agent',
43
- // content: contentParts.join(':').trim(),
44
- // timestamp: Date.now()
45
- // };
46
- // });
47
- let newHistory: ChatMessage[] = [...chatHistory, {
48
  role: 'agent',
49
- content: data.updated_history[data.updated_history.length - 1],
50
  timestamp: Date.now(),
51
  plans: !showPlanRecs && data.plan_recommendations?.recommendations?.length && data.plan_recommendations?.recommendations?.length > 0 ? data.plan_recommendations.recommendations : undefined
52
- }];
53
- setChatHistory(newHistory);
54
  if (!showPlanRecs && data.plan_recommendations?.recommendations?.length && data.plan_recommendations?.recommendations?.length > 0) {
55
  setShowPlanRecs(true);
56
  }
@@ -84,6 +102,7 @@ export function useChatInterface(userProfile: UserProfile, isProfileComplete?: b
84
  handleSendMessage,
85
  showPlanRecs,
86
  chatEndRef,
 
87
  sendChatMessage
88
  };
89
  }
 
8
  const [currentMessage, setCurrentMessage] = useState('');
9
  const [showPlanRecs, setShowPlanRecs] = useState<boolean>(false);
10
  const chatEndRef = useRef<HTMLDivElement>(null);
11
+ const inputRef = useRef<HTMLInputElement>(null);
12
  // threadId is generated once per chat session and persists for the hook's lifetime
13
  const [threadId] = useState(() => crypto.randomUUID());
14
 
15
  useEffect(() => {
16
  chatEndRef.current?.scrollIntoView({ behavior: 'smooth' });
17
+ // Focus input after chatHistory changes (i.e., after response is rendered)
18
+ if (inputRef.current) {
19
+ inputRef.current.focus();
20
+ }
21
  }, [chatHistory]);
22
 
23
+ // Prevent double API call: only send initial chat message once when userProfile is complete
24
+ const hasSentInitialMessage = useRef(false);
25
+ useEffect(() => {
26
+ // TODO: review this logic
27
+ // Check if userProfile is complete before sending initial message
28
+ const isValidProfile = !!userProfile &&
29
+ userProfile?.zip_code?.length && userProfile?.zip_code?.length > 0 &&
30
+ !!userProfile.age && userProfile.age > 0 &&
31
+ !!userProfile.gender && userProfile.gender.length > 0 &&
32
+ !!userProfile.household_size &&
33
+ !!userProfile.income &&
34
+ !!userProfile.employment_status &&
35
+ !!userProfile.citizenship;
36
+ if (isValidProfile && !hasSentInitialMessage.current) {
37
+ sendChatMessage('START_PROFILE_BUILDING', userProfile);
38
+ hasSentInitialMessage.current = true;
39
+ }
40
+ }, [userProfile]);
41
+
42
  const sendChatMessage = async (
43
  message: string,
44
  profileOverride?: UserProfile
 
59
  });
60
  if (!response.ok) throw new Error('Failed to send message');
61
  const data: ApiResponse = await response.json();
62
+ // Only append the agent's message to the existing chatHistory
63
+ const agentMsgRaw = data.updated_history[data.updated_history.length - 1] || '';
64
+ const agentMsgContent = agentMsgRaw.replace(/^Agent:\s*/, '');
65
+ const agentMessage: ChatMessage = {
 
 
 
 
 
 
66
  role: 'agent',
67
+ content: agentMsgContent,
68
  timestamp: Date.now(),
69
  plans: !showPlanRecs && data.plan_recommendations?.recommendations?.length && data.plan_recommendations?.recommendations?.length > 0 ? data.plan_recommendations.recommendations : undefined
70
+ };
71
+ setChatHistory(prev => [...prev, agentMessage]);
72
  if (!showPlanRecs && data.plan_recommendations?.recommendations?.length && data.plan_recommendations?.recommendations?.length > 0) {
73
  setShowPlanRecs(true);
74
  }
 
102
  handleSendMessage,
103
  showPlanRecs,
104
  chatEndRef,
105
+ inputRef,
106
  sendChatMessage
107
  };
108
  }