import React, { useEffect, useMemo, useState } from 'react'; import useProcessorDependencies from '../../hooks/useProcessorDependencies'; import useInitialValues from '../../hooks/useInitialValues'; import { FormRenderer } from '../renderer/form/form-renderer.component'; import { type FormProcessorContextProps, type FormSchema } from '../../types'; import { CustomHooksRenderer } from '../renderer/custom-hooks-renderer.component'; import { useFormFields } from '../../hooks/useFormFields'; import { useConcepts } from '../../hooks/useConcepts'; import { useFormFieldValidators } from '../../hooks/useFormFieldValidators'; import { useFormFieldsMeta } from '../../hooks/useFormFieldsMeta'; import { useFormFactory } from '../../provider/form-factory-provider'; import { useFormFieldValueAdapters } from '../../hooks/useFormFieldValueAdapters'; import { EncounterFormProcessor } from '../../processors/encounter/encounter-form-processor'; import { reportError } from '../../utils/error-utils'; import { useTranslation } from 'react-i18next'; import Loader from '../loaders/loader.component'; import { registerFormFieldAdaptersForCleanUp } from '../../lifecycle'; interface FormProcessorFactoryProps { formJson: FormSchema; isSubForm?: boolean; setIsLoadingFormDependencies: (isLoading: boolean) => void; } const FormProcessorFactory = ({ formJson, isSubForm = false, setIsLoadingFormDependencies, }: FormProcessorFactoryProps) => { const { patient, sessionMode, formProcessors, layoutType, location, provider, sessionDate, visit } = useFormFactory(); const processor = useMemo(() => { const ProcessorClass = formProcessors[formJson.processor]; let processorInstance; if (ProcessorClass) { processorInstance = new ProcessorClass(formJson); } else { console.error(`Form processor ${formJson.processor} not found, defaulting to EncounterFormProcessor`); processorInstance = new EncounterFormProcessor(formJson); } processorInstance.prepareFormSchema(formJson); return processorInstance; }, [formProcessors, formJson.processor]); const [processorContext, setProcessorContext] = useState({ patient, formJson, sessionMode, layoutType, location, currentProvider: provider, processor, sessionDate, visit, formFields: [], formFieldAdapters: {}, formFieldValidators: {}, }); const { t } = useTranslation(); const { formFields: rawFormFields, conceptReferences } = useFormFields(formJson); const { concepts: formFieldsConcepts, isLoading: isLoadingConcepts } = useConcepts(Array.from(conceptReferences)); const formFieldsWithMeta = useFormFieldsMeta(rawFormFields, formFieldsConcepts); const formFieldAdapters = useFormFieldValueAdapters(rawFormFields); const formFieldValidators = useFormFieldValidators(rawFormFields); const { isLoading: isLoadingCustomDeps } = useProcessorDependencies(processor, processorContext, setProcessorContext); const useCustomHooks = processor.getCustomHooks().useCustomHooks; const [isLoadingCustomHooks, setIsLoadingCustomHooks] = useState(!!useCustomHooks); const [isLoadingProcessorDependencies, setIsLoadingProcessorDependencies] = useState(true); const { isLoadingInitialValues, initialValues, error: initialValuesError, } = useInitialValues(processor, isLoadingCustomDeps || isLoadingCustomHooks || isLoadingConcepts, processorContext); useEffect(() => { const isLoading = isLoadingCustomDeps || isLoadingCustomHooks || isLoadingConcepts || isLoadingInitialValues; setIsLoadingFormDependencies(isLoading); setIsLoadingProcessorDependencies(isLoading); }, [isLoadingCustomDeps, isLoadingCustomHooks, isLoadingConcepts, isLoadingInitialValues]); useEffect(() => { setProcessorContext((prev) => ({ ...prev, ...(formFieldAdapters && { formFieldAdapters }), ...(formFieldValidators && { formFieldValidators }), ...(formFieldsWithMeta?.length ? { formFields: formFieldsWithMeta } : rawFormFields?.length ? { formFields: rawFormFields } : {}), })); }, [formFieldAdapters, formFieldValidators, rawFormFields, formFieldsWithMeta]); useEffect(() => { reportError(initialValuesError, t('errorLoadingInitialValues', 'Error loading initial values')); }, [initialValuesError]); useEffect(() => { if (formFieldAdapters) { registerFormFieldAdaptersForCleanUp(formFieldAdapters); } }, [formFieldAdapters]); return ( <> {useCustomHooks && ( )} {isLoadingProcessorDependencies && !isSubForm ? ( ) : ( )} ); }; export default FormProcessorFactory;