"use client"; import { useRouter } from "next/navigation"; import { useTranslations } from "next-intl"; import { useState } from "react"; import { useForm } from "react-hook-form"; import { createEvent, updateEvent } from "@/actions/events"; import { ArticlePreview } from "@/components/admin/article-preview"; import { PublicationPreflight } from "@/components/admin/publication-preflight"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { DateTimePicker } from "@/components/ui/date-time-picker"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Textarea } from "@/components/ui/textarea"; import { useFormRecovery } from "@/hooks/use-form-recovery"; import { useServerAction } from "@/hooks/use-server-action"; import { useUnsavedChanges } from "@/hooks/use-unsaved-changes"; import { publicationIssues } from "@/lib/publication-preflight"; import type { CreateEventInput, UpdateEventInput, } from "@/lib/validators/event"; interface EventType { id: number; name: string; slug: string; color: string; } interface EventFormProps { userId?: string; eventTypes: EventType[]; defaultValues?: Partial & { id?: number }; } interface EventFormValues { title: string; description: string; image?: string | null; maxPlayers?: string | number | null; roomId?: string | number | null; typeId: number; status: string; isRecurring: number; startsAt?: Date | null; endsAt?: Date | null; } export function EventForm({ eventTypes, defaultValues, userId, }: EventFormProps) { const t = useTranslations("pages.admin.events"); const tAction = useTranslations("pages.admin.actions"); const router = useRouter(); const [preview, setPreview] = useState(false); const { run, isPending } = useServerAction(); const isEditing = !!defaultValues?.id; const form = useForm({ defaultValues: { title: "", description: "", typeId: eventTypes[0]?.id ?? 0, status: "draft", isRecurring: 0, ...defaultValues, }, }); const dirty = form.formState.isDirty; useUnsavedChanges(dirty, tAction("leaveUnsaved")); const recovery = useFormRecovery({ userId, kind: "event", record: String(defaultValues?.id ?? "new"), dirty, snapshot: () => JSON.parse(JSON.stringify(form.getValues())), restore: (payload) => { const restored = { ...payload, startsAt: payload.startsAt ? new Date(String(payload.startsAt)) : null, endsAt: payload.endsAt ? new Date(String(payload.endsAt)) : null, } as EventFormValues; form.reset(restored, { keepDefaultValues: true }); }, }); const values = form.watch(); const issues = publicationIssues({ kind: "event", ...values }); function onSubmit(data: EventFormValues) { if (isPending) return; recovery.flush(); if ( data.status === "published" && publicationIssues({ kind: "event", ...data }).some( (issue) => issue.severity === "error", ) ) return; if (isEditing && defaultValues?.id) { run( () => updateEvent({ id: defaultValues.id, ...data } as UpdateEventInput & { id: number; }), { successMessage: t("toastUpdated"), onSuccess: () => { recovery.clear(); form.reset(data); router.refresh(); }, }, ); } else { run(() => createEvent(data as CreateEventInput), { successMessage: t("toastCreated"), onSuccess: (result) => { recovery.clear(); form.reset(data); if (result.id) { router.push(`/admin/events/${result.id}`); } }, }); } } return (
{isEditing ? t("formEditTitle") : t("formDetailsTitle")} {recovery.panel}
{form.formState.errors.title && (

{form.formState.errors.title.message}

)}