'use server'; import { revalidatePath } from 'next/cache'; import { erfordereBenutzer, erfordereBewertungsrecht, erfordereZugriffAufAzubi } from '@/lib/auth/rechte'; import { inhalte } from '@/lib/inhalte'; import { anhangAblegen, anhangLoeschen, anhangNachId } from '@/lib/repos/anhaenge'; import { abnehmen, bewertungSetzen, notizSetzen, statusSetzen, standVon, zurueckgeben, } from '@/lib/repos/aufgaben'; import { aufgabenStatus, type AufgabenStatus } from '@/lib/db/schema'; import { pruefeModul } from '@/lib/module/pruefen'; export type Rueckmeldung = { fehler?: string; erfolg?: string }; function aktualisiere(aufgabeId: string) { revalidatePath('/aufgaben'); revalidatePath(`/aufgaben/${aufgabeId}`); revalidatePath('/'); } function aufgabeGibtEs(aufgabeId: string): boolean { return inhalte().aufgabeNach.has(aufgabeId); } // --- Der Azubi an seiner eigenen Aufgabe ----------------------------------- export async function eigenenStatusSetzen(formular: FormData): Promise { const benutzer = await erfordereBenutzer(); pruefeModul('aufgaben'); if (benutzer.rolle !== 'azubi') return; const aufgabeId = String(formular.get('aufgabeId') ?? ''); const status = String(formular.get('status') ?? '') as AufgabenStatus; if (!aufgabeGibtEs(aufgabeId)) return; if (!aufgabenStatus.includes(status)) return; // Abnehmen darf nur der Ausbilder. if (status === 'abgenommen') return; statusSetzen(benutzer.id, aufgabeId, status); aktualisiere(aufgabeId); } export async function eigeneNotizSpeichern(_vorher: Rueckmeldung, formular: FormData): Promise { const benutzer = await erfordereBenutzer(); pruefeModul('aufgaben'); if (benutzer.rolle !== 'azubi') return { fehler: 'Nur der Azubi schreibt seine eigenen Notizen.' }; const aufgabeId = String(formular.get('aufgabeId') ?? ''); const notiz = String(formular.get('notiz') ?? ''); if (!aufgabeGibtEs(aufgabeId)) return { fehler: 'Diese Aufgabe gibt es nicht.' }; if (notiz.length > 8000) return { fehler: 'Die Notiz ist zu lang – höchstens 8000 Zeichen.' }; notizSetzen(benutzer.id, aufgabeId, notiz); aktualisiere(aufgabeId); return { erfolg: 'Notiz gespeichert.' }; } export async function anhangHochladen(_vorher: Rueckmeldung, formular: FormData): Promise { const benutzer = await erfordereBenutzer(); pruefeModul('aufgaben'); if (benutzer.rolle !== 'azubi') return { fehler: 'Anhänge lädt der Azubi hoch.' }; const aufgabeId = String(formular.get('aufgabeId') ?? ''); if (!aufgabeGibtEs(aufgabeId)) return { fehler: 'Diese Aufgabe gibt es nicht.' }; const stand = standVon(benutzer.id, aufgabeId); if (stand?.status === 'abgenommen') { return { fehler: 'Die Aufgabe ist abgenommen – sie lässt sich nicht mehr ändern.' }; } const dateien = formular.getAll('datei').filter((d): d is File => d instanceof File && d.size > 0); if (dateien.length === 0) return { fehler: 'Keine Datei ausgewählt.' }; const beschriftung = String(formular.get('beschriftung') ?? ''); const fehler: string[] = []; let angelegt = 0; for (const datei of dateien) { const ergebnis = await anhangAblegen({ bezugTyp: 'aufgabe', // Der Bezug ist Aufgabe **und** Azubi – sonst sähe ein zweiter Azubi // die Anhänge des ersten an derselben Aufgabe. bezugId: `${aufgabeId}::${benutzer.id}`, benutzerId: benutzer.id, datei, beschriftung: dateien.length === 1 ? beschriftung : undefined, }); if ('fehler' in ergebnis) { fehler.push(`${datei.name}: ${ergebnis.fehler}`); } else { angelegt += 1; } } aktualisiere(aufgabeId); if (angelegt === 0) return { fehler: fehler.join(' · ') }; if (fehler.length > 0) { return { fehler: `${angelegt} übernommen, aber: ${fehler.join(' · ')}` }; } return { erfolg: `${angelegt} ${angelegt === 1 ? 'Anhang' : 'Anhänge'} hinzugefügt.` }; } export async function anhangEntfernen(formular: FormData): Promise { const benutzer = await erfordereBenutzer(); pruefeModul('aufgaben'); const anhangId = String(formular.get('anhangId') ?? ''); const aufgabeId = String(formular.get('aufgabeId') ?? ''); const eintrag = anhangNachId(anhangId); if (!eintrag) return; // Nur der eigene Anhang, und nur solange die Aufgabe nicht abgenommen ist. if (eintrag.benutzerId !== benutzer.id) return; const stand = standVon(benutzer.id, aufgabeId); if (stand?.status === 'abgenommen') return; await anhangLoeschen(anhangId); aktualisiere(aufgabeId); } // --- Der Ausbilder an der Aufgabe seines Azubis ---------------------------- export async function bewerten(_vorher: Rueckmeldung, formular: FormData): Promise { const ausbilder = await erfordereBenutzer(); pruefeModul('aufgaben'); const azubiId = String(formular.get('azubiId') ?? ''); const aufgabeId = String(formular.get('aufgabeId') ?? ''); erfordereBewertungsrecht(ausbilder, azubiId); const aufgabe = inhalte().aufgabeNach.get(aufgabeId); if (!aufgabe) return { fehler: 'Diese Aufgabe gibt es nicht.' }; const kriterien = formular .getAll('kriterium') .map((wert) => Number(wert)) .filter((n) => Number.isInteger(n) && n >= 0 && n < aufgabe.kriterien.length); const bewertung = String(formular.get('bewertung') ?? '').trim(); const rueckmeldung = String(formular.get('rueckmeldung') ?? '').trim(); if (bewertung.length > 60) return { fehler: 'Die Bewertung ist zu lang – höchstens 60 Zeichen.' }; if (rueckmeldung.length > 4000) return { fehler: 'Die Rückmeldung ist zu lang – höchstens 4000 Zeichen.' }; bewertungSetzen(azubiId, aufgabeId, { kriterien, bewertung: bewertung || null, rueckmeldung: rueckmeldung || null, }); aktualisiere(aufgabeId); return { erfolg: `Bewertung gespeichert – ${kriterien.length} von ${aufgabe.kriterien.length} Kriterien erfüllt.` }; } export async function aufgabeAbnehmen(formular: FormData): Promise { const ausbilder = await erfordereBenutzer(); pruefeModul('aufgaben'); const azubiId = String(formular.get('azubiId') ?? ''); const aufgabeId = String(formular.get('aufgabeId') ?? ''); erfordereBewertungsrecht(ausbilder, azubiId); if (!aufgabeGibtEs(aufgabeId)) return; abnehmen(azubiId, aufgabeId, ausbilder.id); aktualisiere(aufgabeId); } export async function aufgabeZurueckgeben(formular: FormData): Promise { const ausbilder = await erfordereBenutzer(); pruefeModul('aufgaben'); const azubiId = String(formular.get('azubiId') ?? ''); const aufgabeId = String(formular.get('aufgabeId') ?? ''); erfordereBewertungsrecht(ausbilder, azubiId); if (!aufgabeGibtEs(aufgabeId)) return; zurueckgeben(azubiId, aufgabeId); aktualisiere(aufgabeId); } /** Wird von der Aufgabenseite gebraucht, um fremde Daten überhaupt lesen zu dürfen. */ export async function pruefeLesezugriff(azubiId: string): Promise { const benutzer = await erfordereBenutzer(); pruefeModul('aufgaben'); erfordereZugriffAufAzubi(benutzer, azubiId); }