feat(frontend): router restructure /admin → /lessons with redirects

This commit is contained in:
2026-05-21 07:16:17 +02:00
parent d5dfc0d2db
commit 9928390946
3 changed files with 17 additions and 12 deletions

View File

@@ -114,7 +114,7 @@ function TreeRow({ n, depth }: { n: LessonTreeNode; depth: number }) {
></span>
)}
<span className={`h-2 w-2 rounded-full ${depth === 0 ? 'bg-brand-500' : 'bg-brand-300'}`} />
<Link to={`/admin/lessons/${n.id}`} className="flex-1 truncate font-medium text-slate-800 dark:text-slate-100">
<Link to={`/lessons/${n.id}`} className="flex-1 truncate font-medium text-slate-800 dark:text-slate-100">
{n.name}
<span className="ml-2 rounded-full bg-brand-100 px-2 py-0.5 text-xs font-semibold text-brand-700 dark:bg-brand-900/30 dark:text-brand-200">
{n.cardCount}

View File

@@ -33,7 +33,7 @@ export function MarketplacePage() {
async function fork(id: number) {
try {
const f = await lessonsApi.fork(id);
navigate(`/admin/lessons/${f.id}`);
navigate(`/lessons/${f.id}`);
}
catch (e) { alert(e instanceof ApiClientError ? e.message : 'Forken mislukt'); }
}

View File

@@ -1,10 +1,9 @@
import { lazy, Suspense, type ComponentType } from 'react';
import { createBrowserRouter, Navigate } from 'react-router-dom';
import { createBrowserRouter, Navigate, useParams } from 'react-router-dom';
import { Layout } from './components/Layout.js';
import { AuthBoundary } from './components/AuthBoundary.js';
import { RoleGuard } from './components/RoleGuard.js';
// Tiny loading placeholder reused for every lazy route boundary.
function PageFallback() {
return (
<div className="flex h-full items-center justify-center p-12">
@@ -13,8 +12,6 @@ function PageFallback() {
);
}
// `React.lazy` requires a default export; our pages use named exports, so we
// adapt with a small helper that picks the named export from the module.
function lazyPage<K extends string>(
loader: () => Promise<Record<K, ComponentType>>,
name: K,
@@ -33,8 +30,8 @@ function lazyPage<K extends string>(
}
const Dashboard = lazyPage(() => import('./pages/Dashboard.js'), 'DashboardPage');
const Admin = lazyPage(() => import('./pages/Admin.js'), 'AdminPage');
const AdminLesson = lazyPage(() => import('./pages/AdminLesson.js'), 'AdminLessonPage');
const Lessons = lazyPage(() => import('./pages/Lessons.js'), 'LessonsPage');
const LessonDetail = lazyPage(() => import('./pages/LessonDetail.js'), 'LessonDetailPage');
const PracticeSetup = lazyPage(() => import('./pages/PracticeSetup.js'), 'PracticeSetupPage');
const Practice = lazyPage(() => import('./pages/Practice.js'), 'PracticePage');
const PracticeDone = lazyPage(() => import('./pages/PracticeDone.js'), 'PracticeDonePage');
@@ -53,12 +50,17 @@ const ForgotPassword = lazyPage(() => import('./pages/auth/ForgotPassword.js'),
const ResetPassword = lazyPage(() => import('./pages/auth/ResetPassword.js'), 'ResetPasswordPage');
const AcceptInvite = lazyPage(() => import('./pages/auth/AcceptInvite.js'), 'AcceptInvitePage');
function AdminToLessons() { return <Navigate to="/lessons" replace />; }
function AdminLessonRedirect() {
const { id } = useParams();
return <Navigate to={`/lessons/${id ?? ''}`} replace />;
}
export const router = createBrowserRouter([
{
path: '/',
element: <Layout />,
children: [
// Public auth routes
{ path: 'login', element: <Login /> },
{ path: 'register', element: <Register /> },
{ path: 'verify-email', element: <VerifyEmail /> },
@@ -66,13 +68,16 @@ export const router = createBrowserRouter([
{ path: 'reset-password', element: <ResetPassword /> },
{ path: 'accept-invite', element: <AcceptInvite /> },
// Authenticated routes
{
element: <AuthBoundary />,
children: [
{ index: true, element: <Dashboard /> },
{ path: 'admin', element: <Admin /> },
{ path: 'admin/lessons/:id', element: <AdminLesson /> },
{ path: 'lessons', element: <Lessons /> },
{ path: 'lessons/:id', element: <LessonDetail /> },
{ path: 'admin', element: <AdminToLessons /> },
{ path: 'admin/lessons/:id', element: <AdminLessonRedirect /> },
{ path: 'practice/:lessonId/setup', element: <PracticeSetup /> },
{ path: 'practice/:lessonId', element: <Practice /> },
{ path: 'practice/:lessonId/done', element: <PracticeDone /> },