UNPKG

pagamio-frontend-commons-lib

Version:

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

90 lines (89 loc) 4.97 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import clsx from 'clsx'; import { useForm } from 'react-hook-form'; import { useEffect, useState } from 'react'; import { Button, SheetRoot, SheetTrigger } from '../components'; import { cn } from '../helpers'; import FieldWrapper from './components/FieldWrapper'; const CancelButton = ({ isSubmitting, onCancel, isNotTrigger }) => { const sharedClasses = 'bg-white border-primary-500 text-primary-500 hover:bg-primary-600 hover:text-white w-full mr-3'; return isNotTrigger ? (_jsx(Button, { className: sharedClasses, disabled: isSubmitting, onClick: onCancel, children: "Cancel" })) : (_jsx(SheetRoot, { children: _jsx(SheetTrigger, { asChild: true, children: _jsx(Button, { className: sharedClasses, disabled: isSubmitting, onClick: onCancel, children: "Cancel" }) }) })); }; const FormEngine = ({ fields, onSubmit, initialValues, layout = 'vertical', isNotTrigger, showCancelButton = true, submitButtonText = 'Save', showSubmittingText = true, submitButtonClass, onCancel, getFieldValues, formRef, className, }) => { const { control, handleSubmit, watch, formState: { errors, isSubmitting }, reset, setValue, trigger, } = useForm({ mode: 'onBlur', defaultValues: initialValues }); const allFields = watch(); const password = watch('password'); const confirmPassword = watch('confirmPassword'); //re-validate confirmPassword when password changes useEffect(() => { if (password && confirmPassword) { trigger('confirmPassword'); } }, [password, trigger, confirmPassword]); useEffect(() => { if (getFieldValues) { getFieldValues(allFields); } }, [allFields, getFieldValues]); // Expose form control methods via ref useEffect(() => { if (formRef) { formRef.current = { reset: () => reset(initialValues), setValue: (name, value) => setValue(name, value), }; } }, [formRef, reset, setValue, initialValues]); const [submitError, setSubmitError] = useState(null); const handleFormSubmit = async (data) => { setSubmitError(null); try { await onSubmit(data); if (!formRef) { reset(initialValues); } } catch (error) { setSubmitError(error instanceof Error ? error.message : 'An error occurred'); } }; // Enhanced validation functions const validatePassword = (value) => { if (!value) return 'Password is required'; if (value.length < 8) return 'Password must be at least 8 characters'; return true; }; const validateConfirmPassword = (value) => { if (!value) return 'Please confirm your password'; if (!password) return 'Please enter a password first'; if (password.length < 8) return 'Please enter a valid password first (minimum 8 characters)'; if (value !== password) return 'Passwords do not match'; return true; }; return (_jsxs("form", { className: cn(`${layout === 'horizontal' ? 'flex flex-wrap -mx-4' : ''} mb-6 border-gray-400 p-3`, className), onSubmit: handleSubmit(handleFormSubmit), children: [_jsx("div", { className: `${layout === 'vertical' ? 'grid grid-cols-12 gap-2 align-middle' : 'w-full flex flex-wrap'}`, children: fields?.map((field) => { // Extract validation logic const getFieldValidation = () => { if (field.name === 'password') { return validatePassword; } if (field.name === 'confirmPassword') { return validateConfirmPassword; } return field.validation?.validate; }; return (_jsx(FieldWrapper, { field: { ...field, validation: { ...field.validation, validate: getFieldValidation(), }, }, control: control, errors: errors, layout: layout }, field.name)); }) }), _jsxs("div", { className: clsx('flex col-span-2 mt-4 w-full', showCancelButton ? 'space-x-4' : 'justify-end'), children: [showCancelButton && (_jsx(CancelButton, { isSubmitting: isSubmitting, onCancel: onCancel, isNotTrigger: isNotTrigger })), _jsx(Button, { type: "submit", className: clsx(showCancelButton ? 'w-full ml-3' : 'w-[20%]', submitButtonClass), disabled: isSubmitting, children: submitButtonText }), isSubmitting && showSubmittingText && _jsx("span", { children: "Submitting..." })] }), submitError && _jsx("p", { className: "text-red-500", children: submitError })] })); }; export default FormEngine;