feat: review admin overview and popup details fwith importance

This commit is contained in:
Julien Froidefond
2025-08-27 13:16:39 +02:00
parent 94a18b0ca5
commit e9aecca2a5
5 changed files with 415 additions and 82 deletions

View File

@@ -20,8 +20,10 @@ import {
User,
Zap,
Crown,
AlertTriangle,
} from "lucide-react";
import { TechIcon } from "@/components/icons/tech-icon";
import { getImportanceColors } from "@/lib/tech-colors";
interface TeamStatsRowProps {
teamId: string;
@@ -34,8 +36,14 @@ interface TeamStatsRowProps {
averageLevel: number;
color?: string;
icon?: string;
importance: "incontournable" | "majeure" | "standard";
coverage: number;
}>;
skillCoverage: number;
criticalSkillsCoverage: {
incontournable: number;
majeure: number;
};
onViewDetails?: () => void;
onViewReport?: () => void;
}
@@ -77,9 +85,14 @@ export function TeamStatsRow({
averageSkillLevel,
topSkills,
skillCoverage,
criticalSkillsCoverage,
onViewDetails,
onViewReport,
}: TeamStatsRowProps) {
// Calculer les alertes sur les compétences critiques
const hasIncontournableAlert = criticalSkillsCoverage.incontournable < 75;
const hasMajeureAlert = criticalSkillsCoverage.majeure < 60;
return (
<div className="group bg-gradient-to-r from-slate-800/50 to-slate-700/40 backdrop-blur-sm border border-slate-600/40 rounded-xl p-4 hover:from-slate-700/60 hover:to-slate-600/50 hover:border-slate-500/50 transition-all duration-300 shadow-lg hover:shadow-xl">
{/* Layout horizontal compact */}
@@ -125,19 +138,57 @@ export function TeamStatsRow({
{/* Indicateurs clés compacts */}
<div className="flex items-center gap-4">
<div className="text-center">
<div className="text-sm font-bold text-white">
{averageSkillLevel.toFixed(1)}
</div>
<div className="text-xs text-slate-300">/ 3.0</div>
</div>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<div className="text-center">
<div
className={`text-sm font-bold ${
criticalSkillsCoverage.incontournable < 75
? "text-red-400"
: "text-green-400"
}`}
>
{criticalSkillsCoverage.incontournable.toFixed(0)}%
</div>
<div className="text-xs text-slate-300">Incont.</div>
</div>
</TooltipTrigger>
<TooltipContent>
<p className="text-xs">
Couverture des compétences incontournables
<br />
Objectif : 75%
</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<div className="text-center">
<div className="text-sm font-bold text-white">
{skillCoverage.toFixed(0)}%
</div>
<div className="text-xs text-slate-300">Couv.</div>
</div>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<div className="text-center">
<div
className={`text-sm font-bold ${
criticalSkillsCoverage.majeure < 60
? "text-red-400"
: "text-green-400"
}`}
>
{criticalSkillsCoverage.majeure.toFixed(0)}%
</div>
<div className="text-xs text-slate-300">Maj.</div>
</div>
</TooltipTrigger>
<TooltipContent>
<p className="text-xs">
Couverture des compétences majeures
<br />
Objectif : 60%
</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<TooltipProvider>
<Tooltip>
@@ -169,21 +220,68 @@ export function TeamStatsRow({
{/* Top skills mini */}
<div className="flex items-center gap-2">
{topSkills.slice(0, 3).map((skill, idx) => (
<div
key={idx}
className={`px-2 py-1 border rounded-md text-center min-w-[60px] shadow-sm ${getSkillLevelBadgeClasses(
skill.averageLevel
)}`}
>
<div className="text-xs font-medium text-white truncate mb-1">
{skill.skillName}
</div>
<div className="text-xs font-bold">
{((skill.averageLevel / 3) * 100).toFixed(0)}%
</div>
</div>
))}
{topSkills.slice(0, 3).map((skill, idx) => {
const colors = getImportanceColors(skill.importance);
const target =
skill.importance === "incontournable"
? 75
: skill.importance === "majeure"
? 60
: 0;
const isUnderTarget = target > 0 && skill.coverage < target;
return (
<TooltipProvider key={idx}>
<Tooltip>
<TooltipTrigger asChild>
<div
className={`relative px-2 py-1 border rounded-md text-center min-w-[60px] shadow-sm ${
isUnderTarget
? "bg-red-500/20 border-red-500/30"
: "bg-green-500/20 border-green-500/30"
}`}
>
<div
className={`text-xs font-medium truncate mb-1 ${
isUnderTarget ? "text-red-400" : "text-green-400"
}`}
>
{skill.skillName}
</div>
<div
className={`text-xs font-bold ${
isUnderTarget ? "text-red-400" : "text-green-400"
}`}
>
{skill.coverage.toFixed(0)}%
</div>
</div>
</TooltipTrigger>
<TooltipContent>
<div className="text-xs">
<p className="font-medium">{skill.skillName}</p>
<p className="text-slate-400">
{skill.importance === "incontournable"
? "Compétence incontournable"
: skill.importance === "majeure"
? "Compétence majeure"
: "Compétence standard"}
</p>
{target > 0 && (
<p
className={
isUnderTarget ? "text-red-400" : "text-green-400"
}
>
Objectif : {target}%
</p>
)}
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
})}
</div>
{/* Actions compactes */}