import { inhalte, type Handout, type Aufgabe } from '../inhalte'; import type { Checkliste, Kontrolle, Woche } from '../inhalte/schema'; import { gelesenSet } from '../repos/fortschritt'; import { planVon } from '../repos/wochenplanung'; import { uebersicht as kartenUebersicht } from '../repos/karten'; import { anzahlAbgenommen } from '../repos/aufgaben'; import { anzahlAbgeschlossen } from '../repos/checklisten'; import { heute } from '../zeit'; import { aktuelleWoche } from './wochen'; import { wochenFortschritt, type Fortschritt } from './fortschritt'; import type { Wochenplanung } from '../db/schema'; /** * Setzt aus Inhalt (Datei), Planung (Datenbank) und Fortschritt (Datenbank) * die Wochenansicht zusammen. Alles, was die Startseite braucht, kommt hier her. */ export type Tagessicht = { tag: string; theorie: Handout[]; praxis: string; /** Der Tag, der im Kalender zu diesem Wochentag gehört. */ datum: string; istHeute: boolean; }; export type Wochensicht = { woche: Woche; planung: Wochenplanung; fortschritt: Fortschritt; tage: Tagessicht[]; handouts: { handout: Handout; gelesen: boolean }[]; aufgaben: Aufgabe[]; checklisten: Checkliste[]; kontrolle: Kontrolle | null; vorherige: number | null; naechste: number | null; }; export function wochensicht(ausbildungId: string, azubiId: string, wochenNummer: number): Wochensicht | null { const alle = inhalte(); const woche = alle.wocheNach.get(wochenNummer); if (!woche) return null; const plan = planVon(ausbildungId); const planung = plan.find((z) => z.wochenNummer === wochenNummer); if (!planung) return null; const gelesen = gelesenSet(azubiId); const heuteDatum = heute(); const handouts = woche.handouts .map((id) => alle.handoutNach.get(id)) .filter((h) => h !== undefined) .map((handout) => ({ handout, gelesen: gelesen.has(handout.id) })); const tage: Tagessicht[] = woche.tage.map((tag, stelle) => { const datum = tagVersetzt(planung.geplantVon, stelle); return { tag: tag.tag, praxis: tag.praxis, datum, istHeute: datum === heuteDatum, theorie: tag.theorie.map((id) => alle.handoutNach.get(id)).filter((h) => h !== undefined), }; }); const aufgaben = woche.aufgaben.map((id) => alle.aufgabeNach.get(id)).filter((a) => a !== undefined); const checklisten = woche.checklisten.map((id) => alle.checklisteNach.get(id)).filter((c) => c !== undefined); const kontrolle = woche.lernzielkontrolle ? (alle.kontrolleNach.get(woche.lernzielkontrolle) ?? null) : null; // Die Merkkarten dieser Woche sind die Karten ihrer Handouts. const karteIds = handouts.flatMap(({ handout }) => alle.karten.filter((k) => k.handoutId === handout.id).map((k) => k.id), ); const kartenStand = kartenUebersicht(azubiId, karteIds, heuteDatum); const fortschritt = wochenFortschritt({ handouts: { erledigt: handouts.filter((h) => h.gelesen).length, gesamt: handouts.length }, karten: { erledigt: kartenStand.gelernt, gesamt: kartenStand.gesamt }, aufgaben: { erledigt: anzahlAbgenommen(azubiId, aufgaben.map((a) => a.id)), gesamt: aufgaben.length }, // Diese Bereiche werden mit ihren Bausteinen scharf geschaltet. Bis dahin // zeigen sie ehrlich an, was die Woche vorsieht und noch offen ist. checklisten: { erledigt: anzahlAbgeschlossen(azubiId, checklisten.map((c) => c.id)), gesamt: checklisten.length, }, kontrolle: { erledigt: 0, gesamt: kontrolle ? 1 : 0 }, }); const nummern = plan.map((z) => z.wochenNummer); const stelle = plan.findIndex((z) => z.wochenNummer === wochenNummer); return { woche, planung, fortschritt, tage, handouts, aufgaben, checklisten, kontrolle, vorherige: stelle > 0 ? (nummern[stelle - 1] ?? null) : null, naechste: stelle < nummern.length - 1 ? (nummern[stelle + 1] ?? null) : null, }; } /** Die Woche, die gerade dran ist. */ export function aktuelleWochensicht(ausbildungId: string, azubiId: string): Wochensicht | null { const plan = planVon(ausbildungId); const dran = aktuelleWoche(plan, heute()); if (!dran) return null; return wochensicht(ausbildungId, azubiId, dran.wochenNummer); } /** Kurzstand für die Ausbilderübersicht – ohne den ganzen Wochenaufbau. */ export type Kurzstand = { wochenNummer: number; titel: string; geplantVon: string; geplantBis: string; status: Wochenplanung['status']; fortschritt: Fortschritt; handoutsGelesen: number; handoutsGesamt: number; }; export function kurzstand(ausbildungId: string, azubiId: string): Kurzstand | null { const sicht = aktuelleWochensicht(ausbildungId, azubiId); if (!sicht) return null; return { wochenNummer: sicht.woche.nummer, titel: sicht.woche.titel, geplantVon: sicht.planung.geplantVon, geplantBis: sicht.planung.geplantBis, status: sicht.planung.status, fortschritt: sicht.fortschritt, handoutsGelesen: sicht.handouts.filter((h) => h.gelesen).length, handoutsGesamt: sicht.handouts.length, }; } function tagVersetzt(montag: string, tage: number): string { const d = new Date(`${montag}T12:00:00Z`); d.setUTCDate(d.getUTCDate() + tage); return d.toISOString().slice(0, 10); }