mirror of
https://github.com/Since-3/since3-website.git
synced 2026-10-12 19:51:16 +00:00
45 lines
1.4 KiB
TypeScript
45 lines
1.4 KiB
TypeScript
import { z } from "zod"
|
|
|
|
// Shared between the server action and the form so both validate identically.
|
|
export const contactSchema = z.object({
|
|
name: z
|
|
.string()
|
|
.trim()
|
|
.min(2, "Bitte gib deinen Namen an."),
|
|
email: z
|
|
.string()
|
|
.trim()
|
|
// Zod's default email pattern rejects valid Unicode addresses (e.g. müller@example.de)
|
|
.pipe(
|
|
z.email({
|
|
pattern: z.regexes.unicodeEmail,
|
|
error: "Bitte gib eine gültige E-Mail-Adresse an.",
|
|
})
|
|
),
|
|
company: z.string().trim().max(120, "Maximal 120 Zeichen.").optional(),
|
|
message: z
|
|
.string()
|
|
.trim()
|
|
.min(20, "Erzähl uns in mindestens 20 Zeichen, worum es geht.")
|
|
.max(4000, "Maximal 4000 Zeichen."),
|
|
privacy: z.literal("on", {
|
|
error: "Bitte stimme der Verarbeitung deiner Angaben zu.",
|
|
}),
|
|
})
|
|
|
|
export type ContactInput = z.infer<typeof contactSchema>
|
|
export type ContactField = keyof ContactInput
|
|
|
|
export type ContactFormState = {
|
|
status: "idle" | "success" | "error"
|
|
message?: string
|
|
fieldErrors?: Partial<Record<ContactField, string[]>>
|
|
// Echoed back so the form keeps its values after a failed submit.
|
|
// `privacy` is separate from ContactField's string values: the checkbox
|
|
// needs a boolean, not the raw "on" the form field submits.
|
|
values?: Partial<Record<Exclude<ContactField, "privacy">, string>> & {
|
|
privacy?: boolean
|
|
}
|
|
}
|
|
|
|
export const initialContactState: ContactFormState = { status: "idle" }
|