167 lines
6.2 KiB
TypeScript
167 lines
6.2 KiB
TypeScript
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { TeamReviewData } from "@/lib/team-review-types";
|
|
import { Progress } from "@/components/ui/progress";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { AlertTriangle } from "lucide-react";
|
|
|
|
interface TeamOverviewProps {
|
|
team: TeamReviewData["team"];
|
|
stats: TeamReviewData["stats"];
|
|
members: TeamReviewData["members"];
|
|
categoryCoverage: TeamReviewData["categoryCoverage"];
|
|
}
|
|
|
|
export function TeamOverview({
|
|
team,
|
|
stats,
|
|
members,
|
|
categoryCoverage,
|
|
}: TeamOverviewProps) {
|
|
// Trouver les top contributeurs
|
|
const topContributors = [...members]
|
|
.sort((a, b) => b.expertSkills - a.expertSkills)
|
|
.slice(0, 3);
|
|
|
|
// Trouver les catégories les plus fortes
|
|
const strongestCategories = [...categoryCoverage]
|
|
.sort((a, b) => b.coverage - a.coverage)
|
|
.slice(0, 2);
|
|
|
|
// Trouver les catégories qui nécessitent de l'attention
|
|
const categoriesNeedingAttention = [...categoryCoverage]
|
|
.filter((cat) => {
|
|
// Une catégorie nécessite de l'attention si :
|
|
// - Couverture faible (< 40%)
|
|
// - OU pas assez d'experts (< 2) avec une équipe de taille significative (> 5)
|
|
// - OU beaucoup d'apprenants (> 30% de l'équipe) avec peu de mentors (< 2)
|
|
return (
|
|
cat.coverage < 40 ||
|
|
(cat.experts < 2 && stats.totalMembers > 5) ||
|
|
(cat.learners > stats.totalMembers * 0.3 && cat.mentors < 2)
|
|
);
|
|
})
|
|
.sort((a, b) => {
|
|
// Prioriser les catégories avec le plus de besoins
|
|
const aScore = a.learners * 2 - a.mentors - a.experts;
|
|
const bScore = b.learners * 2 - b.mentors - b.experts;
|
|
return bScore - aScore;
|
|
})
|
|
.slice(0, 2);
|
|
|
|
return (
|
|
<Card className="bg-white/5 border-white/10 backdrop-blur">
|
|
<CardHeader>
|
|
<CardTitle className="text-slate-200">Vue d'ensemble</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
|
{/* Points forts */}
|
|
<div>
|
|
<h3 className="text-sm font-medium text-slate-200 mb-4">
|
|
Points forts
|
|
</h3>
|
|
<div className="space-y-4">
|
|
{strongestCategories.map((cat) => (
|
|
<div key={cat.category} className="space-y-2">
|
|
<div className="flex justify-between items-center">
|
|
<p className="text-sm font-medium text-slate-300">
|
|
{cat.category}
|
|
</p>
|
|
<span className="text-sm text-slate-400">
|
|
{cat.coverage.toFixed(0)}%
|
|
</span>
|
|
</div>
|
|
<Progress value={cat.coverage} className="bg-white/10" />
|
|
<p className="text-xs text-slate-400">
|
|
{cat.experts} experts • {cat.mentors} mentors
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Top contributeurs */}
|
|
<div>
|
|
<h3 className="text-sm font-medium text-slate-200 mb-4">
|
|
Top contributeurs
|
|
</h3>
|
|
<div className="space-y-4">
|
|
{topContributors.map((member) => (
|
|
<div key={member.member.uuid} className="space-y-1">
|
|
<p className="text-sm font-medium text-slate-300">
|
|
{member.member.firstName} {member.member.lastName}
|
|
</p>
|
|
<div className="flex gap-2 text-xs">
|
|
<Badge
|
|
variant="secondary"
|
|
className="bg-white/10 text-slate-300 border-white/20"
|
|
>
|
|
{member.expertSkills} expertises
|
|
</Badge>
|
|
{member.mentorSkills > 0 && (
|
|
<Badge
|
|
variant="outline"
|
|
className="text-slate-300 border-white/20"
|
|
>
|
|
{member.mentorSkills} mentorats
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Points d'attention */}
|
|
<div>
|
|
<h3 className="text-sm font-medium flex items-center gap-2 text-amber-400 mb-4">
|
|
<AlertTriangle size={16} />
|
|
Besoins prioritaires
|
|
</h3>
|
|
<div className="space-y-4">
|
|
{categoriesNeedingAttention.map((cat) => (
|
|
<div key={cat.category} className="space-y-2">
|
|
<div className="flex justify-between items-center">
|
|
<p className="text-sm font-medium text-slate-300">
|
|
{cat.category}
|
|
</p>
|
|
<div className="flex items-center gap-2">
|
|
<Badge
|
|
variant="outline"
|
|
className="text-amber-400 border-amber-400/30"
|
|
>
|
|
{cat.learners} apprenants
|
|
</Badge>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center gap-4 text-sm text-slate-400">
|
|
<span>{cat.experts} experts</span>
|
|
<span>{cat.mentors} mentors</span>
|
|
</div>
|
|
<div className="text-xs text-amber-400/80">
|
|
{cat.coverage < 40 && "Couverture insuffisante • "}
|
|
{cat.experts < 2 &&
|
|
stats.totalMembers > 5 &&
|
|
"Manque d'experts • "}
|
|
{cat.learners > stats.totalMembers * 0.3 &&
|
|
cat.mentors < 2 &&
|
|
"Besoin de mentors"}
|
|
</div>
|
|
</div>
|
|
))}
|
|
{stats.learningNeeds > 0 && (
|
|
<div className="pt-2 border-t border-white/10">
|
|
<p className="text-sm text-amber-400 flex items-center gap-2">
|
|
<AlertTriangle size={16} />
|
|
{stats.learningNeeds} compétences sans expert ni mentor
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|