Spaces:
Sleeping
Sleeping
File size: 2,885 Bytes
2f884df 49d76de 2f884df | 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 | import React, { useState } from 'react';
import { useChat } from 'ai/react';
import { MessageCircle, X, Send, Loader2, Bot } from 'lucide-react';
export default function ChatWidget() {
const [isOpen, setIsOpen] = useState(false);
// Ссылка берется из настроек Space или .env файла
const apiEndpoint = "https://levinaleksey-chat-b.hf.space/api/chat";
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
api: apiEndpoint,
});
return (
<div className="fixed bottom-6 right-6 z-50 font-sans">
{isOpen && (
<div className="mb-4 w-[380px] h-[550px] bg-white rounded-3xl shadow-[0_20px_50px_rgba(0,0,0,0.15)] border border-slate-100 flex flex-col overflow-hidden animate-in fade-in zoom-in duration-200">
<div className="bg-slate-900 p-5 text-white flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="bg-blue-600 p-2 rounded-xl"><Bot size={20} /></div>
<div>
<p className="font-semibold text-sm">Inventory AI</p>
<p className="text-[10px] text-slate-400">Gemini 1.5 Flash Online</p>
</div>
</div>
<button onClick={() => setIsOpen(false)} className="opacity-50 hover:opacity-100"><X size={20} /></button>
</div>
<div className="flex-1 overflow-y-auto p-4 space-y-4 bg-slate-50">
{messages.map((m) => (
<div key={m.id} className={`flex ${m.role === 'user' ? 'justify-end' : 'justify-start'}`}>
<div className={`max-w-[85%] px-4 py-2 rounded-2xl text-sm ${
m.role === 'user' ? 'bg-blue-600 text-white' : 'bg-white border border-slate-200 text-slate-800'
}`}>
{m.content}
</div>
</div>
))}
{isLoading && <Loader2 className="animate-spin text-blue-600 mx-auto" size={20} />}
</div>
<form onSubmit={handleSubmit} className="p-4 bg-white border-t border-slate-100 flex gap-2">
<input
className="flex-1 bg-slate-100 rounded-xl px-4 py-2 text-sm outline-none focus:ring-2 focus:ring-blue-500"
value={input}
placeholder="Спросите об оборудовании..."
onChange={handleInputChange}
/>
<button type="submit" className="bg-slate-900 text-white p-2 rounded-xl"><Send size={18} /></button>
</form>
</div>
)}
<button
onClick={() => setIsOpen(!isOpen)}
className="bg-slate-900 text-white w-16 h-16 rounded-full shadow-2xl flex items-center justify-center hover:scale-105 transition-transform"
>
{isOpen ? <X size={28} /> : <MessageCircle size={28} />}
</button>
</div>
);
} |