"use client"; import { useState, useEffect } from "react"; import { UserEvaluation, SkillCategory, Team, CategoryEvaluation, UserProfile, SkillLevel, } from "@/lib/types"; import { loadUserEvaluation, saveUserEvaluation, createEmptyEvaluation, } from "@/lib/evaluation-utils"; import { apiClient } from "@/services/api-client"; import { loadSkillCategories, loadTeams } from "@/lib/data-loader"; import { AuthService } from "@/lib/auth-utils"; // Fonction pour migrer une évaluation existante avec de nouvelles catégories function migrateEvaluation( evaluation: UserEvaluation, allCategories: SkillCategory[] ): UserEvaluation { const existingCategoryNames = evaluation.evaluations.map((e) => e.category); const missingCategories = allCategories.filter( (cat) => !existingCategoryNames.includes(cat.category) ); if (missingCategories.length === 0) { return evaluation; // Pas de migration nécessaire } console.log( "🔄 Migrating evaluation with new categories:", missingCategories.map((c) => c.category) ); const newCategoryEvaluations: CategoryEvaluation[] = missingCategories.map( (category) => ({ category: category.category, skills: [], selectedSkillIds: [], }) ); return { ...evaluation, evaluations: [...evaluation.evaluations, ...newCategoryEvaluations], lastUpdated: new Date().toISOString(), }; } export function useEvaluation() { const [userEvaluation, setUserEvaluation] = useState( null ); const [skillCategories, setSkillCategories] = useState([]); const [teams, setTeams] = useState([]); const [loading, setLoading] = useState(true); // Load initial data useEffect(() => { async function initializeData() { try { const [categories, teamsData] = await Promise.all([ loadSkillCategories(), loadTeams(), ]); setSkillCategories(categories); setTeams(teamsData); // Try to load user profile from cookie and then load evaluation from API try { const profile = await AuthService.getCurrentUser(); if (profile) { const saved = await loadUserEvaluation(profile); if (saved) { // Migrate evaluation to include new categories if needed const migratedEvaluation = migrateEvaluation(saved, categories); setUserEvaluation(migratedEvaluation); if (migratedEvaluation !== saved) { await saveUserEvaluation(migratedEvaluation); // Save the migrated version } } } } catch (profileError) { console.error("Failed to load user profile:", profileError); } } catch (error) { console.error("Failed to initialize data:", error); } finally { setLoading(false); } } initializeData(); }, []); const loadEvaluationForProfile = async (profile: UserProfile) => { try { setLoading(true); const saved = await loadUserEvaluation(profile); if (saved) { // Migrate evaluation to include new categories if needed const migratedEvaluation = migrateEvaluation(saved, skillCategories); setUserEvaluation(migratedEvaluation); if (migratedEvaluation !== saved) { await saveUserEvaluation(migratedEvaluation); // Save the migrated version } } else { // Create new evaluation const evaluations = createEmptyEvaluation(skillCategories); const newEvaluation: UserEvaluation = { profile, evaluations, lastUpdated: new Date().toISOString(), }; setUserEvaluation(newEvaluation); } } catch (error) { console.error("Failed to load evaluation for profile:", error); } finally { setLoading(false); } }; const reloadSkillCategories = async () => { try { const categories = await loadSkillCategories(); setSkillCategories(categories); // Si on a une évaluation en cours, la migrer avec les nouvelles catégories if (userEvaluation) { const migratedEvaluation = migrateEvaluation( userEvaluation, categories ); if (migratedEvaluation !== userEvaluation) { setUserEvaluation(migratedEvaluation); await saveUserEvaluation(migratedEvaluation); } } } catch (error) { console.error("Failed to reload skill categories:", error); } }; const updateProfile = async (profile: UserProfile) => { const evaluations = userEvaluation?.evaluations || createEmptyEvaluation(skillCategories); const newEvaluation: UserEvaluation = { profile, evaluations, lastUpdated: new Date().toISOString(), }; // Authenticate user and create cookie await AuthService.login(profile); setUserEvaluation(newEvaluation); await saveUserEvaluation(newEvaluation); }; const updateSkillLevel = async ( category: string, skillId: string, level: SkillLevel ) => { if (!userEvaluation) return; try { // Optimistic update const updatedEvaluations = userEvaluation.evaluations.map((catEval) => { if (catEval.category === category) { const existingSkill = catEval.skills.find( (s) => s.skillId === skillId ); const updatedSkills = existingSkill ? catEval.skills.map((skill) => skill.skillId === skillId ? { ...skill, level } : skill ) : [...catEval.skills, { skillId, level }]; return { ...catEval, skills: updatedSkills, }; } return catEval; }); const newEvaluation: UserEvaluation = { ...userEvaluation, evaluations: updatedEvaluations, lastUpdated: new Date().toISOString(), }; setUserEvaluation(newEvaluation); // Update via API await apiClient.updateSkillLevel( userEvaluation.profile, category, skillId, level ); } catch (error) { console.error("Failed to update skill level:", error); // Revert optimistic update if needed } }; const updateSkillMentorStatus = async ( category: string, skillId: string, canMentor: boolean ) => { if (!userEvaluation) return; try { const updatedEvaluations = userEvaluation.evaluations.map((catEval) => { if (catEval.category === category) { const updatedSkills = catEval.skills.map((skill) => skill.skillId === skillId ? { ...skill, canMentor } : skill ); return { ...catEval, skills: updatedSkills, }; } return catEval; }); const newEvaluation: UserEvaluation = { ...userEvaluation, evaluations: updatedEvaluations, lastUpdated: new Date().toISOString(), }; setUserEvaluation(newEvaluation); await apiClient.updateSkillMentorStatus( userEvaluation.profile, category, skillId, canMentor ); } catch (error) { console.error("Failed to update skill mentor status:", error); } }; const updateSkillLearningStatus = async ( category: string, skillId: string, wantsToLearn: boolean ) => { if (!userEvaluation) return; try { const updatedEvaluations = userEvaluation.evaluations.map((catEval) => { if (catEval.category === category) { const updatedSkills = catEval.skills.map((skill) => skill.skillId === skillId ? { ...skill, wantsToLearn } : skill ); return { ...catEval, skills: updatedSkills, }; } return catEval; }); const newEvaluation: UserEvaluation = { ...userEvaluation, evaluations: updatedEvaluations, lastUpdated: new Date().toISOString(), }; setUserEvaluation(newEvaluation); await apiClient.updateSkillLearningStatus( userEvaluation.profile, category, skillId, wantsToLearn ); } catch (error) { console.error("Failed to update skill learning status:", error); } }; const addSkillToEvaluation = async (category: string, skillId: string) => { if (!userEvaluation) return; // Sauvegarder l'état actuel pour le rollback const previousEvaluation = userEvaluation; try { // Optimistic UI update - mettre à jour immédiatement l'interface const updatedEvaluations = userEvaluation.evaluations.map((catEval) => { if (catEval.category === category) { if (!catEval.selectedSkillIds.includes(skillId)) { return { ...catEval, selectedSkillIds: [...catEval.selectedSkillIds, skillId], skills: [ ...catEval.skills, { skillId, level: null, canMentor: false, wantsToLearn: false }, ], }; } } return catEval; }); const newEvaluation: UserEvaluation = { ...userEvaluation, evaluations: updatedEvaluations, lastUpdated: new Date().toISOString(), }; setUserEvaluation(newEvaluation); // Appel API en arrière-plan await apiClient.addSkillToEvaluation( userEvaluation.profile, category, skillId ); } catch (error) { console.error("Failed to add skill to evaluation:", error); // Rollback optimiste en cas d'erreur setUserEvaluation(previousEvaluation); // Optionnel: afficher une notification d'erreur à l'utilisateur } }; const removeSkillFromEvaluation = async ( category: string, skillId: string ) => { if (!userEvaluation) return; // Sauvegarder l'état actuel pour le rollback const previousEvaluation = userEvaluation; try { // Optimistic UI update - mettre à jour immédiatement l'interface const updatedEvaluations = userEvaluation.evaluations.map((catEval) => { if (catEval.category === category) { return { ...catEval, selectedSkillIds: catEval.selectedSkillIds.filter( (id) => id !== skillId ), skills: catEval.skills.filter((skill) => skill.skillId !== skillId), }; } return catEval; }); const newEvaluation: UserEvaluation = { ...userEvaluation, evaluations: updatedEvaluations, lastUpdated: new Date().toISOString(), }; setUserEvaluation(newEvaluation); // Appel API en arrière-plan await apiClient.removeSkillFromEvaluation( userEvaluation.profile, category, skillId ); } catch (error) { console.error("Failed to remove skill from evaluation:", error); // Rollback optimiste en cas d'erreur setUserEvaluation(previousEvaluation); // Optionnel: afficher une notification d'erreur à l'utilisateur } }; const initializeEmptyEvaluation = async (profile: UserProfile) => { const evaluations = createEmptyEvaluation(skillCategories); const newEvaluation: UserEvaluation = { profile, evaluations, lastUpdated: new Date().toISOString(), }; // Authenticate user and create cookie await AuthService.login(profile); setUserEvaluation(newEvaluation); await saveUserEvaluation(newEvaluation); }; const clearUserProfile = async () => { try { await AuthService.logout(); setUserEvaluation(null); } catch (error) { console.error("Failed to logout:", error); setUserEvaluation(null); } }; return { userEvaluation, skillCategories, teams, loading, loadEvaluationForProfile, updateProfile, updateSkillLevel, updateSkillMentorStatus, updateSkillLearningStatus, addSkillToEvaluation, removeSkillFromEvaluation, initializeEmptyEvaluation, clearUserProfile, reloadSkillCategories, }; }