- 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.
90 lines
3.6 KiB
TypeScript
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>
|
|
);
|
|
}
|