From 328200f8b4c864e1d5a41e7cc190bbf5e2373cfa Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Fri, 20 Feb 2026 13:26:53 +0100 Subject: [PATCH] Update routing logic to redirect users to the dashboard after login and evaluation actions. Refactor middleware to handle public routes and adjust navigation links across the application for improved user experience. --- src/app/auth/login/page.tsx | 2 +- src/app/dashboard/page.tsx | 167 +++++++++++++++++++++++ src/app/evaluations/[id]/page.tsx | 6 +- src/app/page.tsx | 218 ++++++++---------------------- src/components/Header.tsx | 8 +- src/middleware.ts | 4 +- 6 files changed, 240 insertions(+), 165 deletions(-) create mode 100644 src/app/dashboard/page.tsx diff --git a/src/app/auth/login/page.tsx b/src/app/auth/login/page.tsx index 4ecbfd0..cad3c72 100644 --- a/src/app/auth/login/page.tsx +++ b/src/app/auth/login/page.tsx @@ -24,7 +24,7 @@ export default function LoginPage() { setError("Email ou mot de passe incorrect"); return; } - window.location.href = "/"; + window.location.href = "/dashboard"; } catch { setError("Erreur de connexion"); } finally { diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx new file mode 100644 index 0000000..a5a6cce --- /dev/null +++ b/src/app/dashboard/page.tsx @@ -0,0 +1,167 @@ +"use client"; + +import { useState, useEffect } from "react"; +import Link from "next/link"; +import { format } from "date-fns"; +import { ConfirmModal } from "@/components/ConfirmModal"; +import { RadarChart } from "@/components/RadarChart"; + +interface Dimension { + id: string; + title: string; +} + +interface EvalRow { + id: string; + candidateName: string; + candidateRole: string; + candidateTeam?: string | null; + evaluatorName: string; + evaluationDate: string; + template?: { name: string; dimensions?: Dimension[] }; + status: string; + dimensionScores?: { dimensionId: string; score: number | null; dimension?: { title: string } }[]; +} + +function buildRadarData(e: EvalRow) { + const dimensions = e.template?.dimensions ?? []; + const scoreMap = new Map( + (e.dimensionScores ?? []).map((ds) => [ds.dimensionId, ds]) + ); + return dimensions + .filter((dim) => !(dim.title ?? "").startsWith("[Optionnel]")) + .map((dim) => { + const ds = scoreMap.get(dim.id); + const score = ds?.score; + if (score == null) return null; + const s = Number(score); + if (Number.isNaN(s) || s < 0 || s > 5) return null; + const title = dim.title ?? ""; + return { + dimension: title.length > 12 ? title.slice(0, 12) + "…" : title, + score: s, + fullMark: 5, + }; + }) + .filter((d): d is { dimension: string; score: number; fullMark: number } => d != null); +} + +export default function DashboardPage() { + const [evaluations, setEvaluations] = useState([]); + const [loading, setLoading] = useState(true); + const [deleteTarget, setDeleteTarget] = useState(null); + + useEffect(() => { + fetch("/api/evaluations") + .then((r) => r.json()) + .then(setEvaluations) + .catch(() => []) + .finally(() => setLoading(false)); + }, []); + + return ( +
+
+

Évaluations

+ + + nouvelle + +
+ + {loading ? ( +
loading...
+ ) : evaluations.length === 0 ? ( +
+ Aucune évaluation.{" "} + + Créer + +
+ ) : ( +
+ {evaluations.map((e) => { + const radarData = buildRadarData(e); + return ( + +
+
+
+

{e.candidateName}

+

+ {e.candidateRole} + {e.candidateTeam && ` · ${e.candidateTeam}`} +

+
+ + {e.status === "submitted" ? "ok" : "draft"} + +
+
+ {e.evaluatorName} + {format(new Date(e.evaluationDate), "yyyy-MM-dd")} + {e.template?.name ?? ""} +
+
+ {radarData.length > 0 ? ( + + ) : ( +
+ pas de scores +
+ )} +
+
+
+ → ouvrir + +
+ + ); + })} +
+ )} + + { + if (!deleteTarget) return; + const res = await fetch(`/api/evaluations/${deleteTarget.id}`, { method: "DELETE" }); + if (res.ok) setEvaluations((prev) => prev.filter((x) => x.id !== deleteTarget.id)); + else alert("Erreur lors de la suppression"); + }} + onCancel={() => setDeleteTarget(null)} + /> +
+ ); +} diff --git a/src/app/evaluations/[id]/page.tsx b/src/app/evaluations/[id]/page.tsx index d3650e3..2c28c8f 100644 --- a/src/app/evaluations/[id]/page.tsx +++ b/src/app/evaluations/[id]/page.tsx @@ -212,7 +212,7 @@ export default function EvaluationDetailPage() { return (
Évaluation introuvable.{" "} - + ← dashboard
@@ -391,7 +391,7 @@ export default function EvaluationDetailPage() { > soumettre - - - - ); - })} - - )} + - { - if (!deleteTarget) return; - const res = await fetch(`/api/evaluations/${deleteTarget.id}`, { method: "DELETE" }); - if (res.ok) setEvaluations((prev) => prev.filter((x) => x.id !== deleteTarget.id)); - else alert("Erreur lors de la suppression"); - }} - onCancel={() => setDeleteTarget(null)} - /> +
+

+ Fonctionnalités +

+
    +
  • + Templates +

    + Grilles multi-dimensions (Full 15, Short 8) avec rubriques et signaux par niveau. +

    +
  • +
  • + Guide d'entretien +

    + Questions suggérées, relances IA, notation 1→5 avec justification et exemples. +

    +
  • +
  • + Radar & synthèse +

    + Visualisation radar, findings et recommandations générés automatiquement. +

    +
  • +
  • + Export +

    + Export PDF et CSV pour partage et archivage. +

    +
  • +
+
+ +
+

+ IA Gen Maturity Evaluator · Équipe Cars Front +

+
); } diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 17306b1..39163a8 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -14,9 +14,9 @@ export function Header() { iag-eval diff --git a/src/middleware.ts b/src/middleware.ts index 7dcc001..cfbe5f5 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -3,6 +3,7 @@ import { NextResponse } from "next/server"; export default auth((req) => { const isLoggedIn = !!req.auth; + const isPublicRoute = req.nextUrl.pathname === "/"; const isAuthRoute = req.nextUrl.pathname.startsWith("/auth/login") || req.nextUrl.pathname.startsWith("/auth/signup"); @@ -10,8 +11,9 @@ export default auth((req) => { const isAdminRoute = req.nextUrl.pathname.startsWith("/admin"); if (isApiAuth) return NextResponse.next(); + if (isPublicRoute) return NextResponse.next(); if (isAuthRoute && isLoggedIn) { - return NextResponse.redirect(new URL("/", req.nextUrl)); + return NextResponse.redirect(new URL("/dashboard", req.nextUrl)); } if (!isLoggedIn && !isAuthRoute) { return NextResponse.redirect(new URL("/auth/login", req.nextUrl));