224 lines
6.1 KiB
TypeScript
224 lines
6.1 KiB
TypeScript
"use client";
|
|
|
|
import { useTransition } from "react";
|
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
import { Loader2, Send } from "lucide-react";
|
|
import { useForm } from "react-hook-form";
|
|
import { toast } from "sonner";
|
|
|
|
import { submitContactRequest } from "@/actions/contact";
|
|
import {
|
|
contactRequestSchema,
|
|
contactRequestTypeLabels,
|
|
type ContactRequestInput,
|
|
type ContactSubmissionPayload,
|
|
} from "@/lib/contact-schema";
|
|
import { Button } from "@/components/ui/button";
|
|
import {
|
|
Form,
|
|
FormControl,
|
|
FormField,
|
|
FormItem,
|
|
FormLabel,
|
|
FormMessage,
|
|
} from "@/components/ui/form";
|
|
import { Input } from "@/components/ui/input";
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/components/ui/select";
|
|
import { Textarea } from "@/components/ui/textarea";
|
|
|
|
export function ContactForm() {
|
|
const [isPending, startTransition] = useTransition();
|
|
const form = useForm<ContactRequestInput>({
|
|
resolver: zodResolver(contactRequestSchema),
|
|
defaultValues: {
|
|
name: "",
|
|
kitaName: "",
|
|
email: "",
|
|
requestType: "DEMO",
|
|
message: "",
|
|
},
|
|
});
|
|
|
|
function onSubmit(
|
|
values: ContactRequestInput,
|
|
event?: React.BaseSyntheticEvent,
|
|
) {
|
|
const formEl = event?.target as HTMLFormElement | undefined;
|
|
const website =
|
|
(formEl?.elements.namedItem("website") as HTMLInputElement | null)
|
|
?.value ?? "";
|
|
|
|
startTransition(async () => {
|
|
const payload: ContactSubmissionPayload = { ...values, website };
|
|
const result = await submitContactRequest(payload);
|
|
|
|
if (!result.success) {
|
|
toast.error(result.error);
|
|
return;
|
|
}
|
|
|
|
toast.success(
|
|
"Danke! Wir haben dir eine Bestätigung an deine E-Mail-Adresse geschickt.",
|
|
);
|
|
form.reset({
|
|
name: "",
|
|
kitaName: "",
|
|
email: "",
|
|
requestType: "DEMO",
|
|
message: "",
|
|
});
|
|
const honeypot = formEl?.elements.namedItem(
|
|
"website",
|
|
) as HTMLInputElement | null;
|
|
if (honeypot) honeypot.value = "";
|
|
});
|
|
}
|
|
|
|
return (
|
|
<Form {...form}>
|
|
<form onSubmit={form.handleSubmit(onSubmit)} className="grid gap-5">
|
|
<FormField
|
|
control={form.control}
|
|
name="name"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Name</FormLabel>
|
|
<FormControl>
|
|
<Input
|
|
placeholder="Anna Vorstand"
|
|
autoComplete="name"
|
|
className="h-12 bg-white"
|
|
{...field}
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
|
|
<FormField
|
|
control={form.control}
|
|
name="kitaName"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Name der Kita / Initiative</FormLabel>
|
|
<FormControl>
|
|
<Input
|
|
placeholder="Waldameisen e.V."
|
|
autoComplete="organization"
|
|
className="h-12 bg-white"
|
|
{...field}
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
|
|
<FormField
|
|
control={form.control}
|
|
name="email"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>E-Mail-Adresse</FormLabel>
|
|
<FormControl>
|
|
<Input
|
|
type="email"
|
|
placeholder="vorstand@eure-kita.de"
|
|
autoComplete="email"
|
|
className="h-12 bg-white"
|
|
{...field}
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
|
|
<FormField
|
|
control={form.control}
|
|
name="requestType"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Art der Anfrage</FormLabel>
|
|
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
|
<FormControl>
|
|
<SelectTrigger className="h-12 bg-white">
|
|
<SelectValue placeholder="Anfrage auswählen" />
|
|
</SelectTrigger>
|
|
</FormControl>
|
|
<SelectContent>
|
|
{Object.entries(contactRequestTypeLabels).map(
|
|
([value, label]) => (
|
|
<SelectItem key={value} value={value}>
|
|
{label}
|
|
</SelectItem>
|
|
),
|
|
)}
|
|
</SelectContent>
|
|
</Select>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
|
|
<FormField
|
|
control={form.control}
|
|
name="message"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Nachricht</FormLabel>
|
|
<FormControl>
|
|
<Textarea
|
|
rows={6}
|
|
placeholder="Erzählt kurz, wie eure Kita aktuell organisiert ist und wobei ihr Unterstützung sucht."
|
|
className="resize-none bg-white"
|
|
{...field}
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
|
|
<div
|
|
aria-hidden="true"
|
|
style={{
|
|
position: "absolute",
|
|
left: "-10000px",
|
|
top: "auto",
|
|
width: "1px",
|
|
height: "1px",
|
|
overflow: "hidden",
|
|
}}
|
|
>
|
|
<label htmlFor="contact-website">Website (bitte leer lassen)</label>
|
|
<input
|
|
id="contact-website"
|
|
type="text"
|
|
name="website"
|
|
tabIndex={-1}
|
|
autoComplete="off"
|
|
defaultValue=""
|
|
/>
|
|
</div>
|
|
|
|
<Button type="submit" size="lg" disabled={isPending} className="h-12">
|
|
{isPending ? (
|
|
<Loader2 className="h-4 w-4 animate-spin" />
|
|
) : (
|
|
<Send className="h-4 w-4" />
|
|
)}
|
|
{isPending ? "Wird gesendet..." : "Anfrage senden"}
|
|
</Button>
|
|
</form>
|
|
</Form>
|
|
);
|
|
}
|