krona-front/src/features/ai/AiCenterModule.tsx

182 lines
8.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState } from 'react';
import { Badge } from '../../shared/components/Badge';
import { Button } from '../../shared/components/Button';
import { Sparkles, Bot, Brain, Send, Cpu, CheckCircle2, Shield, Activity } from 'lucide-react';
interface AiAgent {
id: string;
name: string;
role: string;
description: string;
tools: string[];
status: 'active' | 'busy' | 'idle';
tasksCompleted: number;
}
const AI_AGENTS: AiAgent[] = [
{
id: 'orch',
name: 'Главный Оркестратор',
role: 'Orchestrator',
description: 'Декомпозирует глобальные бизнес-цели и распределяет задачи между агентами-специалистами',
tools: ['Task Delegator', 'Cross-module Context', 'Guardian Policy'],
status: 'active',
tasksCompleted: 342,
},
{
id: 'analyst',
name: 'Бизнес-аналитик',
role: 'BI & Financial Analyst',
description: 'Анализирует чеки, food cost, маржинальность, динамику продаж и выявляет аномалии',
tools: ['SQL Query', 'Revenue Forecast', 'ABC Matrix', 'Shift Audit'],
status: 'active',
tasksCompleted: 819,
},
{
id: 'marketer',
name: 'Бизнес-маркетолог',
role: 'Growth & Retention',
description: 'Генерирует контент-планы, офферы для рассылок, анализирует сегменты клиентов в зоне риска',
tools: ['Promo Engine', 'Telegram Bot Sender', 'Copywriter', 'Cohort Analysis'],
status: 'active',
tasksCompleted: 420,
},
{
id: 'warehouse_agent',
name: 'Складской су-шеф',
role: 'Supply Chain Agent',
description: 'Мониторит критические остатки, сроки годности и формирует авто-заказы поставщикам',
tools: ['Supplier Auto-Order', 'Waste Tracker', 'Inventory Audit'],
status: 'active',
tasksCompleted: 612,
},
];
export const AiCenterModule: React.FC = () => {
const [activeAgentId, setActiveAgentId] = useState<string>('orch');
const [chatMessages, setChatMessages] = useState<{ sender: 'user' | 'ai'; text: string; time: string }[]>([
{
sender: 'ai',
text: 'Здравствуйте! Я Главный Оркестратор Кроны. Моя команда специалистов (Аналитик, Маркетолог, Склад) готова помочь вам оптимизировать операционные процессы, снизить списания и поднять средний чек.',
time: '12:00',
},
]);
const [prompt, setPrompt] = useState('');
const handleSend = (e: React.FormEvent) => {
e.preventDefault();
if (!prompt.trim()) return;
const userText = prompt;
setChatMessages((prev) => [
...prev,
{ sender: 'user', text: userText, time: 'Только что' },
]);
setPrompt('');
setTimeout(() => {
setChatMessages((prev) => [
...prev,
{
sender: 'ai',
text: `Агент «${AI_AGENTS.find(a => a.id === activeAgentId)?.name}»: Анализ запроса «${userText}» завершен. Сформирован проект решения в задачах. Выручка и себестоимость учтены в сводном отчете.`,
time: 'Только что',
},
]);
}, 450);
};
return (
<div className="space-y-4 animate-fade-in">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-3 bg-krona-surface p-3.5 rounded-xl border border-krona-border shadow-krona-soft">
<div>
<div className="flex items-center gap-2">
<h2 className="text-sm font-bold text-krona-primary">
✦ Krona AI Center & Автономная бизнес-команда
</h2>
<Badge variant="gold" size="sm">Крона Модель v1.8 Flash</Badge>
</div>
<p className="text-xs text-krona-secondary mt-0.5">
Специализированные агенты с прямым доступом к инструментам платформы и памяти заведения
</p>
</div>
<div className="flex items-center gap-2">
<Badge variant="green" size="md">Токены: 48 200 / 100 000</Badge>
</div>
</div>
{/* Agents Selection Cards */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3.5">
{AI_AGENTS.map((agent) => (
<div
key={agent.id}
onClick={() => setActiveAgentId(agent.id)}
className={`p-4 rounded-xl border cursor-pointer transition-all shadow-krona-soft flex flex-col justify-between space-y-2.5 ${
agent.id === activeAgentId
? 'border-krona-gold bg-krona-gold/10 ring-2 ring-krona-gold/20'
: 'border-krona-border bg-krona-surface hover:border-krona-border-strong'
}`}
>
<div>
<div className="flex items-center justify-between mb-1.5">
<span className="text-[10px] uppercase font-bold text-krona-secondary">{agent.role}</span>
<span className="w-2 h-2 rounded-full bg-krona-green animate-pulse"></span>
</div>
<h4 className="text-xs font-bold text-krona-primary">{agent.name}</h4>
<p className="text-[11px] text-krona-secondary line-clamp-2 mt-1">{agent.description}</p>
</div>
<div className="pt-2 border-t border-krona-border/50 text-[10px] text-krona-secondary flex items-center justify-between">
<span>Инструментов: {agent.tools.length}</span>
<span className="font-semibold text-krona-primary">{agent.tasksCompleted} задач</span>
</div>
</div>
))}
</div>
{/* Interactive AI Dialog Box */}
<div className="bg-krona-surface border border-krona-border rounded-xl p-4 shadow-krona-soft space-y-3">
<div className="flex items-center justify-between pb-2 border-b border-krona-border">
<div className="flex items-center gap-2">
<Bot className="w-4 h-4 text-krona-gold" />
<span className="text-xs font-bold text-krona-primary">
Диалог с агентом: {AI_AGENTS.find(a => a.id === activeAgentId)?.name}
</span>
</div>
<Badge variant="gold" size="sm">Контекст синхронизирован</Badge>
</div>
<div className="h-64 overflow-y-auto space-y-2.5 p-2 text-xs">
{chatMessages.map((m, i) => (
<div
key={i}
className={`p-3 rounded-xl max-w-xl ${
m.sender === 'user'
? 'ml-auto bg-[#2F684C] text-white rounded-br-none'
: 'mr-auto bg-krona-workspace border border-krona-border text-krona-primary rounded-bl-none shadow-krona-soft'
}`}
>
<p className="leading-relaxed">{m.text}</p>
<span className="block text-[9px] mt-1 opacity-70 text-right">{m.time}</span>
</div>
))}
</div>
<form onSubmit={handleSend} className="flex gap-2 pt-2 border-t border-krona-border">
<input
type="text"
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
placeholder="Сформулируйте задачу для агента (например: 'Оптимизируй закупку лосося')..."
className="flex-1 bg-krona-workspace border border-krona-border rounded-lg px-3 py-2 text-xs text-krona-primary placeholder:text-krona-secondary focus:outline-none focus:border-krona-gold"
/>
<Button type="submit" variant="gold" size="sm">
<Send className="w-3.5 h-3.5 mr-1" />
Отправить в работу
</Button>
</form>
</div>
</div>
);
};