import React, { useMemo } from 'react'; import { Inbox, Clock, CheckCircle2, AlertTriangle, TrendingUp, Activity, Users, Zap } from 'lucide-react'; import { DomaApplication } from '../../types'; interface Props { applications: DomaApplication[]; onNavigate: (tab: any) => void; } export const AppSummary: React.FC = ({ applications, onNavigate }) => { // Используем поле isOverdue из БД, если есть, иначе вычисляем const stats = { new: applications.filter(a => a.status === 'new').length, inProgress: applications.filter(a => a.status === 'in_progress').length, deferred: applications.filter(a => a.status === 'deferred').length, done: applications.filter(a => a.status === 'done').length, overdue: applications.filter(a => a.isOverdue !== undefined ? a.isOverdue : (a.status !== 'done' && a.status !== 'canceled' && new Date(a.deadlineAt) < new Date()) ).length }; const totalActive = stats.new + stats.inProgress + stats.deferred; const completionRate = applications.length > 0 ? Math.round((stats.done / (stats.done + totalActive)) * 100) : 0; // Группируем заявки по исполнителям для "Загрузка мастеров" const performerStats = useMemo(() => { const map = new Map(); applications.forEach(app => { if (app.performer?.name && app.status !== 'done' && app.status !== 'canceled') { const count = map.get(app.performer.name) || 0; map.set(app.performer.name, count + 1); } }); return Array.from(map.entries()) .map(([name, count]) => ({ name, count })) .sort((a, b) => b.count - a.count) .slice(0, 4); // Топ-4 исполнителя }, [applications]); return (
{/* Real-time KPI Cards */}
onNavigate('registry')} /> onNavigate('registry')} /> onNavigate('registry')} /> onNavigate('control')} />
{/* Main Progress Widget */}

Производительность

Эффективность закрытия заявок за сегодня

{completionRate}%

Индекс SLA

0 ? Math.round((stats.new / applications.length) * 100) : 0} color="bg-red-500" /> 0 ? Math.round((stats.inProgress / applications.length) * 100) : 0} color="bg-blue-500" />
{/* Performer Load */}

Загрузка мастеров

{performerStats.length > 0 ? ( performerStats.map((perf, idx) => ( 5} /> )) ) : (

Нет активных заявок

)}
); }; const StatCard = ({ icon: Icon, label, value, color, bg, onClick }: any) => (
{value > 5 && label === 'Новые' && }

{value}

{label}

); const StatusLine = ({ label, value, color }: any) => (
{label} {value}%
); const PerformerItem = ({ name, count, warning }: any) => (
{name} {count} заяв.
);