import React, { useState, useEffect, useRef } from "react"; import { Send, Moon, Sun, User, Bot, AlertCircle, CheckCircle, Clock, Heart, Phone, Calendar, MapPin, FileText, } from "lucide-react"; import { apiService } from "./services/apiService"; const MedicalChatUI = () => { // UI State const [isDarkMode, setIsDarkMode] = useState(false); const [currentMessage, setCurrentMessage] = useState(""); const [messages, setMessages] = useState([]); const [isTyping, setIsTyping] = useState(false); const [isConnected, setIsConnected] = useState(false); const [connectionError, setConnectionError] = useState(""); // Patient Data State const [patientRecord, setPatientRecord] = useState({ personal_info: { full_name: "", dob: "", gender: "", phone: "", address: "", }, medical_info: { current_symptoms: [], symptom_start_date: "", previous_medications: [], allergies: [], severity_level: "", }, }); // Session State const [sessionStatus, setSessionStatus] = useState("idle"); // idle | collecting | completed const [confidenceScores, setConfidenceScores] = useState({ extraction: 0, validation: 0, }); const messagesEndRef = useRef(null); // Auto-scroll to bottom const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); }; useEffect(() => { scrollToBottom(); }, [messages]); // Initialize connection and start chat useEffect(() => { initializeChat(); }, []); const initializeChat = async () => { try { // Health check await apiService.healthCheck(); setIsConnected(true); setConnectionError(""); // Start chat session const response = await apiService.startChat(); // Add initial AI message setMessages([ { id: Date.now(), text: response.message, sender: "ai", timestamp: new Date().toISOString(), }, ]); setSessionStatus("collecting"); } catch (error) { setIsConnected(false); setConnectionError(error.message); console.error("Failed to initialize chat:", error); } }; const handleSendMessage = async () => { if (!currentMessage.trim() || isTyping) return; const userMessage = { id: Date.now(), text: currentMessage.trim(), sender: "user", timestamp: new Date().toISOString(), }; // Add user message to chat setMessages((prev) => [...prev, userMessage]); setCurrentMessage(""); setIsTyping(true); try { // Send to backend const response = await apiService.sendMessage(userMessage.text); // Update patient record setPatientRecord(response.patient_record); setConfidenceScores(response.confidence_scores); setSessionStatus(response.session_status); // Add AI response const aiMessage = { id: Date.now() + 1, text: response.ai_message, sender: "ai", timestamp: new Date().toISOString(), metadata: response.metadata, }; setMessages((prev) => [...prev, aiMessage]); // If conversation completed, show completion message if (response.should_end) { setTimeout(() => { const completionMessage = { id: Date.now() + 2, text: "✅ Information collection completed! Click 'Generate Summary' to create a doctor report.", sender: "system", timestamp: new Date().toISOString(), }; setMessages((prev) => [...prev, completionMessage]); }, 1000); } } catch (error) { console.error("Failed to send message:", error); // Add error message const errorMessage = { id: Date.now() + 1, text: `❌ Error: ${error.message}. Please try again.`, sender: "system", timestamp: new Date().toISOString(), }; setMessages((prev) => [...prev, errorMessage]); } finally { setIsTyping(false); } }; const handleGenerateSummary = async () => { try { setIsTyping(true); const summary = await apiService.generateSummary(); const summaryMessage = { id: Date.now(), text: `📋 **Doctor Summary Generated**\n\n**Summary:** ${ summary.doctor_summary }\n\n**Urgency Level:** ${ summary.urgency_level }\n\n**Key Findings:**\n${summary.key_findings .map((f) => `• ${f}`) .join( "\n" )}\n\n**Recommended Questions:**\n${summary.recommended_questions .map((q) => `• ${q}`) .join("\n")}`, sender: "system", timestamp: new Date().toISOString(), }; setMessages((prev) => [...prev, summaryMessage]); } catch (error) { console.error("Failed to generate summary:", error); } finally { setIsTyping(false); } }; const handleResetChat = async () => { try { await apiService.resetSession(); setMessages([]); setPatientRecord({ personal_info: { full_name: "", dob: "", gender: "", phone: "", address: "", }, medical_info: { current_symptoms: [], symptom_start_date: "", previous_medications: [], allergies: [], severity_level: "", }, }); setSessionStatus("idle"); setConfidenceScores({ extraction: 0, validation: 0 }); // Restart chat await initializeChat(); } catch (error) { console.error("Failed to reset chat:", error); } }; // Components const MessageBubble = ({ message }) => { const isUser = message.sender === "user"; const isSystem = message.sender === "system"; return (
{!isUser && (
{isSystem ? ( ) : ( )}
)}
{message.text}
{message.metadata && (
Exchange #{message.metadata.exchange_count} | Confidence:{" "} {(message.metadata.confidence || 0).toFixed(2)}
)}
{isUser && (
)}
); }; const TypingIndicator = () => (
); const PatientPanel = () => (
{/* Header */}

Patient Record

Status: {sessionStatus}
Confidence:{" "} {Math.round( ((confidenceScores.extraction + confidenceScores.validation) / 2) * 100 )} %
{/* Content */}
{/* Personal Information */}

Personal Information

Name:

{patientRecord.personal_info.full_name || "Not provided"}

Date of Birth:

{patientRecord.personal_info.dob || "Not provided"}

Phone:

{patientRecord.personal_info.phone || "Not provided"}

Address:

{patientRecord.personal_info.address || "Not provided"}

{/* Medical Information */}

Medical Information

Symptoms:

{patientRecord.medical_info.current_symptoms?.length > 0 ? patientRecord.medical_info.current_symptoms.join(", ") : "Not provided"}

Duration:

{patientRecord.medical_info.symptom_start_date || "Not provided"}

Severity:

{patientRecord.medical_info.severity_level || "Not assessed"}

Medications:

{patientRecord.medical_info.previous_medications?.length > 0 ? patientRecord.medical_info.previous_medications.join(", ") : "None reported"}

Allergies:

{patientRecord.medical_info.allergies?.length > 0 ? patientRecord.medical_info.allergies.join(", ") : "None reported"}

{/* Actions */}
); // Connection error screen if (!isConnected && connectionError) { return (

Connection Failed

{connectionError}

); } return (
{/* Main Content */}
{/* Header */}

Medical Multi-Agent System

{isConnected ? ( ) : ( )} {isConnected ? "Connected to Qwen 3-4B" : "Disconnected"}
{/* Chat Area */}
{/* Messages */}
{messages.length === 0 && (

Initializing Medical Multi-Agent System...

)} {messages.map((message) => ( ))} {isTyping && }
{/* Input Area */}
setCurrentMessage(e.target.value)} onKeyPress={(e) => e.key === "Enter" && handleSendMessage()} placeholder="Describe your symptoms or provide requested information..." disabled={!isConnected} className={`flex-1 px-4 py-3 rounded-lg border ${ isDarkMode ? "bg-gray-700 border-gray-600 text-gray-200 placeholder-gray-400" : "bg-white border-gray-300 text-gray-900 placeholder-gray-500" } focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:opacity-50`} />
{/* Patient Panel */}
); }; export default MedicalChatUI;