import { useMemo } from 'react'; import { ProductivityMetrics } from '@/services/analytics/analytics'; import { DeadlineMetrics } from '@/services/analytics/deadline-analytics'; import { TagDistributionMetrics } from '@/services/analytics/tag-analytics'; import { CompletionTrendChart } from '@/components/charts/CompletionTrendChart'; import { VelocityChart } from '@/components/charts/VelocityChart'; import { PriorityDistributionChart } from '@/components/charts/PriorityDistributionChart'; import { WeeklyStatsCard } from '@/components/charts/WeeklyStatsCard'; import { TagDistributionChart } from '@/components/dashboard/TagDistributionChart'; import { Card, MetricCard } from '@/components/ui'; import { DeadlineOverview } from '@/components/deadline/DeadlineOverview'; interface ProductivityAnalyticsProps { metrics: ProductivityMetrics; deadlineMetrics: DeadlineMetrics; tagMetrics: TagDistributionMetrics; selectedSources: string[]; hiddenSources?: string[]; } export function ProductivityAnalytics({ metrics, deadlineMetrics, tagMetrics, selectedSources, hiddenSources = [] }: ProductivityAnalyticsProps) { // Filtrer les métriques selon les sources sélectionnées const filteredMetrics = useMemo(() => { if (selectedSources.length === 0) { return metrics; } // Pour les métriques complexes, on garde les données originales // car elles nécessitent un recalcul complet côté serveur // TODO: Implémenter le recalcul côté client ou créer une API return metrics; }, [metrics, selectedSources]); const filteredDeadlineMetrics = useMemo(() => { let filteredOverdue = deadlineMetrics.overdue; let filteredCritical = deadlineMetrics.critical; let filteredWarning = deadlineMetrics.warning; let filteredUpcoming = deadlineMetrics.upcoming; // Si on a des sources sélectionnées, ne garder que celles-ci if (selectedSources.length > 0) { filteredOverdue = filteredOverdue.filter(task => selectedSources.includes(task.source) ); filteredCritical = filteredCritical.filter(task => selectedSources.includes(task.source) ); filteredWarning = filteredWarning.filter(task => selectedSources.includes(task.source) ); filteredUpcoming = filteredUpcoming.filter(task => selectedSources.includes(task.source) ); } else if (hiddenSources.length > 0) { // Sinon, retirer les sources masquées filteredOverdue = filteredOverdue.filter(task => !hiddenSources.includes(task.source) ); filteredCritical = filteredCritical.filter(task => !hiddenSources.includes(task.source) ); filteredWarning = filteredWarning.filter(task => !hiddenSources.includes(task.source) ); filteredUpcoming = filteredUpcoming.filter(task => !hiddenSources.includes(task.source) ); } return { overdue: filteredOverdue, critical: filteredCritical, warning: filteredWarning, upcoming: filteredUpcoming, summary: { overdueCount: filteredOverdue.length, criticalCount: filteredCritical.length, warningCount: filteredWarning.length, upcomingCount: filteredUpcoming.length, totalWithDeadlines: filteredOverdue.length + filteredCritical.length + filteredWarning.length + filteredUpcoming.length } }; }, [deadlineMetrics, selectedSources, hiddenSources]); return (
{/* Section Échéances Critiques */} {/* Titre de section Analytics */}

📊 Analytics & Métriques

Derniers 30 jours
{/* Performance hebdomadaire */} {/* Graphiques principaux */}
{/* Distributions */}
{/* Status Flow - Graphique simple en barres horizontales */}

Répartition par Statut

{filteredMetrics.statusFlow.map((item, index) => (
{item.status}
{item.count}
{item.percentage}%
))}
{/* Distribution par Tags */} {/* Insights automatiques */}

💡 Insights

0 ? Math.round(filteredMetrics.velocityData.reduce((acc, item) => acc + item.completed, 0) / filteredMetrics.velocityData.length) : 0 } tâches/sem`} color="primary" /> item.count > max.count ? item : max, filteredMetrics.priorityDistribution[0] )?.priority || 'N/A'} color="success" /> { const completed = filteredMetrics.statusFlow.find(s => s.status === 'Terminé')?.count || 0; const total = filteredMetrics.statusFlow.reduce((acc, s) => acc + s.count, 0); return total > 0 ? Math.round((completed / total) * 100) : 0; })()}%`} color="warning" />
); }