Files
lernbar/src/app/(angemeldet)/wochenplan/Formulare.tsx
T
Florian WildeandClaude Opus 5 103a603eb4 Baustein 3: Wochenplan als Startseite, Fortschritt, Wochen verschieben
- Wochenplan ist die Startseite des Azubis: Thema, Leitfrage, fuenf Tage
  mit Theorie und Praxis, Fortschrittsbalken, was noch offen ist
- Ausbilder sieht je Azubi die laufende Woche mit Stand und offenen Punkten
- /woche/<nr> fuer jede Woche, Ausbilder waehlt ueber ?azubi= den Stand;
  Zugriff wird serverseitig bei jedem Aufruf geprueft
- Tabelle wochenplanung mit geplantem und tatsaechlichem Datum, Zustand
  und Notiz fuer den Azubi
- Verschieben per Datumsfeld, wahlweise mit allen folgenden Wochen
- Reihenfolge per Ziehen und Ablegen sowie per Tastatur (Alt + Pfeil)
- Warnung bei sich ueberlappenden Terminen
- Plan entsteht automatisch beim Anlegen eines Azubikontos
- Planungs- und Fortschrittslogik als reine Funktionen, 36 Tests dafuer
- Insgesamt 104 Tests

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 09:04:39 +02:00

147 lines
4.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { useActionState } from 'react';
import { Absenden, Meldung } from '@/komponenten/Formularmeldung';
import { planErzeugen, wochenNotiz, wocheVerlegen, wochenStatusSetzen, type Rueckmeldung } from './aktionen';
export function PlanErzeugenFormular({ azubiId, text }: { azubiId: string; text: string }) {
const [zustand, aktion] = useActionState<Rueckmeldung, FormData>(planErzeugen, {});
return (
<form action={aktion} className="stapel-eng">
<Meldung zustand={zustand} />
<input type="hidden" name="azubiId" value={azubiId} />
<Absenden className="knopf knopf-akzent">{text}</Absenden>
</form>
);
}
export function VerlegenFormular({
azubiId,
wochen,
}: {
azubiId: string;
wochen: { nummer: number; titel: string; geplantVon: string }[];
}) {
const [zustand, aktion] = useActionState<Rueckmeldung, FormData>(wocheVerlegen, {});
const erste = wochen[0];
return (
<form action={aktion} className="stapel">
<Meldung zustand={zustand} />
<input type="hidden" name="azubiId" value={azubiId} />
<div className="reihe" style={{ alignItems: 'flex-end' }}>
<div style={{ flex: '2 1 240px' }}>
<label htmlFor="verlegen-woche">Woche</label>
<select id="verlegen-woche" name="wochenNummer" defaultValue={erste?.nummer}>
{wochen.map((w) => (
<option key={w.nummer} value={w.nummer}>
Woche {w.nummer} – {w.titel}
</option>
))}
</select>
</div>
<div style={{ flex: '1 1 170px' }}>
<label htmlFor="verlegen-datum">Neuer Beginn</label>
<input id="verlegen-datum" name="neuerMontag" type="date" defaultValue={erste?.geplantVon} required />
</div>
<Absenden className="knopf">Verlegen</Absenden>
</div>
<label className="ankreuzfeld">
<input type="checkbox" name="folgende" value="an" defaultChecked />
<span>
Folgende Wochen mitverschieben
<span className="leise" style={{ display: 'block' }}>
Der Normalfall: Fällt eine Woche aus, rutscht der ganze Rest hinterher. Ohne Haken wird nur diese
eine Woche verlegt – dann können sich Termine überlappen.
</span>
</span>
</label>
<p className="leise" style={{ margin: 0 }}>
Ein beliebiges Datum wird auf den Montag seiner Woche gerundet. Abgeschlossene Wochen bleiben stehen.
</p>
</form>
);
}
export function StatusFormular({
azubiId,
wochenNummer,
status,
}: {
azubiId: string;
wochenNummer: number;
status: 'geplant' | 'laufend' | 'abgeschlossen';
}) {
return (
<form action={wochenStatusSetzen} className="reihe" style={{ gap: '0.35rem' }}>
<input type="hidden" name="azubiId" value={azubiId} />
<input type="hidden" name="wochenNummer" value={wochenNummer} />
<button
type="submit"
name="status"
value="laufend"
className="knopf knopf-still"
disabled={status === 'laufend'}
>
Startet jetzt
</button>
<button
type="submit"
name="status"
value="abgeschlossen"
className="knopf knopf-still"
disabled={status === 'abgeschlossen'}
>
Abschließen
</button>
<button
type="submit"
name="status"
value="geplant"
className="knopf knopf-still"
disabled={status === 'geplant'}
>
Zurücksetzen
</button>
</form>
);
}
export function NotizFormular({
azubiId,
wochenNummer,
notiz,
}: {
azubiId: string;
wochenNummer: number;
notiz: string;
}) {
const [zustand, aktion] = useActionState<Rueckmeldung, FormData>(wochenNotiz, {});
return (
<form action={aktion} className="stapel-eng">
<Meldung zustand={zustand} />
<input type="hidden" name="azubiId" value={azubiId} />
<input type="hidden" name="wochenNummer" value={wochenNummer} />
<label htmlFor={`notiz-${wochenNummer}`}>Notiz zu dieser Woche (sieht der Azubi)</label>
<textarea
id={`notiz-${wochenNummer}`}
name="notiz"
defaultValue={notiz}
rows={2}
maxLength={500}
placeholder="z. B. Dienstag Berufsschule, Mittwoch Kundeneinsatz Halle 3"
/>
<div>
<Absenden className="knopf knopf-zweit">Notiz speichern</Absenden>
</div>
</form>
);
}