'use client' import { zodResolver } from '@hookform/resolvers/zod' import { useEffect, useMemo, useRef } from 'react' import { FormProvider, useForm } from 'react-hook-form' import { texts, format } from '@/texts' import type { EventWizardEditLocks, EventWizardFormData } from '@/components/events/create/consumer/types' import { hasRequiredPosters } from '@/components/events/create/consumer/types' import { addToast } from '@/lib/toast' import EventMediaGalleryUploader from '@/components/events/create/EventMediaGalleryUploader' import { EventWizardStep1Validation, type EventWizardStep1Values } from '@/validation/eventWizard' import { shouldAutogenerateEventSlug, slugifyEventTitle } from '@/features/events/eventSlug' import { usePublicCategoriesQuery } from '@/queries/consumer/usePublicCategoriesQuery' import { showFormValidationToast } from '@/lib/formValidationToast' import ConsumerInput from '@/components/consumer/ConsumerInput' import { buildCategoryTree } from '@/helpers/categoryPath' interface Step1BasicInfoProps { data: EventWizardFormData /** Present in edit mode; media stays editable regardless of locks. */ locks?: EventWizardEditLocks onBindSubmit: (submit: (() => void) | null) => void onChange: (patch: Partial) => void onNext: (patch: Partial) => void } export default function Step1BasicInfo({ data, onBindSubmit, onChange, onNext }: Step1BasicInfoProps) { const categoriesQuery = usePublicCategoriesQuery() const categoryOptions = useMemo( () => buildCategoryTree(categoriesQuery.data?.items ?? []).map((option) => ({ depth: option.depth, id: String(option.id), name: option.name, })), [categoriesQuery.data?.items] ) const form = useForm({ resolver: zodResolver(EventWizardStep1Validation), defaultValues: { title: data.title, slug: data.slug, categoryId: data.categoryId, shortDescription: data.shortDescription, description: data.description, }, }) const followTitleRef = useRef(shouldAutogenerateEventSlug(data.slug, data.title)) const lastAutoSlugRef = useRef(data.slug || slugifyEventTitle(data.title)) const title = form.watch('title') const slug = form.watch('slug') useEffect(() => { if (categoriesQuery.isError) { addToast({ title: texts.events.categoriesLoadFailed, color: 'danger' }) } }, [categoriesQuery.isError]) useEffect(() => { if (!followTitleRef.current) return const next = slugifyEventTitle(title ?? '') lastAutoSlugRef.current = next if (form.getValues('slug') !== next) { form.setValue('slug', next) } }, [form, title]) useEffect(() => { const subscription = form.watch((values, info) => { if (info.name === 'slug' && (values.slug ?? '') !== lastAutoSlugRef.current) { followTitleRef.current = false } onChange({ title: values.title ?? '', slug: values.slug ?? '', categoryId: values.categoryId ?? '', shortDescription: values.shortDescription ?? '', description: values.description ?? '', }) }) return () => { subscription.unsubscribe() } }, [form, onChange]) const handleSubmit = form.handleSubmit((values) => { if (!hasRequiredPosters(data.media)) { addToast({ title: texts.events.postersRequiredTitle, description: texts.events.postersRequiredShort, color: 'danger', }) return } onNext({ title: values.title, slug: values.slug, categoryId: values.categoryId, shortDescription: values.shortDescription ?? '', description: values.description ?? '', media: data.media, }) }, showFormValidationToast) useEffect(() => { onBindSubmit(() => { void handleSubmit() }) return () => { onBindSubmit(null) } }, [handleSubmit, onBindSubmit]) return (
{ event.preventDefault() void handleSubmit() }} > { onChange({ media }) }} />
) }