document.head.insertAdjacentHTML('beforeend','') module.exports = name: 'FormValidator' render: (new Function '_ctx', '_cache', renderFns['app/shared/FormValidator/index.pug'])() props: fields: type: Object default: -> email: true phone: true message: true file: false validationRules: type: Object default: -> {} data: -> formData: email: '' phone: '' message: '' file: null errors: {} isSubmitting: false isSubmitted: false fileInfo: '' debounceTimers: {} computed: isFormValid: -> Object.keys(@errors).length == 0 && Object.keys(@formData).some((key) => @formData[key] && @formData[key].toString().trim() != '') mounted: -> @initializeValidation() methods: initializeValidation: -> # Установка правил валидации по умолчанию @defaultRules = email: required: true pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ message: 'Введите корректный email адрес' phone: required: true pattern: /^\+?[0-9\s\-\(\)]{10,}$/ message: 'Введите корректный номер телефона' message: required: true minLength: 10 message: 'Сообщение должно содержать минимум 10 символов' file: maxSize: 5 * 1024 * 1024 # 5MB allowedTypes: ['image/jpeg', 'image/png', 'application/pdf'] message: 'Файл должен быть JPEG, PNG или PDF, не более 5MB' validateField: (fieldName) -> rules = @validationRules[fieldName] || @defaultRules[fieldName] value = @formData[fieldName] @errors[fieldName] = '' if rules.required && (!value || value.toString().trim() == '') @errors[fieldName] = 'Это поле обязательно для заполнения' return false if rules.pattern && value && !rules.pattern.test(value) @errors[fieldName] = rules.message return false if rules.minLength && value && value.length < rules.minLength @errors[fieldName] = rules.message return false true debouncedValidate: (fieldName) -> clearTimeout @debounceTimers[fieldName] if @debounceTimers[fieldName] @debounceTimers[fieldName] = setTimeout => @validateField fieldName , 500 handleFileUpload: (event) -> file = event.target.files[0] return unless file rules = @defaultRules.file @errors.file = '' # Проверка типа файла :cite[2]:cite[7] if !rules.allowedTypes.includes(file.type) @errors.file = 'Разрешены только JPEG, PNG и PDF файлы' return if file.size > rules.maxSize @errors.file = 'Файл слишком большой. Максимальный размер: 5MB' return @formData.file = file @fileInfo = "#{file.name} (#{(file.size / 1024 / 1024).toFixed(2)} MB)" handleSubmit: (event) -> event.preventDefault() # Валидация всех полей isValid = true for fieldName of @fields if @fields[fieldName] && !@validateField(fieldName) isValid = false return unless isValid @isSubmitting = true # Имитация отправки setTimeout => @isSubmitting = false @isSubmitted = true @$emit 'form-submitted', @formData , 2000 getFieldClasses: (fieldName) -> baseClasses = 'border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-white' errorClasses = 'border-red-500 dark:border-red-400 ring-1 ring-red-500 dark:ring-red-400' validClasses = 'border-green-500 dark:border-green-400' if @errors[fieldName] return "#{baseClasses} #{errorClasses}" else if @formData[fieldName] && @formData[fieldName].toString().trim() != '' return "#{baseClasses} #{validClasses}" else return baseClasses emits: ['form-submitted', 'validation-changed']