- 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>
147 lines
4.4 KiB
TypeScript
147 lines
4.4 KiB
TypeScript
'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>
|
||
);
|
||
}
|