import * as React from 'react'; import Alert from '@mui/material/Alert'; import Box from '@mui/material/Box'; import CircularProgress from '@mui/material/CircularProgress'; import { useNavigate, useParams } from 'react-router'; import useNotifications from '../hooks/useNotifications/useNotifications'; import { getOne as getEmployee, updateOne as updateEmployee, validate as validateEmployee, type Employee, } from '../data/employees'; import EmployeeForm, { type FormFieldValue, type EmployeeFormState, } from './EmployeeForm'; import PageContainer from './PageContainer'; function EmployeeEditForm({ initialValues, onSubmit, }: { initialValues: Partial; onSubmit: (formValues: Partial) => Promise; }) { const { employeeId } = useParams(); const navigate = useNavigate(); const notifications = useNotifications(); const [formState, setFormState] = React.useState(() => ({ values: initialValues, errors: {}, })); const formValues = formState.values; const formErrors = formState.errors; const setFormValues = React.useCallback( (newFormValues: Partial) => { setFormState((previousState) => ({ ...previousState, values: newFormValues, })); }, [], ); const setFormErrors = React.useCallback( (newFormErrors: Partial) => { setFormState((previousState) => ({ ...previousState, errors: newFormErrors, })); }, [], ); const handleFormFieldChange = React.useCallback( (name: keyof EmployeeFormState['values'], value: FormFieldValue) => { const validateField = async (values: Partial) => { const { issues } = validateEmployee(values); setFormErrors({ ...formErrors, [name]: issues?.find((issue) => issue.path?.[0] === name)?.message, }); }; const newFormValues = { ...formValues, [name]: value }; setFormValues(newFormValues); validateField(newFormValues); }, [formValues, formErrors, setFormErrors, setFormValues], ); const handleFormReset = React.useCallback(() => { setFormValues(initialValues); }, [initialValues, setFormValues]); const handleFormSubmit = React.useCallback(async () => { const { issues } = validateEmployee(formValues); if (issues && issues.length > 0) { setFormErrors( Object.fromEntries(issues.map((issue) => [issue.path?.[0], issue.message])), ); return; } setFormErrors({}); try { await onSubmit(formValues); notifications.show('Employee edited successfully.', { severity: 'success', autoHideDuration: 3000, }); navigate('/employees'); } catch (editError) { notifications.show( `Failed to edit employee. Reason: ${(editError as Error).message}`, { severity: 'error', autoHideDuration: 3000, }, ); throw editError; } }, [formValues, navigate, notifications, onSubmit, setFormErrors]); return ( ); } export default function EmployeeEdit() { const { employeeId } = useParams(); const [employee, setEmployee] = React.useState(null); const [isLoading, setIsLoading] = React.useState(true); const [error, setError] = React.useState(null); const loadData = React.useCallback(async () => { setError(null); setIsLoading(true); try { const showData = await getEmployee(Number(employeeId)); setEmployee(showData); } catch (showDataError) { setError(showDataError as Error); } setIsLoading(false); }, [employeeId]); React.useEffect(() => { loadData(); }, [loadData]); const handleSubmit = React.useCallback( async (formValues: Partial) => { const updatedData = await updateEmployee(Number(employeeId), formValues); setEmployee(updatedData); }, [employeeId], ); const renderEdit = React.useMemo(() => { if (isLoading) { return ( ); } if (error) { return ( {error.message} ); } return employee ? ( ) : null; }, [isLoading, error, employee, handleSubmit]); return ( {renderEdit} ); }