Files
towercontrol/src/components/deadline/DeadlineRiskCard.tsx
Julien Froidefond fd3827214f feat: update dashboard components and analytics for 7-day summaries
- Modified `ManagerWeeklySummary`, `MetricsTab`, and `ProductivityAnalytics` to reflect a focus on the last 7 days instead of the current week.
- Enhanced `ManagerSummaryService` and `MetricsService` to calculate metrics over a sliding 7-day window, improving data relevance.
- Added a new utility function `formatDistanceToNow` for better date formatting in French.
- Updated comments and documentation to clarify changes in timeframes.
2025-09-23 21:22:59 +02:00

90 lines
3.6 KiB
TypeScript

'use client';
import { DeadlineMetrics, DeadlineAnalyticsService } from '@/services/analytics/deadline-analytics';
import { Card } from '@/components/ui/Card';
interface DeadlineRiskCardProps {
metrics: DeadlineMetrics;
}
export function DeadlineRiskCard({ metrics }: DeadlineRiskCardProps) {
const riskAnalysis = DeadlineAnalyticsService.calculateRiskMetrics(metrics);
const getRiskIcon = (level: string) => {
switch (level) {
case 'critical': return '🔴';
case 'high': return '🟠';
case 'medium': return '🟡';
case 'low': return '🟢';
default: return '⚪';
}
};
const getRiskColor = (level: string) => {
switch (level) {
case 'critical': return 'text-red-600 dark:text-red-400';
case 'high': return 'text-orange-600 dark:text-orange-400';
case 'medium': return 'text-yellow-600 dark:text-yellow-400';
case 'low': return 'text-green-600 dark:text-green-400';
default: return 'text-gray-600 dark:text-gray-400';
}
};
const getRiskBgColor = (level: string) => {
switch (level) {
case 'critical': return 'bg-red-50/30 border-red-200/50 dark:bg-red-950/20 dark:border-red-800/30';
case 'high': return 'bg-orange-50/30 border-orange-200/50 dark:bg-orange-950/20 dark:border-orange-800/30';
case 'medium': return 'bg-yellow-50/30 border-yellow-200/50 dark:bg-yellow-950/20 dark:border-yellow-800/30';
case 'low': return 'bg-green-50/30 border-green-200/50 dark:bg-green-950/20 dark:border-green-800/30';
default: return 'bg-gray-50/30 border-gray-200/50 dark:bg-gray-950/20 dark:border-gray-800/30';
}
};
return (
<Card className={`p-6 ${getRiskBgColor(riskAnalysis.riskLevel)} transition-all hover:shadow-lg`}>
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-2">
<span className="text-2xl">{getRiskIcon(riskAnalysis.riskLevel)}</span>
<h3 className="text-lg font-semibold">Niveau de Risque</h3>
</div>
<div className={`text-3xl font-bold ${getRiskColor(riskAnalysis.riskLevel)}`}>
{riskAnalysis.riskScore}
</div>
</div>
<div className="space-y-3">
{/* Barre de risque */}
<div className="w-full bg-gray-200 rounded-full h-3 overflow-hidden">
<div
className={`h-3 rounded-full transition-all duration-500 ${
riskAnalysis.riskLevel === 'critical' ? 'bg-red-500/80' :
riskAnalysis.riskLevel === 'high' ? 'bg-orange-500/80' :
riskAnalysis.riskLevel === 'medium' ? 'bg-yellow-500/80' : 'bg-green-500/80'
}`}
style={{ width: `${Math.min(riskAnalysis.riskScore, 100)}%` }}
/>
</div>
{/* Détails des risques */}
<div className="grid grid-cols-2 gap-2 text-sm">
<div className="flex justify-between">
<span className="text-[var(--muted-foreground)]">En retard:</span>
<span className="font-medium text-red-600/80 dark:text-red-400/80">{metrics.summary.overdueCount}</span>
</div>
<div className="flex justify-between">
<span className="text-[var(--muted-foreground)]">Critique:</span>
<span className="font-medium text-orange-600/80 dark:text-orange-400/80">{metrics.summary.criticalCount}</span>
</div>
</div>
{/* Recommandation */}
<div className="pt-2 border-t border-[var(--border)]">
<p className="text-xs text-[var(--muted-foreground)] leading-relaxed">
{riskAnalysis.recommendation}
</p>
</div>
</div>
</Card>
);
}