Add non-destructive dev seed on startup

This commit is contained in:
t.indorf
2026-05-06 22:31:07 +02:00
parent 9f452fccac
commit b686e714ff
77 changed files with 10862 additions and 87 deletions
+125
View File
@@ -0,0 +1,125 @@
"use client";
import { useActionState } from "react";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { registerAction, type RegisterState } from "./actions";
const initialState: RegisterState = {};
export function RegisterForm() {
const [state, formAction, pending] = useActionState(registerAction, initialState);
return (
<form action={formAction} className="space-y-4">
<div className="grid gap-4 sm:grid-cols-2">
<FormField
id="firstName"
name="firstName"
label="Vorname"
autoComplete="given-name"
required
error={state.errors?.firstName?.[0]}
/>
<FormField
id="lastName"
name="lastName"
label="Nachname"
autoComplete="family-name"
required
error={state.errors?.lastName?.[0]}
/>
</div>
<FormField
id="email"
name="email"
type="email"
label="E-Mail"
autoComplete="email"
required
error={state.errors?.email?.[0]}
/>
<FormField
id="password"
name="password"
type="password"
label="Passwort"
autoComplete="new-password"
required
helperText="Mindestens 8 Zeichen."
error={state.errors?.password?.[0]}
/>
<div className="flex items-start gap-3 pt-2">
<Checkbox id="acceptPrivacyPolicy" name="acceptPrivacyPolicy" required />
<div className="grid gap-1 leading-none">
<Label htmlFor="acceptPrivacyPolicy" className="text-sm font-normal">
Ich habe die{" "}
<a href="/datenschutz" className="underline" target="_blank" rel="noreferrer">
Datenschutzerklärung
</a>{" "}
gelesen und akzeptiere sie.
</Label>
{state.errors?.acceptPrivacyPolicy?.[0] && (
<p className="text-xs text-destructive">{state.errors.acceptPrivacyPolicy[0]}</p>
)}
</div>
</div>
{state.errors?._form?.[0] && (
<p className="rounded-md border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive">
{state.errors._form[0]}
</p>
)}
<Button type="submit" className="w-full" disabled={pending}>
{pending ? "Wird erstellt…" : "Account erstellen"}
</Button>
</form>
);
}
function FormField({
id,
name,
label,
type = "text",
required,
autoComplete,
helperText,
error,
}: {
id: string;
name: string;
label: string;
type?: string;
required?: boolean;
autoComplete?: string;
helperText?: string;
error?: string;
}) {
return (
<div className="space-y-1.5">
<Label htmlFor={id}>{label}</Label>
<Input
id={id}
name={name}
type={type}
required={required}
autoComplete={autoComplete}
aria-invalid={!!error}
/>
{error ? (
<p className="text-xs text-destructive">{error}</p>
) : helperText ? (
<p className="text-xs text-muted-foreground">{helperText}</p>
) : null}
</div>
);
}