feat: Betreuung, Kinderprofile und Aufnahmeverwaltung implementieren
Dashboard mit Abholslots und Filter-Scrolling, Anwesenheit mit Audit-Verlauf sowie Elternanmeldung, Warteliste und bestätigte Aufnahme ergänzen. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
1 parent
10af6159b4
commit
c1513c040b
36 files changed
+2593
No files matched your search
@@ -0,0 +1,32 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useTransition } from "react";
|
||||
import { Clock3, Plus } from "lucide-react";
|
||||
import { addSlot, toggleSlot } from "@/app/admission-actions";
|
||||
import type { PickupSlot } from "@/lib/slots";
|
||||
import type { ActionResult } from "@/lib/validation";
|
||||
|
||||
export function SlotManager({ slots }: { slots: PickupSlot[] }) {
|
||||
const [message, setMessage] = useState<ActionResult>({});
|
||||
const [pending, startTransition] = useTransition();
|
||||
function run(action: () => Promise<ActionResult>) {
|
||||
setMessage({});
|
||||
startTransition(async () => {
|
||||
try { setMessage(await action()); }
|
||||
catch (error) { console.error("Slot speichern", error); setMessage({ error: "Speichern fehlgeschlagen. Bitte erneut versuchen." }); }
|
||||
});
|
||||
}
|
||||
return <><div className="section-title"><div><span className="eyebrow">GEMEINSAM GUT ORGANISIERT</span><h1>Abholslots</h1><p>Feste Zeitfenster für einen entspannten Abschied.</p></div><Clock3 size={30} /></div>
|
||||
<div className="info-box"><p>Slots haben keine Kapazitätsgrenze. Ein deaktivierter Slot bleibt in bestehenden Plänen erhalten, wird aber nicht mehr neu angeboten. Für andere Zeiten einen neuen Slot anlegen; individuelle Abholzeiten bleiben möglich.</p></div>
|
||||
{message.error && <p className="form-error" role="alert">{message.error}</p>}
|
||||
{message.success && <p className="form-success" role="status">Abholslots gespeichert.</p>}
|
||||
<section className="slots-management">{slots.map((slot) => <article className="profile-panel slot-management-card" key={slot.id}><Clock3 size={21} />
|
||||
<div><h2>{slot.start}–{slot.end} Uhr</h2><p className="muted small">{slot.active ? "Für neue Pläne verfügbar" : "Inaktiv · bestehende Pläne bleiben erhalten"}</p></div>
|
||||
<button className="button secondary" disabled={pending} onClick={() => run(() => toggleSlot({ id: slot.id, active: !slot.active }))}>{slot.active ? "Deaktivieren" : "Aktivieren"}</button></article>)}</section>
|
||||
<section className="profile-panel"><h2>Neues Abholfenster</h2><form className="inline-form stack" onSubmit={(event) => {
|
||||
event.preventDefault(); const form = new FormData(event.currentTarget);
|
||||
run(() => addSlot({ start: form.get("start"), end: form.get("end") }));
|
||||
}}><label>Beginn<input name="start" type="time" required defaultValue="14:00" /></label><label>Ende<input name="end" type="time" required defaultValue="14:15" /></label>
|
||||
<button className="button primary" disabled={pending}><Plus size={16} />Slot anlegen</button></form></section>
|
||||
</>;
|
||||
}
|
||||
Reference in new issue
Block a user