import { Box, Button, Divider, TextField, Typography } from '@mui/material'; import { useEffect, useState } from 'react'; import { PrimaryButton } from '../../components/common/Buttons/Buttons'; import Modal from '../../components/common/Modal/Modal'; import SelectWithOptions from '../AdminPanel/components/SelectWithOptions'; export const ModalCreateProject = ({ open, onClose, onCreate, config = {}, initialData = null, title = 'Создание проекта', buttonText = 'Создать', }) => { const [projectData, setProjectData] = useState(() => { if (initialData) { return { ...initialData }; } // Иначе создаем из конфига const data = {}; Object.keys(config).forEach((key) => { data[key] = config[key].defaultValue; }); return data; }); const [errors, setErrors] = useState({}); useEffect(() => { if (initialData) { setProjectData({ ...initialData }); } else { const data = {}; Object.keys(config).forEach((key) => { data[key] = config[key].defaultValue; }); setProjectData(data); } setErrors({}); }, [initialData, config, open]); const handleChange = (field, value) => { setProjectData((prev) => ({ ...prev, [field]: value, })); if (errors[field]) { setErrors((prev) => ({ ...prev, [field]: undefined, })); } }; const validateField = (fieldName, config) => { const value = projectData[fieldName]; if (config.required_field) { if (config.type === 'multiselect') { if (!value || (Array.isArray(value) && value.length === 0) || value === '') { return `Поле "${fieldName}" обязательно для заполнения`; } } else if (config.type === 'text') { if (!value || value.trim() === '') { return `Поле "${fieldName}" обязательно для заполнения`; } } else if (config.type === 'number') { if (value === null || value === undefined || value === '') { return `Поле "${fieldName}" обязательно для заполнения`; } } } if (config.type === 'number' && value !== null && value !== undefined && value !== '') { if (config.min !== undefined && Number(value) < config.min) { return `Значение должно быть не меньше ${config.min}`; } if (config.max !== undefined && Number(value) > config.max) { return `Значение должно быть не больше ${config.max}`; } } return null; }; const validateAllFields = () => { const newErrors = {}; let hasErrors = false; Object.entries(config).forEach(([fieldName, fieldConfig]) => { const error = validateField(fieldName, fieldConfig); if (error) { newErrors[fieldName] = error; hasErrors = true; } }); setErrors(newErrors); return !hasErrors; }; const handleClickCreate = () => { if (validateAllFields()) { onCreate(projectData); onClose(); } }; const handleClose = () => { const resetData = {}; Object.keys(config).forEach((key) => { resetData[key] = config[key].defaultValue; }); setProjectData(resetData); setErrors({}); onClose(); }; const renderField = (fieldName, config) => { const hasError = !!errors[fieldName]; const errorText = errors[fieldName]; switch (config.type) { case 'multiselect': return ( {fieldName} {config.required_field && *} handleChange(fieldName, value)} width='28.25rem' style={{ borderColor: hasError ? 'var(--error-color, #d32f2f)' : undefined, borderWidth: hasError ? '2px' : undefined, }} /> {hasError && ( {errorText} )} ); case 'text': return ( {fieldName} {config.required_field && *} handleChange(fieldName, e.target.value)} placeholder={config.placeholder} size='small' error={hasError} helperText={hasError ? errorText : ''} FormHelperTextProps={{ sx: { marginLeft: 0, fontSize: '0.75rem', }, }} /> ); case 'number': return ( {fieldName} {config.required_field && *} { const inputValue = e.target.value; const isValidInput = /^\d*\.?\d*$/.test(inputValue) || inputValue === ''; if (isValidInput) { handleChange(fieldName, inputValue); } }} placeholder={config.placeholder} size='small' error={hasError} helperText={hasError ? errorText : ''} slotProps={{ htmlInput: { min: config.min, max: config.max || null, step: config.step || 1, }, }} FormHelperTextProps={{ sx: { marginLeft: 0, fontSize: '0.75rem', }, }} /> ); default: return null; } }; return ( {buttonText} }> {Object.entries(config).map(([fieldName, config]) => renderField(fieldName, config))} ); };