Spaces:
Sleeping
Sleeping
File size: 4,099 Bytes
66f3298 ffa2991 66f3298 ffa2991 66f3298 ffa2991 66f3298 ffa2991 66f3298 ffa2991 66f3298 ffa2991 66f3298 ffa2991 66f3298 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | import { useState, useEffect, useRef } from 'react';
import { ApiResponse, ChatMessage, UserProfile } from '../../interface';
import { CHAT_ENDPOINT } from '../../endpoint';
export function useChatInterface(userProfile: UserProfile, isProfileComplete?: boolean) {
const [chatHistory, setChatHistory] = useState<ChatMessage[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [currentMessage, setCurrentMessage] = useState('');
const [showPlanRecs, setShowPlanRecs] = useState<boolean>(false);
const chatEndRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
// threadId is generated once per chat session and persists for the hook's lifetime
const [threadId] = useState(() => crypto.randomUUID());
useEffect(() => {
chatEndRef.current?.scrollIntoView({ behavior: 'smooth' });
// Focus input after chatHistory changes (i.e., after response is rendered)
if (inputRef.current) {
inputRef.current.focus();
}
}, [chatHistory]);
// Prevent double API call: only send initial chat message once when userProfile is complete
const hasSentInitialMessage = useRef(false);
useEffect(() => {
// TODO: review this logic
// Check if userProfile is complete before sending initial message
const isValidProfile = !!userProfile &&
userProfile?.zip_code?.length && userProfile?.zip_code?.length > 0 &&
!!userProfile.age && userProfile.age > 0 &&
!!userProfile.gender && userProfile.gender.length > 0 &&
!!userProfile.household_size &&
!!userProfile.income &&
!!userProfile.employment_status &&
!!userProfile.citizenship;
if (isValidProfile && !hasSentInitialMessage.current) {
sendChatMessage('START_PROFILE_BUILDING', userProfile);
hasSentInitialMessage.current = true;
}
}, [userProfile]);
const sendChatMessage = async (
message: string,
profileOverride?: UserProfile
) => {
setIsLoading(true);
try {
const payload = {
thread_id: threadId,
user_profile: profileOverride ?? userProfile,
message,
is_profile_complete: isProfileComplete ?? false,
conversation_history: chatHistory.map(m => `${m.role}: ${m.content}`)
};
const response = await fetch(CHAT_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (!response.ok) throw new Error('Failed to send message');
const data: ApiResponse = await response.json();
// Only append the agent's message to the existing chatHistory
const agentMsgRaw = data.updated_history[data.updated_history.length - 1] || '';
const agentMsgContent = agentMsgRaw.replace(/^Agent:\s*/, '');
const agentMessage: ChatMessage = {
role: 'agent',
content: agentMsgContent,
timestamp: Date.now(),
plans: !showPlanRecs && data.plan_recommendations?.recommendations?.length && data.plan_recommendations?.recommendations?.length > 0 ? data.plan_recommendations.recommendations : undefined
};
setChatHistory(prev => [...prev, agentMessage]);
if (!showPlanRecs && data.plan_recommendations?.recommendations?.length && data.plan_recommendations?.recommendations?.length > 0) {
setShowPlanRecs(true);
}
return data;
} catch (error) {
console.error('Error sending message:', error);
} finally {
setIsLoading(false);
}
};
const handleSendMessage = async () => {
if (!currentMessage.trim()) return;
// Add user message to chat immediately
const userMessage: ChatMessage = {
role: 'user',
content: currentMessage,
timestamp: Date.now()
};
setChatHistory(prev => [...prev, userMessage]);
const messageToSend = currentMessage;
setCurrentMessage('');
await sendChatMessage(messageToSend);
};
return {
chatHistory,
isLoading,
currentMessage,
setCurrentMessage,
handleSendMessage,
showPlanRecs,
chatEndRef,
inputRef,
sendChatMessage
};
}
|