import React, { useEffect, useMemo, useReducer } from 'react'; import { useForm } from 'react-hook-form'; import PageRenderer from '../page/page.renderer.component'; import FormProcessorFactory from '../../processor-factory/form-processor-factory.component'; import { formStateReducer, initialState } from './state'; import { useEvaluateFormFieldExpressions } from '../../../hooks/useEvaluateFormFieldExpressions'; import { useFormFactory } from '../../../provider/form-factory-provider'; import { FormProvider, type FormContextProps } from '../../../provider/form-provider'; import { type FormProcessorContextProps } from '../../../types'; import { useFormStateHelpers } from '../../../hooks/useFormStateHelpers'; import { pageObserver } from '../../sidebar/page-observer'; import { isPageContentVisible } from '../../../utils/form-helper'; export type FormRendererProps = { processorContext: FormProcessorContextProps; initialValues: Record; isSubForm: boolean; setIsLoadingFormDependencies: (isLoading: boolean) => void; }; export const FormRenderer = ({ processorContext, initialValues, isSubForm, setIsLoadingFormDependencies, }: FormRendererProps) => { const { evaluatedFields, evaluatedFormJson, evaluatedPagesVisibility } = useEvaluateFormFieldExpressions( initialValues, processorContext, ); const { registerForm, setIsFormDirty, workspaceLayout, isFormExpanded } = useFormFactory(); const methods = useForm({ defaultValues: initialValues, mode: 'onChange', reValidateMode: 'onChange', criteriaMode: 'all', }); const { formState: { isDirty }, } = methods; const [{ formFields, invalidFields, formJson, deletedFields }, dispatch] = useReducer(formStateReducer, { ...initialState, formFields: evaluatedFields, formJson: evaluatedFormJson, }); const { addFormField, updateFormField, getFormField, removeFormField, setInvalidFields, addInvalidField, removeInvalidField, setForm, setDeletedFields, } = useFormStateHelpers(dispatch, formFields); useEffect(() => { const scrollablePages = formJson.pages.filter((page) => !page.isSubform).map((page) => page); pageObserver.updateScrollablePages(scrollablePages); }, [formJson.pages]); useEffect(() => { pageObserver.setEvaluatedPagesVisibility(evaluatedPagesVisibility); }, [evaluatedPagesVisibility]); useEffect(() => { pageObserver.updatePagesWithErrors(invalidFields.map((field) => field.meta.pageId)); }, [invalidFields]); const context: FormContextProps = useMemo(() => { return { ...processorContext, workspaceLayout, methods, formFields, formJson, invalidFields, deletedFields, addFormField, updateFormField, getFormField, removeFormField, setInvalidFields, addInvalidField, removeInvalidField, setForm, setDeletedFields, }; }, [processorContext, workspaceLayout, methods, formFields, formJson, invalidFields, deletedFields]); useEffect(() => { registerForm(formJson.name, isSubForm, context); }, [formJson.name, isSubForm, context]); useEffect(() => { setIsFormDirty(isDirty); }, [isDirty]); return ( {formJson.pages.map((page) => { if (!page.isSubform && !isPageContentVisible(page)) { return null; } if (page.isSubform && page.subform?.form) { return ( ); } return ; })} ); };