index.pug 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. .form-validator
  2. form(@submit='handleSubmit' novalidate)
  3. slot(name='default')
  4. //- Поле email с валидацией
  5. .form-group.mb-6(v-if='fields.email')
  6. label.block.text-sm.font-medium.mb-2(for='email' class='text-gray-700 dark:text-gray-300') Email адрес
  7. input.w-full.px-4.py-3.rounded-lg.border.transition-colors(
  8. id='email'
  9. type='email'
  10. v-model='formData.email'
  11. @input='debouncedValidate("email")'
  12. @blur='validateField("email")'
  13. :class='getFieldClasses("email")'
  14. placeholder='your@email.com'
  15. autocomplete='email'
  16. )
  17. .validation-message.mt-2.text-sm.transition-all.duration-300(
  18. v-if='errors.email'
  19. class='text-red-500 dark:text-red-400'
  20. ) {{ errors.email }}
  21. //- Поле телефона
  22. .form-group.mb-6(v-if='fields.phone')
  23. label.block.text-sm.font-medium.mb-2(for='phone' class='text-gray-700 dark:text-gray-300') Телефон
  24. input.w-full.px-4.py-3.rounded-lg.border.transition-colors(
  25. id='phone'
  26. type='tel'
  27. v-model='formData.phone'
  28. @input='debouncedValidate("phone")'
  29. @blur='validateField("phone")'
  30. :class='getFieldClasses("phone")'
  31. placeholder='+992 XX XXX-XX-XX'
  32. autocomplete='tel'
  33. )
  34. .validation-message.mt-2.text-sm.transition-all.duration-300(
  35. v-if='errors.phone'
  36. class='text-red-500 dark:text-red-400'
  37. ) {{ errors.phone }}
  38. //- Файловый загрузчик :cite[2]:cite[7]
  39. .form-group.mb-6(v-if='fields.file')
  40. label.block.text-sm.font-medium.mb-2(for='file' class='text-gray-700 dark:text-gray-300') Загрузить файл
  41. input.w-full.px-4.py-3.rounded-lg.border.transition-colors(
  42. id='file'
  43. type='file'
  44. @change='handleFileUpload'
  45. accept='.jpg,.jpeg,.png,.pdf'
  46. :class='getFieldClasses("file")'
  47. )
  48. .validation-message.mt-2.text-sm.transition-all.duration-300(
  49. v-if='errors.file'
  50. class='text-red-500 dark:text-red-400'
  51. ) {{ errors.file }}
  52. .file-info.mt-2.text-sm.text-gray-600(class="dark:text-gray-400" v-if='fileInfo') {{ fileInfo }}
  53. //- Текстовое поле
  54. .form-group.mb-6(v-if='fields.message')
  55. label.block.text-sm.font-medium.mb-2(for='message' class='text-gray-700 dark:text-gray-300') Сообщение
  56. textarea.w-full.px-4.py-3.rounded-lg.border.transition-colors(
  57. id='message'
  58. rows='4'
  59. v-model='formData.message'
  60. @input='debouncedValidate("message")'
  61. @blur='validateField("message")'
  62. :class='getFieldClasses("message")'
  63. placeholder='Ваше сообщение...'
  64. )
  65. .validation-message.mt-2.text-sm.transition-all.duration-300(
  66. v-if='errors.message'
  67. class='text-red-500 dark:text-red-400'
  68. ) {{ errors.message }}
  69. //- Кнопка отправки
  70. button.submit-btn.w-full.bg-accent.text-white.py-3.px-6.rounded-lg.font-medium.transition-all(
  71. :disabled='!isFormValid || isSubmitting'
  72. type='submit'
  73. class='hover:bg-yellow-600 focus:ring-2 focus:ring-accent focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed'
  74. )
  75. .button-content.flex.items-center.justify-center
  76. span(v-if='!isSubmitting') Отправить
  77. span(v-else) Отправка...
  78. svg.w-4.h-4.ml-2(v-if='!isSubmitting' fill='none' stroke='currentColor' viewBox='0 0 24 24')
  79. path(stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M14 5l7 7m0 0l-7 7m7-7H3')
  80. //- Общий статус формы
  81. .form-status.mt-4.text-center
  82. .success-message.text-green-600.text-sm( class="dark:text-green-400"
  83. v-if='isSubmitted && !isSubmitting && isFormValid'
  84. ) ✅ Форма успешно отправлена!
  85. .error-message.text-red-500.text-sm( class="dark:text-red-400"
  86. v-if='Object.keys(errors).length > 0 && !isSubmitting'
  87. ) ⚠️ Пожалуйста, исправьте ошибки в форме