'use client' import type { FormFieldBlock, Form as FormType } from '@payloadcms/plugin-form-builder/types' import { useRouter } from 'next/navigation' import React, { useCallback, useState } from 'react' import { useForm, FormProvider } from 'react-hook-form' import RichText from '@/components/RichText' import { Button } from '@/components/ui/button' import type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical' import { fields } from './fields' import { getClientSideURL } from '@/utilities/getURL' export type FormBlockType = { blockName?: string blockType?: 'formBlock' enableIntro: boolean form: FormType introContent?: SerializedEditorState } export const FormBlock: React.FC< { id?: string } & FormBlockType > = (props) => { const { enableIntro, form: formFromProps, form: { id: formID, confirmationMessage, confirmationType, redirect, submitButtonLabel } = {}, introContent, } = props const formMethods = useForm({ defaultValues: formFromProps.fields, }) const { control, formState: { errors }, handleSubmit, register, } = formMethods const [isLoading, setIsLoading] = useState(false) const [hasSubmitted, setHasSubmitted] = useState() const [error, setError] = useState<{ message: string; status?: string } | undefined>() const router = useRouter() const onSubmit = useCallback( (data: FormFieldBlock[]) => { let loadingTimerID: ReturnType const submitForm = async () => { setError(undefined) const dataToSend = Object.entries(data).map(([name, value]) => ({ field: name, value, })) // delay loading indicator by 1s loadingTimerID = setTimeout(() => { setIsLoading(true) }, 1000) try { const req = await fetch(`${getClientSideURL()}/api/form-submissions`, { body: JSON.stringify({ form: formID, submissionData: dataToSend, }), headers: { 'Content-Type': 'application/json', }, method: 'POST', }) const res = await req.json() clearTimeout(loadingTimerID) if (req.status >= 400) { setIsLoading(false) setError({ message: res.errors?.[0]?.message || 'Internal Server Error', status: res.status, }) return } setIsLoading(false) setHasSubmitted(true) if (confirmationType === 'redirect' && redirect) { const { url } = redirect const redirectUrl = url if (redirectUrl) router.push(redirectUrl) } } catch (err) { console.warn(err) setIsLoading(false) setError({ message: 'Something went wrong.', }) } } void submitForm() }, [router, formID, redirect, confirmationType], ) return (
{enableIntro && introContent && !hasSubmitted && ( )}
{!isLoading && hasSubmitted && confirmationType === 'message' && ( )} {isLoading && !hasSubmitted &&

Loading, please wait...

} {error &&
{`${error.status || '500'}: ${error.message || ''}`}
} {!hasSubmitted && (
{formFromProps && formFromProps.fields && formFromProps.fields?.map((field, index) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const Field: React.FC = fields?.[field.blockType as keyof typeof fields] if (Field) { return (
) } return null })}
)}
) }