feat: Добавить анимации и улучшения UX/UI в компоненты приложения, включая плавные переходы, эффекты при наведении и анимации для модальных окон. Обновить карточки и таблицы с новыми анимациями для улучшения визуального восприятия и доступности.
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m42s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m42s
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
|
||||
/**
|
||||
* useForm - hook для управления формами с валидацией
|
||||
*
|
||||
* @param {Object} initialValues - начальные значения полей
|
||||
* @param {Object} validationSchema - схема валидации {fieldName: validatorFn}
|
||||
* @returns {Object} - {values, errors, touched, isSubmitting, handlers}
|
||||
*
|
||||
* Пример использования:
|
||||
* const { values, errors, handleChange, handleBlur, handleSubmit } = useForm(
|
||||
* { email: '', password: '' },
|
||||
* {
|
||||
* email: (value) => !value ? 'Email обязателен' : null,
|
||||
* password: (value) => value.length < 6 ? 'Минимум 6 символов' : null
|
||||
* }
|
||||
* );
|
||||
*/
|
||||
function useForm(initialValues, validationSchema = {}) {
|
||||
const [values, setValues] = useState(initialValues);
|
||||
const [errors, setErrors] = useState({});
|
||||
const [touched, setTouched] = useState({});
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
// Валидация одного поля
|
||||
const validateField = useCallback((name, value) => {
|
||||
if (!validationSchema[name]) return null;
|
||||
|
||||
const validator = validationSchema[name];
|
||||
const error = validator(value, values);
|
||||
|
||||
return error;
|
||||
}, [validationSchema, values]);
|
||||
|
||||
// Обработчик изменения поля
|
||||
const handleChange = useCallback((name, value) => {
|
||||
setValues(prev => ({ ...prev, [name]: value }));
|
||||
|
||||
// Валидация при изменении, если поле уже было touched
|
||||
if (touched[name]) {
|
||||
const error = validateField(name, value);
|
||||
setErrors(prev => ({ ...prev, [name]: error }));
|
||||
}
|
||||
}, [touched, validateField]);
|
||||
|
||||
// Обработчик blur (потеря фокуса)
|
||||
const handleBlur = useCallback((name) => {
|
||||
setTouched(prev => ({ ...prev, [name]: true }));
|
||||
|
||||
const value = values[name];
|
||||
const error = validateField(name, value);
|
||||
setErrors(prev => ({ ...prev, [name]: error }));
|
||||
}, [values, validateField]);
|
||||
|
||||
// Валидация всех полей
|
||||
const validate = useCallback(() => {
|
||||
const newErrors = {};
|
||||
let isValid = true;
|
||||
|
||||
Object.keys(validationSchema).forEach(name => {
|
||||
const error = validateField(name, values[name]);
|
||||
if (error) {
|
||||
newErrors[name] = error;
|
||||
isValid = false;
|
||||
}
|
||||
});
|
||||
|
||||
setErrors(newErrors);
|
||||
return isValid;
|
||||
}, [validationSchema, values, validateField]);
|
||||
|
||||
// Обработчик submit
|
||||
const handleSubmit = useCallback(async (onSubmit) => {
|
||||
setIsSubmitting(true);
|
||||
|
||||
// Отмечаем все поля как touched
|
||||
const allTouched = Object.keys(values).reduce((acc, key) => {
|
||||
acc[key] = true;
|
||||
return acc;
|
||||
}, {});
|
||||
setTouched(allTouched);
|
||||
|
||||
const isValid = validate();
|
||||
|
||||
if (isValid) {
|
||||
try {
|
||||
await onSubmit(values);
|
||||
} catch (error) {
|
||||
console.error('Form submission error:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
} else {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
}, [values, validate]);
|
||||
|
||||
// Сброс формы
|
||||
const reset = useCallback(() => {
|
||||
setValues(initialValues);
|
||||
setErrors({});
|
||||
setTouched({});
|
||||
setIsSubmitting(false);
|
||||
}, [initialValues]);
|
||||
|
||||
// Установка значения поля программно
|
||||
const setValue = useCallback((name, value) => {
|
||||
setValues(prev => ({ ...prev, [name]: value }));
|
||||
}, []);
|
||||
|
||||
// Установка ошибки поля программно
|
||||
const setError = useCallback((name, error) => {
|
||||
setErrors(prev => ({ ...prev, [name]: error }));
|
||||
}, []);
|
||||
|
||||
return {
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
isSubmitting,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleSubmit,
|
||||
validate,
|
||||
reset,
|
||||
setValue,
|
||||
setError,
|
||||
setValues,
|
||||
setErrors
|
||||
};
|
||||
}
|
||||
|
||||
export default useForm;
|
||||
|
||||
Reference in New Issue
Block a user