UNPKG

pagamio-frontend-commons-lib

Version:

Pagamio library for Frontend reusable components like the form engine and table container

134 lines (133 loc) 6.61 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { useEffect, useRef, useState } from 'react'; import BaseDrawer from './components/BaseDrawer'; import DrawerContent from './components/DrawerContent'; const FormEngineDrawer = ({ title, cancelButtonText = 'Cancel', submitButtonText = 'Submit', showForm = true, showDrawerButtons = true, isOpen, fields: initialFields, initialValues, children, marginTop = '0px', onClose, onSubmit, onFieldUpdate, onFieldChange, persistenceKey, }) => { const [fields, setFields] = useState(initialFields); const initializedRef = useRef(false); const processingDependencyRef = useRef(false); const pendingUpdatesRef = useRef(new Map()); // Update fields when initialFields changes while preserving values useEffect(() => { setFields((prevFields) => { const existingFieldsMap = new Map(prevFields.map((field) => [field.name, field])); return initialFields.map((newField) => { const existingField = existingFieldsMap.get(newField.name); if (existingField) { return { ...existingField, ...newField, options: existingField.options || newField.options, label: existingField.label || newField.label, }; } return newField; }); }); }, [initialFields]); useEffect(() => { if (isOpen) { document.body.classList.add('overflow-hidden'); } else { document.body.classList.remove('overflow-hidden'); // Reset initialization flag when drawer closes initializedRef.current = false; // Clear pending updates to prevent stale state pendingUpdatesRef.current.clear(); // Reset fields to initial state when drawer closes setFields(initialFields); } return () => { document.body.classList.remove('overflow-hidden'); }; }, [isOpen, initialFields]); const setFieldHidden = (fieldName, hidden) => { setFields((currentFields) => currentFields.map((field) => (field.name === fieldName ? { ...field, isHidden: hidden } : field))); }; const updateFieldLabel = (fieldName, newLabelName) => { setFields((currentFields) => currentFields.map((field) => (field.name === fieldName ? { ...field, label: newLabelName } : field))); }; const updateFieldOptions = (fieldName, newOptions) => { setFields((currentFields) => currentFields.map((field) => (field.name === fieldName ? { ...field, options: newOptions } : field))); }; const updateFieldValidation = (fieldName, newValidation) => { setFields((currentFields) => currentFields.map((field) => field.name === fieldName ? { ...field, validation: { ...(field.validation ?? {}), ...newValidation, }, } : field)); }; const addField = (field) => { const isFieldAlreadyAdded = fields.some((f) => f.name === field.name); if (isFieldAlreadyAdded) { updateFieldLabel(field.name, field.label); if (field.options) { updateFieldOptions(field.name, field.options); } } else { setFields((currentFields) => [...currentFields, field]); } }; // Helper function to check if a value is valid for processing const isValidValue = (value) => { return value !== undefined && value !== null && value !== ''; }; // Helper function to apply field updates based on the result const applyFieldUpdate = (result) => { if (!result) return; // Apply field modifications based on result if (result.hideField !== undefined && setFieldHidden) { setFieldHidden(result.field, result.hideField); } if (result.options !== undefined && updateFieldOptions) { updateFieldOptions(result.field, result.options); } if (result.label !== undefined && updateFieldLabel) { updateFieldLabel(result.field, result.label); } }; // Process a single field's updates const processFieldUpdate = async (fieldName, updates, value) => { for (const update of updates) { try { const result = await update.action(value, true); applyFieldUpdate(result); } catch (error) { console.error(`Error processing initial dependency for ${fieldName}:`, error); } } }; // Main function with reduced complexity const processInitialFieldUpdates = async (getValues) => { // Early return if conditions aren't met if (!onFieldUpdate || initializedRef.current || processingDependencyRef.current) return; processingDependencyRef.current = true; try { const processedFields = new Set(); for (const [fieldName, updates] of Object.entries(onFieldUpdate)) { if (processedFields.has(fieldName)) continue; const currentValue = getValues(fieldName); if (!isValidValue(currentValue)) continue; await processFieldUpdate(fieldName, updates, currentValue); processedFields.add(fieldName); } initializedRef.current = true; } finally { processingDependencyRef.current = false; } }; return (_jsx(BaseDrawer, { title: title, isOpen: isOpen, marginTop: marginTop, onClose: onClose, children: _jsx(DrawerContent, { isOpen: isOpen, fields: fields, onSubmit: onSubmit, handleCloseDrawer: onClose, initialValues: initialValues, showForm: showForm, showDrawerButtons: showDrawerButtons, cancelButtonText: cancelButtonText, submitButtonText: submitButtonText, onFieldUpdate: onFieldUpdate, onFieldChange: onFieldChange, updateFieldOptions: updateFieldOptions, updateFieldLabel: updateFieldLabel, setFieldHidden: setFieldHidden, addField: addField, updateFieldValidation: updateFieldValidation, processInitialFieldUpdates: processInitialFieldUpdates, processingDependencyRef: processingDependencyRef, pendingUpdatesRef: pendingUpdatesRef, persistenceKey: persistenceKey, children: children }, `${persistenceKey}-${isOpen ? 'open' : 'closed'}`) })); }; export default FormEngineDrawer;