From 76015510f3a155223f700c8f6387baef0b7a8644 Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Fri, 22 Aug 2025 12:03:59 +0200 Subject: [PATCH] fix: evaluation on empty eval category was KO --- app/evaluation/page.tsx | 6 +- components/evaluation/client-wrapper.tsx | 81 +++++++++++++++++++----- components/skill-evaluation.tsx | 5 +- components/skill-selector.tsx | 13 +++- services/evaluation-service.ts | 14 ++-- 5 files changed, 88 insertions(+), 31 deletions(-) diff --git a/app/evaluation/page.tsx b/app/evaluation/page.tsx index 551e3f9..31baec3 100644 --- a/app/evaluation/page.tsx +++ b/app/evaluation/page.tsx @@ -25,7 +25,11 @@ export default async function EvaluationPage() { ]); return ( - +
{/* Skill Evaluation */} { - setCurrentEvaluation(userEvaluation); - }, [userEvaluation]); + if (userEvaluation) { + setCurrentEvaluation(userEvaluation); + } else if (skillCategories.length > 0) { + // Créer une évaluation vide si aucune n'existe, pour que l'UI puisse fonctionner + const emptyEvaluation: UserEvaluation = { + profile: { firstName: "", lastName: "", teamId: "" }, // Profile temporaire + evaluations: createEmptyEvaluation(skillCategories), + lastUpdated: new Date().toISOString(), + }; + setCurrentEvaluation(emptyEvaluation); + } + }, [userEvaluation, skillCategories]); // Fonctions avec UI optimiste const updateSkillLevel = async ( @@ -173,9 +192,11 @@ export function EvaluationClientWrapper({ const previousEvaluation = currentEvaluation; try { - const updatedEvaluations = currentEvaluation.evaluations.map( - (catEval) => { + // 1. Mise à jour optimiste de l'UI (immédiate) + let updatedEvaluations: CategoryEvaluation[] = + currentEvaluation.evaluations.map((catEval) => { if (catEval.category === category) { + // Si la compétence n'est pas déjà ajoutée if (!catEval.selectedSkillIds.includes(skillId)) { return { ...catEval, @@ -184,7 +205,7 @@ export function EvaluationClientWrapper({ ...catEval.skills, { skillId, - level: null, + level: "never" as SkillLevel, canMentor: false, wantsToLearn: false, }, @@ -193,8 +214,28 @@ export function EvaluationClientWrapper({ } } return catEval; - } - ); + }); + + // Si la catégorie n'existe pas encore, la créer + if ( + !updatedEvaluations.find( + (evaluation) => evaluation.category === category + ) + ) { + const newCategoryEvaluation: CategoryEvaluation = { + category, + selectedSkillIds: [skillId], + skills: [ + { + skillId, + level: "never", + canMentor: false, + wantsToLearn: false, + }, + ], + }; + updatedEvaluations = [...updatedEvaluations, newCategoryEvaluation]; + } const newEvaluation: UserEvaluation = { ...currentEvaluation, @@ -202,10 +243,14 @@ export function EvaluationClientWrapper({ lastUpdated: new Date().toISOString(), }; + // 2. Mettre à jour l'état local immédiatement setCurrentEvaluation(newEvaluation); + + // 3. Persister côté serveur (en arrière-plan) await addSkillToEvaluationAction(category, skillId); } catch (error) { - console.error("Failed to add skill to evaluation:", error); + console.error("❌ Failed to add skill:", error); + // En cas d'erreur, rollback l'état local setCurrentEvaluation(previousEvaluation); } }; @@ -219,8 +264,9 @@ export function EvaluationClientWrapper({ const previousEvaluation = currentEvaluation; try { - const updatedEvaluations = currentEvaluation.evaluations.map( - (catEval) => { + // 1. Mise à jour optimiste de l'UI (immédiate) + const updatedEvaluations: CategoryEvaluation[] = + currentEvaluation.evaluations.map((catEval) => { if (catEval.category === category) { // Filtrer seulement les compétences qui ne sont pas déjà sélectionnées const newSkillIds = skillIds.filter( @@ -235,7 +281,7 @@ export function EvaluationClientWrapper({ ...catEval.skills, ...newSkillIds.map((skillId) => ({ skillId, - level: null, + level: "never" as SkillLevel, canMentor: false, wantsToLearn: false, })), @@ -244,8 +290,7 @@ export function EvaluationClientWrapper({ } } return catEval; - } - ); + }); const newEvaluation: UserEvaluation = { ...currentEvaluation, @@ -253,14 +298,16 @@ export function EvaluationClientWrapper({ lastUpdated: new Date().toISOString(), }; + // 2. Mettre à jour l'état local immédiatement setCurrentEvaluation(newEvaluation); - // Ajouter toutes les compétences en parallèle côté API + // 3. Persister côté serveur (en arrière-plan) await Promise.all( skillIds.map((skillId) => addSkillToEvaluationAction(category, skillId)) ); } catch (error) { - console.error("Failed to add multiple skills to evaluation:", error); + console.error("❌ Failed to add multiple skills:", error); + // En cas d'erreur, rollback l'état local setCurrentEvaluation(previousEvaluation); } }; diff --git a/components/skill-evaluation.tsx b/components/skill-evaluation.tsx index 725ce0a..9f2e073 100644 --- a/components/skill-evaluation.tsx +++ b/components/skill-evaluation.tsx @@ -33,7 +33,8 @@ export function SkillEvaluation({ } = useEvaluationContext(); // Utiliser l'évaluation du contexte (avec état optimiste) ou celle des props (SSR) - const activeEvaluations = contextEvaluation?.evaluations || evaluations; + const activeEvaluations = contextEvaluation?.evaluations || []; + const searchParams = useSearchParams(); const router = useRouter(); const categoryParam = searchParams.get("category"); @@ -90,7 +91,7 @@ export function SkillEvaluation({
cat.category === selectedCategory ); + + // Utiliser les évaluations passées en props (qui viennent du contexte et sont mises à jour) const currentEvaluation = evaluations.find( (evaluation) => evaluation.category === selectedCategory ); if (!currentCategory) return null; - const selectedSkillIds = currentEvaluation?.selectedSkillIds || []; + // Si la catégorie n'existe pas dans l'évaluation, créer une évaluation vide pour cette catégorie + const effectiveEvaluation = currentEvaluation || { + category: selectedCategory, + skills: [], + selectedSkillIds: [], + }; + + const selectedSkillIds = effectiveEvaluation.selectedSkillIds || []; const filteredSkills = currentCategory.skills.filter( (skill) => diff --git a/services/evaluation-service.ts b/services/evaluation-service.ts index bdb5646..727cc40 100644 --- a/services/evaluation-service.ts +++ b/services/evaluation-service.ts @@ -228,12 +228,14 @@ export class EvaluationService { // 1. Upsert user const userId = await this.upsertUser(evaluation.profile); - // 2. Upsert user_evaluation + // 2. Upsert user_evaluation - d'abord supprimer l'ancienne si elle existe + await client.query("DELETE FROM user_evaluations WHERE user_id = $1", [ + userId, + ]); + const userEvalQuery = ` INSERT INTO user_evaluations (user_id, last_updated) VALUES ($1, $2) - ON CONFLICT (user_id) - DO UPDATE SET last_updated = $2 RETURNING id `; @@ -244,12 +246,6 @@ export class EvaluationService { const userEvaluationId = userEvalResult.rows[0].id; - // 3. Supprimer les anciennes évaluations de skills - await client.query( - "DELETE FROM skill_evaluations WHERE user_evaluation_id = $1", - [userEvaluationId] - ); - // 4. Sauvegarder les nouvelles évaluations directement for (const catEval of evaluation.evaluations) { await this.saveSkillEvaluations(client, userEvaluationId, catEval);