This commit is contained in:
2026-05-17 20:54:53 +05:00
parent 65a0babeab
commit 27eb4fd606
90 changed files with 12343 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
import { FormEvent, useState } from 'react';
import { X, Send, Bot } from 'lucide-react';
interface Msg {
who: 'bot' | 'me';
text: string;
ts: number;
}
const HINT = `Это заглушка чат-бота. Здесь будет интеграция с Telegram/AI.
Можно спрашивать про устройства, настройки, бэкапы.`;
function botReply(q: string): string {
const s = q.toLowerCase();
if (/устройств|devices/.test(s)) return 'Список устройств доступен в разделе "Devices".';
if (/бэкап|backup/.test(s)) return 'Бэкапы создаются на странице устройства, кнопкой "Backup".';
if (/прошив|firmware/.test(s)) return 'Репозиторий прошивок — в левом меню "Прошивки".';
if (/привет|hi|hello/.test(s)) return 'Привет! Чем помочь?';
return 'Ок, принял. (бот пока в режиме заглушки)';
}
interface ChatBotProps {
open?: boolean;
onClose?: () => void;
embedded?: boolean;
}
export default function ChatBot({ open = true, onClose, embedded = false }: ChatBotProps) {
const [msgs, setMsgs] = useState<Msg[]>([
{ who: 'bot', text: HINT, ts: Date.now() },
]);
const [input, setInput] = useState('');
const send = (e: FormEvent) => {
e.preventDefault();
const text = input.trim();
if (!text) return;
const now = Date.now();
setMsgs((m) => [...m, { who: 'me', text, ts: now }]);
setInput('');
setTimeout(() => {
setMsgs((m) => [...m, { who: 'bot', text: botReply(text), ts: Date.now() }]);
}, 350);
};
if (!open) return null;
const wrapperCls = embedded
? 'card p-0 flex flex-col h-[60vh] min-h-[360px]'
: 'fixed bottom-5 left-60 z-40 w-80 h-96 card p-0 flex flex-col shadow-2xl';
return (
<div className={wrapperCls}>
<div className="px-4 py-3 border-b border-mk-border flex items-center gap-2">
<Bot size={18} className="text-mk-accent2" />
<div className="font-medium text-sm">Помощник</div>
<span className="ml-2 text-xs text-mk-mute">beta</span>
{!embedded && onClose && (
<button
onClick={onClose}
className="ml-auto p-1 rounded hover:bg-mk-panel2 text-mk-mute hover:text-mk-text"
aria-label="Закрыть"
>
<X size={16} />
</button>
)}
</div>
<div className="flex-1 overflow-auto p-3 space-y-2 text-sm">
{msgs.map((m, i) => (
<div
key={i}
className={`max-w-[85%] px-3 py-2 rounded-lg whitespace-pre-wrap ${
m.who === 'me'
? 'ml-auto bg-mk-accent/20 text-mk-text'
: 'mr-auto bg-mk-panel2 text-mk-text'
}`}
>
{m.text}
</div>
))}
</div>
<form onSubmit={send} className="p-2 border-t border-mk-border flex gap-2">
<input
className="input"
placeholder="Спросите бота…"
value={input}
onChange={(e) => setInput(e.target.value)}
/>
<button className="btn-primary" type="submit" aria-label="Отправить">
<Send size={14} />
</button>
</form>
</div>
);
}