147 lines
5.6 KiB
TypeScript

import { Router } from "express";
import { standardsLessons } from "../data/training/standards";
import { formFactorLessons } from "../data/training/form-factors";
import { switchesLessons } from "../data/training/switches";
import { infrastructureLessons } from "../data/training/infrastructure";
import { testingBuyingLessons } from "../data/training/testing-buying";
import type { TrainingLesson } from "../data/training/types";
export const trainingRouter = Router();
// ── Aggregate all lessons ────────────────────────────────────────────────────
const ALL_LESSONS: TrainingLesson[] = [
...standardsLessons,
...formFactorLessons,
...switchesLessons,
...infrastructureLessons,
...testingBuyingLessons,
];
// ── Category metadata ────────────────────────────────────────────────────────
const CATEGORIES = [
{
id: "standards",
title: "Standards",
title_de: "Standards",
icon: "📋",
description: "IEEE 802.3, MSA, DOM/DDMI — the foundation of optical networking",
description_de: "IEEE 802.3, MSA, DOM/DDMI — das Fundament optischer Netzwerke",
},
{
id: "form-factors",
title: "Form Factors",
title_de: "Formfaktoren",
icon: "🔌",
description: "SFP, QSFP-DD, OSFP, connectors — physical housings and interfaces",
description_de: "SFP, QSFP-DD, OSFP, Stecker — physikalische Gehäuse und Interfaces",
},
{
id: "switches",
title: "Switches & Compatibility",
title_de: "Switches & Kompatibilität",
icon: "🖥️",
description: "Vendor lock, FEC configuration, Cisco / Juniper / Arista CLI",
description_de: "Vendor-Lock, FEC-Konfiguration, Cisco / Juniper / Arista CLI",
},
{
id: "infrastructure",
title: "Fiber & Infrastructure",
title_de: "Glasfaser & Infrastruktur",
icon: "🔧",
description: "MMF/SMF grades, link budget math, MPO, WDM wavelength planning",
description_de: "MMF/SMF-Typen, Link-Budget-Berechnung, MPO, WDM-Wellenlägenplanung",
},
{
id: "testing-buying",
title: "Testing & Buying",
title_de: "Testen & Einkaufen",
icon: "🔬",
description: "Test equipment, OEM vs. compatible, datasheet interpretation, TCO",
description_de: "Messgeräte, OEM vs. kompatibel, Datenblatt-Interpretation, TCO",
},
];
// ── GET /api/training/categories ─────────────────────────────────────────────
trainingRouter.get("/categories", (_req, res) => {
const result = CATEGORIES.map((cat) => ({
...cat,
lesson_count: ALL_LESSONS.filter((l) => l.category === cat.id).length,
total_duration_min: ALL_LESSONS
.filter((l) => l.category === cat.id)
.reduce((sum, l) => sum + l.duration_min, 0),
quiz_count: ALL_LESSONS
.filter((l) => l.category === cat.id)
.reduce((sum, l) => sum + l.quiz.length, 0),
}));
res.json(result);
});
// ── GET /api/training/lessons?category= ──────────────────────────────────────
trainingRouter.get("/lessons", (req, res) => {
const { category } = req.query;
let lessons = ALL_LESSONS;
if (category && typeof category === "string") {
lessons = lessons.filter((l) => l.category === category);
}
// Return metadata only — omit heavy sections + quiz content
res.json(
lessons.map(({ id, category, title, title_de, level, duration_min, summary, summary_de, tags }) => ({
id,
category,
title,
title_de,
level,
duration_min,
summary,
summary_de,
tags,
}))
);
});
// ── GET /api/training/lessons/:id ────────────────────────────────────────────
trainingRouter.get("/lessons/:id", (req, res) => {
const lesson = ALL_LESSONS.find((l) => l.id === req.params.id);
if (!lesson) {
return res.status(404).json({ error: "Lesson not found" });
}
return res.json(lesson);
});
// ── GET /api/training/quiz?lesson=&category= ─────────────────────────────────
trainingRouter.get("/quiz", (req, res) => {
const { lesson, category } = req.query;
let questions = ALL_LESSONS.flatMap((l) => l.quiz);
if (lesson && typeof lesson === "string") {
questions = questions.filter((q) => q.lesson === lesson);
} else if (category && typeof category === "string") {
const catLessonIds = ALL_LESSONS.filter((l) => l.category === category).map((l) => l.id);
questions = questions.filter((q) => catLessonIds.includes(q.lesson));
}
res.json(questions);
});
// ── GET /api/training/stats ───────────────────────────────────────────────────
trainingRouter.get("/stats", (_req, res) => {
res.json({
total_lessons: ALL_LESSONS.length,
total_quiz_questions: ALL_LESSONS.reduce((s, l) => s + l.quiz.length, 0),
total_duration_min: ALL_LESSONS.reduce((s, l) => s + l.duration_min, 0),
categories: CATEGORIES.length,
levels: {
beginner: ALL_LESSONS.filter((l) => l.level === "beginner").length,
intermediate: ALL_LESSONS.filter((l) => l.level === "intermediate").length,
advanced: ALL_LESSONS.filter((l) => l.level === "advanced").length,
},
});
});