Ram2005's picture
Upload frontend/src/components/ChatWidget.jsx
2a548b8 verified
import React, { useState, useRef, useEffect } from 'react'
const SUGGESTIONS = [
"What are the top fintech unicorns?",
"Tell me about SaaS startups in Bangalore",
"What is DPIIT recognition?",
"Which sectors are growing fastest?",
"Compare edtech vs healthtech",
]
export default function ChatWidget({ onClose }) {
const [messages, setMessages] = useState([
{ role: 'assistant', content: '👋 Hi! I\'m Bharat Tech Atlas AI. Ask me about Indian startups, sectors, funding trends, or any company!' }
])
const [input, setInput] = useState('')
const [loading, setLoading] = useState(false)
const scrollRef = useRef(null)
useEffect(() => {
scrollRef.current?.scrollIntoView({ behavior: 'smooth' })
}, [messages])
const sendMessage = async (text) => {
if (!text.trim() || loading) return
const userMsg = { role: 'user', content: text }
setMessages(prev => [...prev, userMsg])
setInput('')
setLoading(true)
try {
const resp = await fetch('/api/chat/completions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages: [...messages, userMsg].map(m => ({ role: m.role, content: m.content })) }),
})
const data = await resp.json()
setMessages(prev => [...prev, { role: 'assistant', content: data.content || 'Sorry, I had trouble responding.' }])
} catch (err) {
setMessages(prev => [...prev, { role: 'assistant', content: '⚠️ Network error. Please try again.' }])
} finally {
setLoading(false)
}
}
return (
<div className="fixed bottom-4 right-4 z-50 w-[380px] max-w-[calc(100vw-2rem)] h-[520px] max-h-[calc(100vh-2rem)] bg-atlas-bg border border-atlas-border rounded-2xl shadow-2xl flex flex-col overflow-hidden">
{/* Header */}
<div className="flex items-center justify-between px-4 py-3 border-b border-atlas-border bg-atlas-surface">
<div className="flex items-center gap-2">
<span className="text-lg">🤖</span>
<div>
<h3 className="text-sm font-semibold text-atlas-text">Bharat Tech Atlas AI</h3>
<p className="text-[10px] text-atlas-muted">Powered by Qwen2.5-0.5B</p>
</div>
</div>
<button onClick={onClose} className="text-atlas-muted hover:text-atlas-text text-lg"></button>
</div>
{/* Messages */}
<div className="flex-1 overflow-y-auto p-3 space-y-3">
{messages.map((m, i) => (
<div key={i} className={`flex ${m.role === 'user' ? 'justify-end' : 'justify-start'}`}>
<div className={`max-w-[85%] rounded-xl px-3 py-2 text-xs leading-relaxed ${
m.role === 'user'
? 'bg-brand-500/20 text-brand-300 rounded-br-none'
: 'bg-atlas-surface text-atlas-muted rounded-bl-none'
}`}>
{m.content}
</div>
</div>
))}
{loading && (
<div className="flex justify-start">
<div className="bg-atlas-surface rounded-xl rounded-bl-none px-3 py-2">
<div className="flex gap-1">
<span className="w-1.5 h-1.5 bg-atlas-muted rounded-full animate-bounce" style={{ animationDelay: '0ms' }} />
<span className="w-1.5 h-1.5 bg-atlas-muted rounded-full animate-bounce" style={{ animationDelay: '150ms' }} />
<span className="w-1.5 h-1.5 bg-atlas-muted rounded-full animate-bounce" style={{ animationDelay: '300ms' }} />
</div>
</div>
</div>
)}
<div ref={scrollRef} />
</div>
{/* Suggestions (only show when few messages) */}
{messages.length < 3 && (
<div className="px-3 pb-2 flex flex-wrap gap-1.5">
{SUGGESTIONS.map(s => (
<button key={s} onClick={() => sendMessage(s)}
className="text-[10px] px-2 py-1 rounded-full bg-atlas-surface border border-atlas-border text-atlas-muted hover:text-atlas-text hover:border-brand-500/30 transition-colors">
{s}
</button>
))}
</div>
)}
{/* Input */}
<div className="px-3 py-2 border-t border-atlas-border flex gap-2">
<input
value={input}
onChange={e => setInput(e.target.value)}
onKeyDown={e => e.key === 'Enter' && sendMessage(input)}
placeholder="Ask about startups, sectors, funding..."
className="flex-1 bg-atlas-surface border border-atlas-border rounded-lg px-3 py-2 text-xs text-atlas-text placeholder:text-atlas-muted/50 focus:outline-none focus:border-brand-500/50"
/>
<button onClick={() => sendMessage(input)} disabled={loading || !input.trim()}
className="px-3 py-2 bg-brand-500/20 text-brand-400 rounded-lg text-xs font-medium hover:bg-brand-500/30 disabled:opacity-30 transition-colors">
Send
</button>
</div>
</div>
)
}