"use client"; import React, { useState, useEffect } from "react"; import { useParams, useRouter } from "next/navigation"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Users, TrendingUp, Target, Award, BarChart3, ArrowLeft, Download, UserCheck, GraduationCap, Building2, Star, BookOpen, X, ChevronRight, } from "lucide-react"; import { TechIcon } from "@/components/icons/tech-icon"; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { loadTeams, loadSkillCategories } from "@/lib/data-loader"; import { Team, SkillCategory } from "@/lib/types"; interface TeamMember { id: string; firstName: string; lastName: string; skills: Array<{ skillId: string; skillName: string; category: string; level: number; canMentor: boolean; wantsToLearn: boolean; }>; joinDate: string; } interface TeamStats { teamId: string; teamName: string; direction: string; totalMembers: number; averageSkillLevel: number; topSkills: Array<{ skillName: string; averageLevel: number }>; skillCoverage: number; members: TeamMember[]; } function getSkillLevelLabel(level: number): string { if (level < 0.5) return "Débutant"; if (level < 1.5) return "Intermé."; if (level < 2.5) return "Avancé"; return "Expert"; } function getSkillLevelColor(level: number): string { if (level < 0.5) return "bg-red-500"; if (level < 1.5) return "bg-orange-500"; if (level < 2.5) return "bg-blue-500"; return "bg-green-500"; } // Mock data generation (same as admin page) function generateTeamMembers( teamName: string, memberCount: number, skillCategories: SkillCategory[] ) { const firstNames = [ "Alice", "Bob", "Claire", "David", "Emma", "Frank", "Grace", "Hugo", "Iris", "Jack", "Kelly", "Liam", "Maya", "Noah", "Olivia", "Paul", "Quinn", "Rose", "Sam", "Tara", ]; const lastNames = [ "Martin", "Bernard", "Dubois", "Thomas", "Robert", "Richard", "Petit", "Durand", "Leroy", "Moreau", "Simon", "Laurent", "Michel", "Garcia", "David", "Bertrand", "Roux", "Vincent", "Fournier", "Morel", ]; const allSkills: Array<{ skillName: string; category: string; id: string }> = []; skillCategories.forEach((category) => { category.skills.forEach((skill) => { allSkills.push({ skillName: skill.name, category: category.category, id: skill.id, }); }); }); return Array.from({ length: memberCount }, (_, index) => { const firstName = firstNames[Math.floor(Math.random() * firstNames.length)]; const lastName = lastNames[Math.floor(Math.random() * lastNames.length)]; const skillCount = Math.floor(Math.random() * 8) + 8; const memberSkills = allSkills .sort(() => Math.random() - 0.5) .slice(0, skillCount) .map((skill) => ({ skillId: skill.id, skillName: skill.skillName, category: skill.category, level: Math.floor(Math.random() * 4), canMentor: Math.random() > 0.7, wantsToLearn: Math.random() > 0.6, })); return { id: `${teamName}-member-${index + 1}`, firstName, lastName, skills: memberSkills, joinDate: new Date( Date.now() - Math.random() * 365 * 24 * 60 * 60 * 1000 * 3 ) .toISOString() .split("T")[0], }; }); } function getRandomSkills(skillCategories: SkillCategory[], count: number = 3) { const allSkills: Array<{ skillName: string; category: string }> = []; skillCategories.forEach((category) => { category.skills.forEach((skill) => { allSkills.push({ skillName: skill.name, category: category.category }); }); }); const shuffled = allSkills.sort(() => Math.random() - 0.5); const randomSkills = shuffled.slice(0, count).map((skill) => ({ skillName: skill.skillName, averageLevel: Math.random() * 3, })); return randomSkills.sort((a, b) => b.averageLevel - a.averageLevel); } export default function TeamDetailPage() { const params = useParams(); const router = useRouter(); const teamId = params.teamId as string; const [team, setTeam] = useState(null); const [loading, setLoading] = useState(true); const [skillAnalysis, setSkillAnalysis] = useState([]); const [selectedMember, setSelectedMember] = useState(null); const [isMemberModalOpen, setIsMemberModalOpen] = useState(false); useEffect(() => { async function loadTeamData() { try { const [teamsData, categoriesData] = await Promise.all([ loadTeams(), loadSkillCategories(), ]); const foundTeam = teamsData.find((t) => t.id === teamId); if (!foundTeam) { router.push("/admin"); return; } const memberCount = Math.floor(Math.random() * 10) + 3; const members = generateTeamMembers( foundTeam.name, memberCount, categoriesData ); const teamStats: TeamStats = { teamId: foundTeam.id, teamName: foundTeam.name, direction: foundTeam.direction, totalMembers: memberCount, averageSkillLevel: Math.random() * 3, topSkills: getRandomSkills(categoriesData, 3), skillCoverage: Math.random() * 100, members: members, }; setTeam(teamStats); // Analyser les compétences const skillMap = new Map(); members.forEach((member) => { member.skills.forEach((skill) => { if (!skillMap.has(skill.skillName)) { // Trouver l'icône de la compétence dans les données let skillIcon = null; for (const category of categoriesData) { const foundSkill = category.skills.find( (s) => s.name === skill.skillName ); if (foundSkill) { skillIcon = foundSkill.icon; break; } } skillMap.set(skill.skillName, { skillName: skill.skillName, category: skill.category, icon: skillIcon, experts: [], learners: [], averageLevel: 0, totalEvaluations: 0, }); } const skillData = skillMap.get(skill.skillName); skillData.totalEvaluations++; skillData.averageLevel += skill.level; if (skill.level >= 2) { skillData.experts.push({ name: `${member.firstName} ${member.lastName}`, level: skill.level, canMentor: skill.canMentor, }); } if (skill.wantsToLearn) { skillData.learners.push({ name: `${member.firstName} ${member.lastName}`, currentLevel: skill.level, }); } }); }); const skills = Array.from(skillMap.values()) .map((skill) => ({ ...skill, averageLevel: skill.averageLevel / skill.totalEvaluations, })) .sort((a, b) => b.averageLevel - a.averageLevel); setSkillAnalysis(skills); } catch (error) { console.error("Error loading team data:", error); router.push("/admin"); } finally { setLoading(false); } } loadTeamData(); }, [teamId, router]); const handleMemberClick = (member: TeamMember) => { setSelectedMember(member); setIsMemberModalOpen(true); }; const handleCloseMemberModal = () => { setIsMemberModalOpen(false); setSelectedMember(null); }; const handleExportReport = () => { if (!team) return; const reportData = { team: team.teamName, direction: team.direction, exportDate: new Date().toLocaleDateString(), summary: { totalMembers: team.totalMembers, averageSkillLevel: team.averageSkillLevel, skillCoverage: team.skillCoverage, }, topSkills: team.topSkills, skillAnalysis: skillAnalysis.slice(0, 15), members: team.members.map((member) => ({ name: `${member.firstName} ${member.lastName}`, joinDate: member.joinDate, skillsCount: member.skills.length, averageLevel: member.skills.reduce((sum, s) => sum + s.level, 0) / member.skills.length, skills: member.skills.map((skill) => ({ skillName: skill.skillName, category: skill.category, level: skill.level, levelLabel: getSkillLevelLabel(skill.level), canMentor: skill.canMentor, wantsToLearn: skill.wantsToLearn, })), })), mentorshipOpportunities: skillAnalysis .filter( (skill) => skill.experts.length > 0 && skill.learners.length > 0 ) .map((skill) => ({ skillName: skill.skillName, experts: skill.experts.filter((e) => e.canMentor), learners: skill.learners, })), }; const dataStr = JSON.stringify(reportData, null, 2); const dataUri = "data:application/json;charset=utf-8," + encodeURIComponent(dataStr); const exportFileDefaultName = `rapport-complet-${team.teamName.toLowerCase()}-${ new Date().toISOString().split("T")[0] }.json`; const linkElement = document.createElement("a"); linkElement.setAttribute("href", dataUri); linkElement.setAttribute("download", exportFileDefaultName); linkElement.click(); }; if (loading) { return (
Chargement...
); } if (!team) { return (
Équipe non trouvée
); } return (
{/* Header */}

Équipe {team.teamName}

{team.direction} • {team.totalMembers} membres

{/* Stats générales */}
{team.totalMembers}
Membres actifs
{((team.averageSkillLevel / 3) * 100).toFixed(0)}%
Niveau moyen
{skillAnalysis.length}
Compétences évaluées
{skillAnalysis.filter((s) => s.experts.length > 0).length}
Expertises disponibles
{/* Analyse des compétences */}

Top Compétences

{skillAnalysis.slice(0, 15).map((skill, idx) => (
{/* Icône de la technologie */}
{skill.icon ? (
) : (
)}
{/* Contenu principal */}

{skill.skillName}

{((skill.averageLevel / 3) * 100).toFixed(0)}%
{/* Barre de progression */}
{/* Métadonnées */}
{skill.category}
{skill.experts.length > 0 && (
{skill.experts.length}
)} {skill.learners.length > 0 && (
{skill.learners.length}
)}
))}
{/* Experts et mentors */}

Experts & Mentors

{skillAnalysis .filter((skill) => skill.experts.length > 0) .slice(0, 20) .map((skill, idx) => (
{/* Icône de la technologie */}
{skill.icon ? (
) : (
)}
{/* Nom de la compétence */}

{skill.skillName}

{skill.category}

{/* Badge du nombre d'experts */}
{skill.experts.length} expert {skill.experts.length > 1 ? "s" : ""}
{/* Liste des experts */}
{skill.experts.map((expert, expertIdx) => (
{expert.name .split(" ") .map((n) => n[0]) .join("")}
{expert.name}
= 3 ? "bg-green-500/20 text-green-300 border border-green-500/30" : expert.level >= 2 ? "bg-blue-500/20 text-blue-300 border border-blue-500/30" : "bg-orange-500/20 text-orange-300 border border-orange-500/30" }`} > {getSkillLevelLabel(expert.level)}
{expert.canMentor && (
)}
))}
))}
{/* Liste des membres */}

Membres de l'équipe

{team.members.map((member, idx) => { const avgLevel = member.skills.reduce((sum, s) => sum + s.level, 0) / member.skills.length; const mentorSkills = member.skills.filter( (s) => s.canMentor ).length; const learningSkills = member.skills.filter( (s) => s.wantsToLearn ).length; return (
handleMemberClick(member)} className="group p-4 bg-white/5 border border-white/10 rounded-xl hover:bg-white/10 hover:border-white/20 transition-all duration-200 cursor-pointer" >
{/* Avatar */}
{member.firstName[0]} {member.lastName[0]}
{/* Informations principales */}

{member.firstName} {member.lastName}

{((avgLevel / 3) * 100).toFixed(0)}%
{/* Date d'arrivée */}

Membre depuis{" "} {new Date(member.joinDate).toLocaleDateString( "fr-FR", { year: "numeric", month: "long", } )}

{/* Barre de progression du niveau */}
{/* Statistiques */}
{member.skills.length}
Compétences
{mentorSkills}
Mentor
{learningSkills}
Apprend
); })}
{/* Modal des détails du membre */} {selectedMember && ( <>
{selectedMember.firstName[0]} {selectedMember.lastName[0]}

{selectedMember.firstName} {selectedMember.lastName}

{selectedMember.skills.length} compétences évaluées

)}
{selectedMember && (
{/* Statistiques rapides */}
{selectedMember.skills.length}
Compétences
{selectedMember.skills.filter((s) => s.canMentor).length}
Peut mentorer
{selectedMember.skills.filter((s) => s.wantsToLearn).length}
Veut apprendre
{/* Liste des compétences par catégorie */}

Compétences détaillées

{/* Grouper les compétences par catégorie */} {Object.entries( selectedMember.skills.reduce((acc, skill) => { if (!acc[skill.category]) { acc[skill.category] = []; } acc[skill.category].push(skill); return acc; }, {} as Record) ).map(([category, skills]) => (

{category} ({skills.length} compétence {skills.length > 1 ? "s" : ""})

{skills .sort((a, b) => b.level - a.level) .map((skill, skillIdx) => { // Trouver l'icône de la compétence let skillIcon = null; if (skillAnalysis.length > 0) { const foundSkill = skillAnalysis.find( (s) => s.skillName === skill.skillName ); if (foundSkill) { skillIcon = foundSkill.icon; } } return (
{/* Icône de la technologie */}
{skillIcon ? ( ) : ( )}
{/* Nom de la compétence */}
{skill.skillName}
{/* Niveau et badges */}
{/* Badge de niveau */}
= 3 ? "bg-green-500/20 text-green-300" : skill.level >= 2 ? "bg-blue-500/20 text-blue-300" : skill.level >= 1 ? "bg-orange-500/20 text-orange-300" : "bg-red-500/20 text-red-300" }`} > {getSkillLevelLabel(skill.level)}
{/* Icônes mentor/apprenant */} {skill.canMentor && (
)} {skill.wantsToLearn && (
)}
); })}
))}
)}
); }