- Changed params in TeamDetailPage to be a Promise, ensuring proper async handling. - Updated data fetching logic to use awaited teamId for better clarity. - Modularized TeamDetailClientWrapper by extracting TeamDetailHeader, TeamMetricsCards, TeamDetailTabs, and TeamMemberModal for improved organization and readability. - Removed unused imports and streamlined the component structure, enhancing maintainability.
188 lines
6.5 KiB
TypeScript
188 lines
6.5 KiB
TypeScript
"use client";
|
|
|
|
import { TrendingUp, MessageSquare, Lightbulb } from "lucide-react";
|
|
|
|
interface SkillAnalysis {
|
|
skillName: string;
|
|
category: string;
|
|
experts: Array<{
|
|
name: string;
|
|
level: number;
|
|
canMentor: boolean;
|
|
}>;
|
|
learners: Array<{
|
|
name: string;
|
|
currentLevel: number;
|
|
}>;
|
|
averageLevel: number;
|
|
totalEvaluations: number;
|
|
expertCount: number;
|
|
learnerCount: number;
|
|
proficiencyRate: number;
|
|
}
|
|
|
|
interface TeamInsights {
|
|
averageTeamLevel: number;
|
|
totalExperts: number;
|
|
totalLearners: number;
|
|
skillGaps: number;
|
|
strongSkills: number;
|
|
}
|
|
|
|
interface TeamInsightsTabProps {
|
|
skillAnalysis: SkillAnalysis[];
|
|
teamInsights: TeamInsights;
|
|
}
|
|
|
|
export function TeamInsightsTab({
|
|
skillAnalysis,
|
|
teamInsights,
|
|
}: TeamInsightsTabProps) {
|
|
return (
|
|
<>
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
{/* Compétences à développer */}
|
|
<div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6">
|
|
<h3 className="text-lg font-semibold text-white mb-6 flex items-center gap-2">
|
|
<TrendingUp className="h-5 w-5 text-red-400" />
|
|
Compétences à développer
|
|
</h3>
|
|
<div className="space-y-3">
|
|
{skillAnalysis
|
|
.filter((s) => s.averageLevel < 1.5)
|
|
.slice(0, 5)
|
|
.map((skill, idx) => (
|
|
<div
|
|
key={idx}
|
|
className="flex items-center justify-between p-3 bg-white/5 rounded-lg"
|
|
>
|
|
<div>
|
|
<div className="text-white font-medium">
|
|
{skill.skillName}
|
|
</div>
|
|
<div className="text-xs text-slate-400">
|
|
{skill.category}
|
|
</div>
|
|
</div>
|
|
<div className="text-right">
|
|
<div className="text-red-300 font-semibold">
|
|
{skill.averageLevel.toFixed(1)}
|
|
</div>
|
|
<div className="text-xs text-slate-400">
|
|
{skill.learnerCount} intéressés
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Opportunités de mentorat */}
|
|
<div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6">
|
|
<h3 className="text-lg font-semibold text-white mb-6 flex items-center gap-2">
|
|
<MessageSquare className="h-5 w-5 text-green-400" />
|
|
Opportunités de mentorat
|
|
</h3>
|
|
<div className="space-y-3">
|
|
{skillAnalysis
|
|
.filter(
|
|
(s) =>
|
|
s.experts.filter((e) => e.canMentor).length > 0 &&
|
|
s.learnerCount > 0
|
|
)
|
|
.slice(0, 5)
|
|
.map((skill, idx) => (
|
|
<div key={idx} className="p-3 bg-white/5 rounded-lg">
|
|
<div className="flex items-center justify-between mb-2">
|
|
<div className="text-white font-medium">
|
|
{skill.skillName}
|
|
</div>
|
|
<div className="text-xs text-slate-400">
|
|
{skill.category}
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center justify-between text-xs">
|
|
<div className="text-green-300">
|
|
{skill.experts.filter((e) => e.canMentor).length} mentor
|
|
{skill.experts.filter((e) => e.canMentor).length > 1
|
|
? "s"
|
|
: ""}
|
|
</div>
|
|
<div className="text-blue-300">
|
|
{skill.learnerCount} apprenant
|
|
{skill.learnerCount > 1 ? "s" : ""}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Recommandations */}
|
|
<div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6">
|
|
<h3 className="text-lg font-semibold text-white mb-6 flex items-center gap-2">
|
|
<Lightbulb className="h-5 w-5 text-yellow-400" />
|
|
Recommandations pour l'équipe
|
|
</h3>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div className="p-4 bg-blue-500/10 border border-blue-500/20 rounded-xl">
|
|
<h4 className="font-medium text-blue-300 mb-2">
|
|
🎯 Formations prioritaires
|
|
</h4>
|
|
<p className="text-sm text-slate-300">
|
|
Organiser des formations sur{" "}
|
|
{skillAnalysis
|
|
.filter((s) => s.averageLevel < 1.5)
|
|
.slice(0, 2)
|
|
.map((s) => s.skillName)
|
|
.join(" et ")}
|
|
pour combler les lacunes identifiées.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="p-4 bg-green-500/10 border border-green-500/20 rounded-xl">
|
|
<h4 className="font-medium text-green-300 mb-2">
|
|
🤝 Programme de mentorat
|
|
</h4>
|
|
<p className="text-sm text-slate-300">
|
|
Mettre en place un système de mentorat avec{" "}
|
|
{skillAnalysis.reduce(
|
|
(sum, skill) =>
|
|
sum + skill.experts.filter((e) => e.canMentor).length,
|
|
0
|
|
)}{" "}
|
|
mentors disponibles.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="p-4 bg-purple-500/10 border border-purple-500/20 rounded-xl">
|
|
<h4 className="font-medium text-purple-300 mb-2">
|
|
📈 Capitaliser sur les forces
|
|
</h4>
|
|
<p className="text-sm text-slate-300">
|
|
Exploiter l'expertise en{" "}
|
|
{skillAnalysis
|
|
.filter((s) => s.averageLevel >= 2.5)
|
|
.slice(0, 2)
|
|
.map((s) => s.skillName)
|
|
.join(" et ")}
|
|
pour des projets ambitieux.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="p-4 bg-orange-500/10 border border-orange-500/20 rounded-xl">
|
|
<h4 className="font-medium text-orange-300 mb-2">
|
|
🔄 Plan de développement
|
|
</h4>
|
|
<p className="text-sm text-slate-300">
|
|
Créer des parcours de montée en compétences personnalisés pour{" "}
|
|
{teamInsights.totalLearners} objectifs d'apprentissage.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|