feat: handling SSR on evaluation

This commit is contained in:
Julien Froidefond
2025-08-21 13:19:46 +02:00
parent 69f23db55d
commit ef16c73625
7 changed files with 481 additions and 135 deletions

View File

@@ -1,28 +1,40 @@
import { NextRequest, NextResponse } from "next/server";
import { cookies } from "next/headers";
import { evaluationService } from "@/services/evaluation-service";
import { UserProfile, SkillLevel } from "@/lib/types";
const COOKIE_NAME = "peakSkills_userId";
export async function PUT(request: NextRequest) {
try {
const body = await request.json();
const {
profile,
category,
skillId,
level,
canMentor,
wantsToLearn,
action,
} = body;
// Récupérer l'utilisateur depuis le cookie
const cookieStore = await cookies();
const userId = cookieStore.get(COOKIE_NAME)?.value;
if (!profile || !category || !skillId) {
if (!userId) {
return NextResponse.json(
{ error: "profile, category et skillId sont requis" },
{ status: 400 }
{ error: "Utilisateur non authentifié" },
{ status: 401 }
);
}
const userProfile: UserProfile = profile;
const userProfile = await evaluationService.getUserById(parseInt(userId));
if (!userProfile) {
return NextResponse.json(
{ error: "Utilisateur introuvable" },
{ status: 404 }
);
}
const body = await request.json();
const { category, skillId, level, canMentor, wantsToLearn, action } = body;
if (!category || !skillId) {
return NextResponse.json(
{ error: "category et skillId sont requis" },
{ status: 400 }
);
}
switch (action) {
case "updateLevel":

View File

@@ -1,106 +1,49 @@
"use client";
import { useEffect } from "react";
import { useEvaluation } from "@/hooks/use-evaluation";
import { ProfileForm } from "@/components/profile-form";
import { SkillEvaluation } from "@/components/skill-evaluation";
import { useUser } from "@/hooks/use-user-context";
import { redirect } from "next/navigation";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
isUserAuthenticated,
getServerUserEvaluation,
getServerSkillCategories,
getServerTeams,
} from "@/lib/server-auth";
import {
EvaluationClientWrapper,
WelcomeEvaluationScreen,
} from "@/components/evaluation";
import { SkillEvaluation } from "@/components/skill-evaluation";
export default function EvaluationPage() {
const {
userEvaluation,
skillCategories,
teams,
loading,
updateProfile,
updateSkillLevel,
updateSkillMentorStatus,
updateSkillLearningStatus,
addSkillToEvaluation,
removeSkillFromEvaluation,
initializeEmptyEvaluation,
} = useEvaluation();
export default async function EvaluationPage() {
// Vérifier l'authentification
const isAuthenticated = await isUserAuthenticated();
const { setUserInfo } = useUser();
// Update user info in navigation when user evaluation is loaded
useEffect(() => {
if (userEvaluation) {
const teamName =
teams.find((t) => t.id === userEvaluation.profile.teamId)?.name || "";
setUserInfo({
firstName: userEvaluation.profile.firstName,
lastName: userEvaluation.profile.lastName,
teamName,
});
} else {
setUserInfo(null);
}
}, [userEvaluation, teams, setUserInfo]);
if (loading) {
return (
<div className="container mx-auto py-8">
<div className="flex items-center justify-center min-h-[400px]">
<div className="text-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary mx-auto mb-4"></div>
<p>Chargement...</p>
</div>
</div>
</div>
);
// Si pas de cookie d'authentification, rediriger vers login
if (!isAuthenticated) {
redirect("/login");
}
// If no user evaluation exists, show profile form
// Charger les données côté serveur
const [userEvaluation, skillCategories, teams] = await Promise.all([
getServerUserEvaluation(),
getServerSkillCategories(),
getServerTeams(),
]);
// Si pas d'évaluation, afficher l'écran d'accueil évaluation
if (!userEvaluation) {
const handleProfileSubmit = (profile: any) => {
initializeEmptyEvaluation(profile);
};
return (
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950 relative overflow-hidden">
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-blue-900/20 via-slate-900 to-slate-950" />
<div className="absolute inset-0 bg-grid-white/5 bg-[size:50px_50px]" />
<div className="relative z-10 container mx-auto py-16 px-6">
<div className="text-center mb-12">
<h1 className="text-4xl font-bold mb-4 text-white">
Commencer l'évaluation
</h1>
<p className="text-lg text-slate-400 mb-8">
Renseignez vos informations pour débuter votre auto-évaluation
</p>
</div>
<div className="max-w-2xl mx-auto">
<ProfileForm teams={teams} onSubmit={handleProfileSubmit} />
</div>
</div>
</div>
);
return <WelcomeEvaluationScreen teams={teams} />;
}
return (
<div>
{/* Skill Evaluation */}
{skillCategories.length > 0 && userEvaluation.evaluations.length > 0 && (
<SkillEvaluation
categories={skillCategories}
evaluations={userEvaluation.evaluations}
onUpdateSkill={updateSkillLevel}
onUpdateMentorStatus={updateSkillMentorStatus}
onUpdateLearningStatus={updateSkillLearningStatus}
onAddSkill={addSkillToEvaluation}
onRemoveSkill={removeSkillFromEvaluation}
/>
)}
</div>
<EvaluationClientWrapper userEvaluation={userEvaluation} teams={teams}>
<div>
{/* Skill Evaluation */}
{skillCategories.length > 0 &&
userEvaluation.evaluations.length > 0 && (
<SkillEvaluation
categories={skillCategories}
evaluations={userEvaluation.evaluations}
/>
)}
</div>
</EvaluationClientWrapper>
);
}