Spaces:
Sleeping
Sleeping
File size: 6,862 Bytes
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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | import React from 'react';
import { Send, User, Bot } from 'lucide-react';
import InsuCompassLogo from '../../assets/InsuCompass_Logo.png';
import ReactMarkdown from 'react-markdown';
import { useChatInterface } from './useChatInterface';
import { Plan, UserProfile } from '../../interface';
const PlanCard: React.FC<{ plan: Plan }> = ({ plan }) => (
<div className="bg-white border border-gray-200 rounded-2xl shadow-sm p-6 hover:shadow-lg transition">
<h3 className="text-xl font-semibold text-gray-900">{plan.plan_name}</h3>
<p className="text-sm text-gray-600 mb-2">{plan.plan_type}</p>
<p className="text-sm italic text-gray-700 mb-4">{plan.reasoning}</p>
<p className="text-sm font-medium text-gray-800 mb-2">
Estimated Premium: {plan.estimated_premium}
</p>
<ul className="list-disc list-inside space-y-1 text-sm text-gray-700">
{plan.key_features.map((feat, i) => (
<li key={i}>{feat}</li>
))}
</ul>
</div>
);
interface ChatInterfaceScreenProps {
userProfile: UserProfile;
}
const ChatInterfaceScreen: React.FC<ChatInterfaceScreenProps> = ({ userProfile }) => {
const {
chatHistory,
isLoading,
currentMessage,
setCurrentMessage,
handleSendMessage,
showPlanRecs,
chatEndRef,
inputRef
} = useChatInterface(userProfile);
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 via-white to-indigo-50 flex flex-col">
{/* Header */}
<div className="fixed top-0 left-0 w-full bg-white shadow-sm border-b z-50">
<div className="max-w-10xl mx-auto px-6 py-4">
<div className="flex items-center space-x-3">
<img src={InsuCompassLogo} alt="InsuCompass Logo" className="h-12 w-auto" />
<div>
<h1 className="text-2xl font-bold text-gray-900">InsuCompass</h1>
<p className="text-sm text-gray-600">Chat with your AI insurance advisor</p>
</div>
</div>
</div>
</div>
{/* Chat Messages */}
<div className="flex-1 overflow-y-auto pt-20">
<div className="max-w-4xl mx-auto px-6 py-8">
<div className="space-y-6">
{chatHistory.map((message, index) => (
<div
key={index}
className={`flex ${message.role === 'user' ? 'justify-end' : 'justify-start'}`}
>
<div className={`flex items-start space-x-3 max-w-3xl ${message.role === 'user' ? 'flex-row-reverse space-x-reverse' : ''}`}>
{/* Avatar */}
<div className={`w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 ${
message.role === 'user'
? 'bg-blue-500 text-white'
: 'bg-gradient-to-r from-purple-500 to-pink-500 text-white'
}`}>
{message.role === 'user' ? (
<User className="w-5 h-5" />
) : (
<Bot className="w-5 h-5" />
)}
</div>
{/* Message Bubble */}
<div className={`px-6 py-4 rounded-2xl shadow-sm ${
message.role === 'user'
? 'bg-blue-500 text-white rounded-tr-sm'
: 'bg-white text-gray-900 rounded-tl-sm border border-gray-200'
}`}>
<div className="text-sm font-medium mb-1 opacity-75">
{message.role === 'user' ? 'You' : 'InsuCompass AI'}
</div>
<ReactMarkdown className="prose prose-sm max-w-none prose-table:border prose-table:border-gray-300 prose-th:bg-gray-100 prose-th:p-2 prose-td:p-2 prose-td:border prose-td:border-gray-300">
{message.content}
</ReactMarkdown>
{showPlanRecs && message.plans?.length && (
<>
<h2 className="text-2xl font-bold text-gray-900">Recommended Plans for You</h2>
<div className="grid md:grid-cols-2 gap-6">
{message.plans?.map((plan, idx) => (
<PlanCard key={idx} plan={plan} />
))}
</div>
</>
)}
</div>
</div>
</div>
))}
{/* Loading indicator */}
{isLoading && (
<div className="flex justify-start">
<div className="flex items-start space-x-3">
<div className="w-10 h-10 rounded-full bg-gradient-to-r from-purple-500 to-pink-500 text-white flex items-center justify-center">
<Bot className="w-5 h-5" />
</div>
<div className="bg-white px-6 py-4 rounded-2xl rounded-tl-sm border border-gray-200">
<div className="flex space-x-2">
<div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce"></div>
<div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '0.1s' }}></div>
<div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '0.2s' }}></div>
</div>
</div>
</div>
</div>
)}
<div ref={chatEndRef} />
</div>
</div>
</div>
{/* Message Input */}
<div className="bg-white border-t border-gray-200 p-4">
<div className="max-w-4xl mx-auto">
<div className="flex items-center space-x-4">
<div className="flex-1 relative">
<input
ref={inputRef}
type="text"
value={currentMessage}
onChange={(e) => setCurrentMessage(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && handleSendMessage()}
placeholder="Type your message..."
className="w-full px-4 py-3 pr-12 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors"
disabled={isLoading}
/>
<button
onClick={handleSendMessage}
disabled={isLoading || !currentMessage.trim()}
className="absolute right-2 top-1/2 transform -translate-y-1/2 p-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
<Send className="w-4 h-4" />
</button>
</div>
</div>
</div>
</div>
</div>
);
};
export default ChatInterfaceScreen; |