Files
Laufzettel/src/components/vorlage-kopfdaten.tsx
T
florian.wilde f85bc87324
Prüfung / pruefung (push) Canceled after 0s
Prüfung / e2e (push) Canceled after 0s
feat(stammdaten): Mitarbeiter, Abteilungen und Geraete (#25)
2026-09-25 10:52:44 +00:00

93 lines
3.2 KiB
TypeScript

"use client";
import { useActionState } from "react";
import { Button } from "@/components/ui/button";
import { vorlageBearbeitenAktion, type AktionsErgebnis } from "@/server/actions/vorlagen";
import { FELD } from "@/lib/formular";
/**
* Kopfdaten einer Vorlage: Name, Beschreibung, Kategorie, Schlagworte, Kunde.
*
* Sie haengen an der Vorlage, nicht an einer Version — deshalb lassen sie sich
* jederzeit aendern, auch wenn die neueste Version veroeffentlicht ist. Ein
* Tippfehler im Namen soll keine neue Version kosten, und die Schritte, auf die
* ein Lauf verweist, bleiben davon unberuehrt.
*/
export function VorlageKopfdaten({
vorlage,
kunden,
}: {
vorlage: {
readonly id: string;
readonly name: string;
readonly beschreibung: string | null;
readonly kategorie: string | null;
readonly schlagworte: readonly string[];
readonly kundeId: string | null;
};
kunden: readonly { id: string; name: string }[];
}) {
const [ergebnis, aktion, laeuft] = useActionState<AktionsErgebnis, FormData>(vorlageBearbeitenAktion, {});
return (
<form action={aktion} className="flex flex-col gap-4">
<input type="hidden" name="vorlageId" value={vorlage.id} />
<label className="flex flex-col gap-1.5 text-sm">
<span className="text-nebentext">Name</span>
<input name="name" required defaultValue={vorlage.name} className={FELD} />
</label>
<label className="flex flex-col gap-1.5 text-sm">
<span className="text-nebentext">Beschreibung</span>
<textarea
name="beschreibung"
rows={2}
defaultValue={vorlage.beschreibung ?? ""}
className={`${FELD} py-2`}
/>
</label>
<div className="grid gap-4 sm:grid-cols-2">
<label className="flex flex-col gap-1.5 text-sm">
<span className="text-nebentext">Kategorie</span>
<input name="kategorie" defaultValue={vorlage.kategorie ?? ""} className={FELD} />
</label>
<label className="flex flex-col gap-1.5 text-sm">
<span className="text-nebentext">Schlagworte, mit Komma getrennt</span>
<input name="schlagworte" defaultValue={vorlage.schlagworte.join(", ")} className={FELD} />
</label>
</div>
{kunden.length > 0 ? (
<label className="flex flex-col gap-1.5 text-sm">
<span className="text-nebentext">Nur für einen Kunden</span>
<select name="kundeId" defaultValue={vorlage.kundeId ?? ""} className={FELD}>
<option value="">für alle Kunden</option>
{kunden.map((kunde) => (
<option key={kunde.id} value={kunde.id}>
{kunde.name}
</option>
))}
</select>
</label>
) : null}
{ergebnis.fehler ? (
<p role="alert" className="text-sm text-fehler">
{ergebnis.fehler}
</p>
) : null}
{ergebnis.erfolg ? (
<p role="status" className="text-sm text-erledigt">
{ergebnis.erfolg}
</p>
) : null}
<Button
type="submit"
disabled={laeuft}
className="h-11 self-start rounded-pille px-5 text-sm font-semibold"
>
{laeuft ? "Wird gespeichert …" : "Kopfdaten speichern"}
</Button>
</form>
);
}