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, }, }); });