import type { Metadata } from 'next'; import Link from 'next/link'; import { notFound } from 'next/navigation'; import { benutzerNachId } from '@/lib/repos/benutzer'; import { ausbildungNachAzubi } from '@/lib/repos/ausbildung'; import { inhalte } from '@/lib/inhalte'; import { alsWochenblatt, notizenIm } from '@/lib/repos/berichtsheft'; import { staendeVon as aufgabenStaende } from '@/lib/repos/aufgaben'; import { laeufeVon } from '@/lib/repos/checklisten'; import { gelesenSet } from '@/lib/repos/fortschritt'; import { planVon } from '@/lib/repos/wochenplanung'; import { baueVorschlaege, type Rohdaten } from '@/lib/berichtsheft/vorschlaege'; import { pruefeWochenblatt, summeBetrieb, summeSchule, summeStunden } from '@/lib/berichtsheft/pruefung'; import { alsDatumText, alsZeitpunktText, kalenderwocheText } from '@/lib/zeit'; import { Blattformular } from '../Blattformular'; import { Formulierungshilfe } from '../Formulierungshilfe'; import { BerichtsMarke } from '../BerichtsMarke'; import { Abzeichnen } from './Abzeichnen'; import { blattZurueckziehen, blattZumLesen } from '../aktionen'; import { erfordereModul } from '@/lib/module/pruefen'; import { erfordereBenutzer } from '@/lib/auth/rechte'; import { modulStand } from '@/lib/repos/module'; export const dynamic = 'force-dynamic'; export async function generateMetadata({ params }: { params: Promise<{ berichtId: string }> }): Promise { const { berichtId } = await params; const gelesen = await blattZumLesen(berichtId); return { title: gelesen ? `Wochenblatt Nr. ${gelesen.bericht.nr}` : 'Wochenblatt' }; } export default async function BlattSeite({ params }: { params: Promise<{ berichtId: string }> }) { await erfordereBenutzer(); erfordereModul('berichtsheft'); const { berichtId } = await params; // Rechteprüfung steckt hier drin: kein Zugriff bedeutet null bedeutet 404. const gelesen = await blattZumLesen(berichtId); if (!gelesen) notFound(); const { benutzer, bericht } = gelesen; const eigenes = bericht.benutzerId === benutzer.id; const azubi = eigenes ? benutzer : benutzerNachId(bericht.benutzerId); if (!azubi) notFound(); const blatt = alsWochenblatt(bericht); const warnungen = pruefeWochenblatt(blatt); const vorschlaege = eigenes ? sammleVorschlaege(azubi.id, bericht.von, bericht.bis) : []; return (
Nr. {bericht.nr} {kalenderwocheText(bericht.von)}

{alsDatumText(bericht.von)} – {alsDatumText(bericht.bis)}

{azubi.name} {bericht.eingereichtAm ? ` · eingereicht ${alsZeitpunktText(bericht.eingereichtAm)}` : ''}

{bericht.status === 'abgezeichnet' ? (

✓ Abgezeichnet am {alsZeitpunktText(bericht.abgezeichnetAm)} {bericht.abgezeichnetVon ? ` von ${benutzerNachId(bericht.abgezeichnetVon)?.name ?? 'dem Ausbilder'}` : ''}. Das Blatt ist gesperrt.

) : null} {bericht.status === 'zurueckgegeben' && bericht.anmerkung ? (
Zur Nacharbeit zurückgegeben:

{bericht.anmerkung}

) : null} {bericht.status === 'abgezeichnet' && bericht.anmerkung ? (
Anmerkung des Ausbilders

{bericht.anmerkung}

) : null} {eigenes ? ( ) : ( )} {/* --- Werkzeuge --- */}
Dieses Blatt als PDF {eigenes && bericht.status === 'eingereicht' ? (
) : null}
{!eigenes ? (

Abzeichnen

) : null} {eigenes ? : null}
); } /** Die Nur-Lese-Ansicht für den Ausbilder – dieselben Daten, ohne Formular. */ function AnsichtFuerAusbilder({ blatt, warnungen, }: { blatt: ReturnType; warnungen: ReturnType; }) { return (

Betriebliche Tätigkeiten und Unterweisungen

{zahlText(summeBetrieb(blatt))} h
{blatt.betrieb.length === 0 ? (

Keine Eintragung.

) : (
    {blatt.betrieb.map((eintrag, stelle) => (
  • {eintrag.text} {eintrag.stunden > 0 ? `${zahlText(eintrag.stunden)} h` : '–'}
  • ))}
)}

Berufsschule

{zahlText(summeSchule(blatt))} h
{blatt.schule.length === 0 ? (

Keine Eintragung.

) : (
    {blatt.schule.map((eintrag, stelle) => (
  • {eintrag.lernfeld ? {eintrag.lernfeld} : null} {eintrag.themen} {eintrag.stunden > 0 ? `${zahlText(eintrag.stunden)} h` : '–'}
  • ))}
)}
{blatt.sonstiges ? (

Sonstiges

{blatt.sonstiges}

) : null}

Prüfung

{zahlText(summeStunden(blatt))} Stunden gesamt
{warnungen.length === 0 ? (

✓ Nichts zu beanstanden.

) : (
    {warnungen.map((warnung, stelle) => (
  • {warnung.text} {warnung.auszug ? – „{warnung.auszug}“ : null}
  • ))}
)}
); } /** Stellt zusammen, was die Anwendung über diese Woche weiß. */ function sammleVorschlaege(azubiId: string, von: string, bis: string) { const alle = inhalte(); // Aus abgeschalteten Modulen kommen keine Vorschläge. const eingeschaltet = modulStand(); const notizen = notizenIm(azubiId, von, bis).map((n) => ({ datum: n.datum, text: n.text, stunden: n.stunden, })); // Praxisaufgaben, die in dieser Woche abgegeben oder abgenommen wurden. const staende = aufgabenStaende(azubiId); const aufgaben = [...(eingeschaltet.aufgaben ? staende.values() : [])] .filter((s) => { const zeitpunkt = (s.abgenommenAm ?? s.abgegebenAm ?? '').slice(0, 10); return zeitpunkt >= von && zeitpunkt <= bis; }) .map((s) => { const aufgabe = alle.aufgabeNach.get(s.aufgabeId); return { id: s.aufgabeId, titel: aufgabe?.titel ?? s.aufgabeId, zeitrahmen: aufgabe?.zeitrahmen ?? '', status: s.status, }; }); const checklisten = (eingeschaltet.checklisten ? laeufeVon(azubiId) : []) .filter((l) => l.abgeschlossenAm !== null && l.datum >= von && l.datum <= bis) .map((l) => ({ id: l.id, titel: l.titel, ticket: l.ticket, kunde: l.kunde })); // Handouts der Wochen, die in diesem Zeitraum lagen – nur die gelesenen. const ausbildung = ausbildungNachAzubi(azubiId); const gelesen = gelesenSet(azubiId); const wochenImZeitraum = ausbildung ? planVon(ausbildung.id).filter((z) => z.geplantVon <= bis && z.geplantBis >= von) : []; const handouts = wochenImZeitraum .flatMap((z) => alle.wocheNach.get(z.wochenNummer)?.handouts ?? []) .filter((id) => gelesen.has(id)) .map((id) => ({ id, titel: alle.handoutNach.get(id)?.titel ?? id })); const lernfelder = [ ...new Set( wochenImZeitraum .flatMap((z) => alle.wocheNach.get(z.wochenNummer)?.handouts ?? []) .map((id) => alle.handoutNach.get(id)?.lernfeld) .filter((lf): lf is string => Boolean(lf)), ), ].map((id) => ({ id, titel: alle.lernfeldNach.get(id)?.titel ?? id })); const rohdaten: Rohdaten = { tagesnotizen: notizen, aufgaben, checklisten, handouts, lernfelder }; return baueVorschlaege(rohdaten); } function zahlText(wert: number): string { return (Math.round(wert * 100) / 100).toString().replace('.', ','); }