Files
erv-clientright/miniapp/js/common.js
2026-03-13 10:42:01 +03:00

2136 lines
88 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Функция инициализации автодополнения адресов через DaData
function initAddressSuggestions() {
if (typeof $.fn.suggestions !== 'undefined') {
// Инициализируем автодополнение адресов для поля с классом .js-adres
$('.js-adres').each(function() {
// Проверяем, не инициализировано ли уже
if (!$(this).data('suggestions-initialized')) {
$(this).suggestions({
token: "d2fa8613e186d54c6c62fc321414552353ffdfa8",
type: "ADDRESS",
onSelect: function(suggestion) {
// При выборе адреса заполняем поле
$(this).val(suggestion.value);
}
});
$(this).data('suggestions-initialized', true);
}
});
}
}
/** Возраст в годах по дате дд-мм-гггг; null при пустой/некорректной дате. Глобально для доступа из всех обработчиков. */
function getAge(dateString) {
if (!dateString) return null;
var today = new Date();
var birthDate = new Date(dateString.replace(/(\d{2})-(\d{2})-(\d{4})/, "$2/$1/$3"));
if (isNaN(birthDate.getTime())) return null;
var age = today.getFullYear() - birthDate.getFullYear();
var m = today.getMonth() - birthDate.getMonth();
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) age--;
return age;
}
$(function() {
$(document).ready(function(){
// F: нормальный регистр для списка стран (первая буква заглавная, остальные строчные)
function normalizeCountryLabel(text) {
return (text || '').trim().replace(/\S+/g, function(word) {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
});
}
$('select[name=countryevent] option, select[name=countrycode] option').each(function() {
var $opt = $(this), t = $opt.text().trim();
if (t) $opt.text(normalizeCountryLabel(t));
});
// Блокируем кнопку "Отправить смс" по умолчанию, пока полис не проверен
$('.js-send-sms').addClass('disabled');
$('.js-send-sms').prop('disabled', true);
// Поля телефона и банка скрыты по умолчанию (через класс d-none в HTML)
// Блокируем поле "ФИО Получателя" по умолчанию (доступно только для несовершеннолетних)
$("input[data-enableby=birthday]").addClass('disabled');
$("input[data-enableby=birthday]").prop('disabled', true);
$("input[data-enableby=birthday]").prop('readonly', true);
$(".js-progress-mask").inputmask("99");
$(".js-inn-mask").inputmask("999999999999");
$(".js-inn-mask2").inputmask("9{10,12}");
$(".js-bank-mask").inputmask({ mask: ["9999 9999 9999 9999", "9999 9999 9999 9999", "9999 9999 9999 9999", "9999 999999 99999"], greedy: false, "placeholder": "*", "clearIncomplete": true });
$(".js-code-mask").inputmask("999999");
$(".js-date-mask").inputmask("99-99-9999",{ "placeholder": "дд-мм-гггг" });
$(".js-doccode-mask").inputmask("99");
$(".js-countrycode-mask").inputmask("999");
// $("#country").countrySelect();
Inputmask.extendDefinitions({
'*': { //masksymbol
"validator": "[0-9\(\)\.\+/ ]"
},
});
// Номер полиса: буква + 35 цифр + дефис + до 20 символов (чтобы влезало A270-11968314/10 и т.п.)
$(".js-inndb-mask").inputmask("A9{3,5}-*{6,20}");
$(".js-inndb-mask").keyup(function(){
//if($this)
});
document.querySelector('input').addEventListener('keydown', function (e) {
if (e.which == 9) {
e.preventDefault();
}
});
let month =['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'];
let days = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];
if($('input[name="birthday"]').length) {
var birthday = datepicker('input[name="birthday"]',
{
customOverlayMonths: month,
customMonths: month,
customDays: days,
maxDate: new Date(),
disableYearOverlay: false, // C1: выбор года включён
formatter: function(input, date, instance) {
var d = date.getDate(), m = date.getMonth() + 1, y = date.getFullYear();
input.value = (d < 10 ? '0' + d : d) + '-' + (m < 10 ? '0' + m : m) + '-' + y; // дд-мм-гггг
},
onSelect: function(dateText, inst) {
var birthdayVal = $('input[name="birthday"]').val();
applyRepresentativeBlockVisibility(birthdayVal);
}
});
// C2: по умолчанию блок законного представителя скрыт
applyRepresentativeBlockVisibility($('input[name="birthday"]').val());
}
function applyRepresentativeBlockVisibility(birthdayVal) {
var age = birthdayVal ? getAge(birthdayVal) : null;
if (age !== null && age < 18) {
$('.form-item.js-representative-block[data-enableby-block=birthday], .form-item.js-representative-block[data-disabledby-block=birthday]').removeClass('d-none');
$("input[data-enableby=birthday]").removeClass('disabled').prop('disabled', false).prop('readonly', false);
$("input[data-disabledby=birthday]").removeClass('disabled').prop('disabled', false);
} else {
$('.form-item.js-representative-block[data-enableby-block=birthday], .form-item.js-representative-block[data-disabledby-block=birthday]').addClass('d-none');
$("input[data-enableby=birthday]").addClass('disabled').prop('disabled', true).prop('readonly', true).val('');
$("input[data-disabledby=birthday]").addClass('disabled').prop('disabled', true);
var $fileInput = $('input[data-disabledby=birthday]');
if ($fileInput.length) { $fileInput[0].value = ''; $fileInput.removeAttr('data-uploadurl'); $fileInput.closest('.form-item').find('.fileList').empty(); }
}
}
// Инициализация datepicker для поля даты рейса отправления
if($('input[name="departure_date"]').length) {
var departure_date = datepicker('input[name="departure_date"]',{
customOverlayMonths: month,
customMonths: month,
customDays: days,
maxDate: new Date(),
formatter: (input, date, instance) => {
const value = date.toLocaleDateString()
input.value = value // => '1/1/2099'
}
});
}
// Инициализация datepicker для всех полей «Дата наступления страхового случая» (авиа и отель)
$('input[name="insurence_date"]').each(function() {
datepicker(this, {
customOverlayMonths: month,
customMonths: month,
customDays: days,
maxDate: new Date(),
disableYearOverlay: false,
formatter: function(input, date, instance) {
var d = date.getDate(), m = date.getMonth() + 1, y = date.getFullYear();
input.value = (d < 10 ? '0' + d : d) + '-' + (m < 10 ? '0' + m : m) + '-' + y;
}
});
});
var phone = document.querySelectorAll('.js-phone-mask');
// Маска телефона (10 цифр без +7, т.к. код страны показываем отдельно)
// Нормализуем вставку 11-значных номеров (7/8 + 10 цифр) ДО того, как Inputmask обрежет лишнее.
function normalizeRfPhoneDigits(val) {
var digits = String(val || '').replace(/\D/g, '');
// Запрет +7, 8, 7 в начале — оставляем только 10 цифр номера РФ
if (digits.length >= 11 && (digits[0] === '7' || digits[0] === '8')) digits = digits.slice(1);
if (digits.length === 12 && digits.startsWith('77')) digits = digits.slice(2);
return digits.slice(0, 10);
}
function formatRfPhoneMasked(digits) {
if (digits.length === 0) return '';
var d = digits.slice(0, 10);
var s = d.slice(0,3);
if (d.length > 3) s += ' ' + d.slice(3,6);
if (d.length > 6) s += '-' + d.slice(6,8);
if (d.length > 8) s += '-' + d.slice(8,10);
return s;
}
$('.js-phone-mask').inputmask('999 999-99-99', {
onBeforePaste: function(pastedValue) {
var digits = normalizeRfPhoneDigits(pastedValue);
return digits;
}
});
$('.js-phone-mask').on('input', function() {
var $el = $(this);
var digits = normalizeRfPhoneDigits($el.val());
var formatted = formatRfPhoneMasked(digits);
if (formatted !== $el.val()) $el.val(formatted);
});
$('.js-phone-mask').on('keypress', function(e) {
var ch = String.fromCharCode(e.which || e.keyCode);
if (!/^\d$/.test(ch)) { e.preventDefault(); return; }
var digits = normalizeRfPhoneDigits($(this).val());
if (digits.length >= 10) e.preventDefault();
});
$('.js-phone-mask').on('keydown', function(e) {
var key = e.which || e.keyCode;
if (key !== 56 && key !== 55) return;
var el = this;
var start = el.selectionStart, end = el.selectionEnd;
var val = el.value || '';
var digitsBeforeCaret = val.slice(0, start).replace(/\D/g, '');
if (digitsBeforeCaret.length === 0 && (key === 56 || key === 55)) e.preventDefault();
});
phone.forEach(el => {
const iti = window.intlTelInput(el, {
initialCountry: 'ru',
onlyCountries : ['ru'],
separateDialCode: true,
customContainer: ".form-item",
autoPlaceholder: 'off', // Отключаем автоматический placeholder
allowDropdown: false, // Убираем выпадающий список
utilsScript: "libs/intl-tel-input-master/build/js/utils.js",
});
// Устанавливаем кастомный placeholder без "8", соответствует маске 999 999-99-99
el.setAttribute('placeholder', '912 345-67-89');
});
// Телефон средства размещения (отель и т.д.) — международный формат, без привязки к РФ
var placePhoneEls = document.querySelectorAll('.js-place-phone');
if (window.intlTelInput && placePhoneEls.length) {
placePhoneEls.forEach(function(el) {
window.intlTelInput(el, {
initialCountry: 'ru',
separateDialCode: true,
utilsScript: "libs/intl-tel-input-master/build/js/utils.js",
allowDropdown: true,
autoPlaceholder: 'off',
placeholderNumberType: 'MOBILE'
});
// Подсказка без кода страны — код уже показывается отдельно (флаг +7)
el.setAttribute('placeholder', '912 345-67-89');
// Очистка артефакта "kkkk..." при фокусе (если осталось от старого бага или маски)
el.addEventListener('focus', function() {
var v = (el.value || '').replace(/\s/g, '');
if (/^\+?7?k+$/.test(v) || /^k+$/.test(v)) el.value = '';
});
// Только цифры и символы номера; не более 15 цифр (маска)
function enforcePlacePhoneMask(inputEl) {
var v = inputEl.value || '';
var digits = v.replace(/\D/g, '');
if (digits.length > 15) digits = digits.slice(0, 15);
var allowed = v.replace(/[^\d+\s\-()]/g, '');
var allowedDigits = allowed.replace(/\D/g, '');
if (allowedDigits.length > 15) {
var take = '';
for (var i = 0, d = 0; i < allowed.length && d < 15; i++) {
if (/\d/.test(allowed[i])) d++;
take += allowed[i];
}
allowed = take;
}
if (v !== allowed) inputEl.value = allowed;
}
el.addEventListener('input', function() { enforcePlacePhoneMask(this); });
el.addEventListener('paste', function(e) {
var pasted = (e.clipboardData || window.clipboardData).getData('text');
var digits = pasted.replace(/\D/g, '').slice(0, 15);
var allowed = pasted.replace(/[^\d+\s\-()]/g, '');
if (allowed.replace(/\D/g, '').length > 15) allowed = digits;
if (pasted !== allowed) {
e.preventDefault();
var start = this.selectionStart, end = this.selectionEnd;
this.value = this.value.slice(0, start) + allowed + this.value.slice(end);
enforcePlacePhoneMask(this);
this.setSelectionRange(Math.min(start + allowed.length, this.value.length), Math.min(start + allowed.length, this.value.length));
}
});
});
}
// Дополнительно: делегированный обработчик, чтобы маска работала и при динамическом появлении поля
$(document).on('input', '.js-place-phone', function() {
var v = this.value || '';
var digits = v.replace(/\D/g, '');
if (digits.length > 15) {
var take = '';
for (var i = 0, d = 0; i < v.length && d < 15; i++) {
if (/\d/.test(v[i])) d++;
take += v[i];
}
this.value = take;
}
var allowed = v.replace(/[^\d+\s\-()]/g, '');
if (v !== allowed) this.value = allowed;
});
// Поля ФИО: только буквы (кириллица, латиница), пробел, дефис (для двойных фамилий)
var nameFieldsSelector = 'input[name="lastname"], input[name="firstname"], input[name="patronymic"]';
var nameAllowedRegex = /[^\u0400-\u04FFa-zA-Z\s\-]/g;
$(document).on('input', nameFieldsSelector, function() {
var v = this.value;
var allowed = v.replace(nameAllowedRegex, '');
if (v !== allowed) this.value = allowed;
});
$(document).on('paste', nameFieldsSelector, function(e) {
var pasted = (e.originalEvent && e.originalEvent.clipboardData) ? e.originalEvent.clipboardData.getData('text') : (window.clipboardData ? window.clipboardData.getData('Text') : '');
var allowed = pasted.replace(nameAllowedRegex, '');
if (pasted !== allowed) {
e.preventDefault();
var start = this.selectionStart, end = this.selectionEnd;
this.value = this.value.slice(0, start) + allowed + this.value.slice(end);
this.setSelectionRange(start + allowed.length, start + allowed.length);
}
});
// Защита от изменения подтвержденного номера телефона (в т.ч. через автозаполнение) — только для своего номера
$('.js-phone-mask').on('input change', function() {
var $this = $(this);
var confirmedPhone = $this.attr('data-confirmed-phone');
if (confirmedPhone && $this.prop('readonly')) {
var currentValue = $this.val();
if (currentValue !== confirmedPhone) {
$this.val(confirmedPhone);
}
}
// Дополнительно обновляем состояние кнопки SMS только для основного телефона
if ($this.attr('name') === 'phonenumber') {
updateSmsButtonState();
}
});
// Обработчик смены страны отключен, так как выпадающий список убран
// $('.js-phone-mask').on('countrychange', e => {
// let $this = $(e.currentTarget),
// placeholder = $this.attr('placeholder'),
// mask = placeholder.replace(/[0-9]/g, 9);
// $this.val('').inputmask(mask);
// let inputCode = $(".code"),
// flag = document.querySelector(".iti__selected-flag"),
// codeTitle = flag.getAttribute("title");
// inputCode.val(codeTitle);
// });
let index=1;
// miniapp: шаги с выбором авиа/отель
var isMiniapp = $('.js-step-choice').length > 0;
var miniappStepList = [];
var miniappStepIndex = -1;
var miniappClaimType = null;
var DEBUG_MINIAPP = false; // I: отладочный флаг для логирования claim_type и stepKey
function miniappShowStep(stepKey) {
if (DEBUG_MINIAPP) console.log('miniappShowStep:', stepKey);
$('.form-step').removeClass('active');
$('.js-step-common-applicant, .js-step-common-final').addClass('d-none');
$('.form-branch-avia, .form-branch-hotel').addClass('d-none');
if (stepKey === 'choice') {
$('.js-step-choice').removeClass('d-none').addClass('active');
} else if (stepKey === 'applicant') {
$('.js-step-choice').addClass('d-none');
$('.js-step-common-applicant').removeClass('d-none').addClass('active');
// Ветку не показываем — только ФИО; ветка откроется на следующем шаге (avia-1 / hotel-1)
} else if (stepKey === 'avia-1') {
$('.js-step-common-applicant').addClass('d-none');
$('.form-branch-avia').removeClass('d-none');
$('.form-branch-avia .form-step[data-step=avia-1]').addClass('active');
} else if (stepKey === 'hotel-1' || stepKey === 'hotel-2') {
$('.js-step-common-applicant').addClass('d-none');
$('.form-branch-hotel').removeClass('d-none');
$('.form-branch-hotel .form-step[data-step=' + stepKey + ']').addClass('active');
} else if (stepKey === 'final') {
$('.form-branch-avia .form-step, .form-branch-hotel .form-step').removeClass('active');
$('.form-branch-avia, .form-branch-hotel').addClass('d-none');
$('.js-step-common-final').removeClass('d-none').addClass('active');
}
}
function miniappValidateChoice() {
if ($('input[name=claim_type]:checked').length === 0) {
$('.js-step-choice .form-item__warning').text('Выберите тип обращения');
return false;
}
$('.js-step-choice .form-item__warning').text('');
return true;
}
// G: при смене типа обращения обновляем список шагов и счётчик в прогрессбаре
$('input[name=claim_type]').on('change', function() {
if (!isMiniapp || miniappStepList.length === 0) return;
miniappClaimType = $(this).val();
miniappStepList = miniappClaimType === 'avia' ? ['choice', 'applicant', 'avia-1', 'final'] : ['choice', 'applicant', 'hotel-1', 'hotel-2', 'final'];
$('.span-progress .total').text(miniappStepList.length);
});
$('.js-btn-next').on("click",function(e){
e.preventDefault();
if($(this).hasClass('disabled') || $(this).prop('disabled')) return false;
if (isMiniapp) {
// G: первый логический шаг — выбор типа (choice)
if (miniappStepIndex === 0) {
if (!miniappValidateChoice()) return;
miniappClaimType = $('input[name=claim_type]:checked').val();
miniappStepList = miniappClaimType === 'avia' ? ['choice', 'applicant', 'avia-1', 'final'] : ['choice', 'applicant', 'hotel-1', 'hotel-2', 'final'];
if (DEBUG_MINIAPP) console.log('miniapp claim_type:', miniappClaimType, 'stepList:', miniappStepList);
$('.span-progress .total').text(miniappStepList.length);
miniappStepIndex = 1;
miniappShowStep(miniappStepList[1]);
$('.span-progress .current').text(2);
$('.js-btn-prev').show();
return;
}
if (!validate_step(miniappStepIndex + 1)) return;
miniappStepIndex++;
$('.span-progress .current').text(miniappStepIndex + 1);
miniappShowStep(miniappStepList[miniappStepIndex]);
if (miniappStepIndex === miniappStepList.length - 1) {
$(this).hide();
$('.btn--submit').show();
} else {
$('.js-btn-prev').show();
}
return;
}
let isvalid=validate_step(index);
if(isvalid) {
index++;
$('.span-progress .current').text(index);
if(index==3) {
$(this).hide();
$('.btn--submit').show();
} else {
$(this).show();
$('.js-btn-prev').show();
}
$('.form-step').removeClass('active');
$('.form-step[data-step='+index+']').addClass('active');
}
});
// Сброс файлов при переходе «назад», чтобы повторная загрузка работала (A4)
function resetFileInputsForActiveStep() {
$('.form-step.active').find('input[type=file].js-attach').each(function() {
var $input = $(this);
$input[0].value = '';
$input.removeAttr('data-uploadurl').removeAttr('data-uploadurl_real');
$input.closest('.form-item').find('.fileList').empty();
$input.closest('.form-item').find('.form-item__warning').text('');
});
}
$('.js-btn-prev').on("click",function(e){
e.preventDefault();
if (isMiniapp && miniappStepList.length) {
miniappStepIndex--;
if (miniappStepIndex < 0) { miniappStepIndex = 0; return; }
$('.span-progress .current').text(miniappStepIndex + 1);
miniappShowStep(miniappStepList[miniappStepIndex]);
// Не сбрасываем файлы при «назад» — загруженные документы должны сохраняться
$('.btn--submit').hide();
$('.js-btn-next').show();
if (miniappStepIndex === 0) $('.js-btn-prev').hide();
return;
}
index--;
if(index==1) {$(this).hide();} else $(this).show();
if(index<1) index=1;
if(index<4) {
$('.btn--submit').hide();
$('.js-btn-next').show();
}
$('.span-progress .current').text(index);
$('.form-step').removeClass('active');
$('.form-step[data-step='+index+']').addClass('active');
// Не сбрасываем файлы при «назад» — загруженные документы должны сохраняться
});
$('select[name=claim]').on("change",function(e){
if($(this).val()==0) {
$(this).closest('.form-step').find('input[type=text]').addClass('disabled');
$(this).closest('.form-step').find('input[type=file]').addClass('disabled');
$(this).closest('.form-step').find('input[type=file]').parent().addClass('disabled');
} else {
$(this).closest('.form-step').find('input[type=text]').removeClass('disabled');
$(this).closest('.form-step').find('input[type=file]').removeClass('disabled');
$(this).closest('.form-step').find('input[type=file]').parent().removeClass('disabled');
}
});
$('select[name=countryevent]').on("change",function(e){
$('.countryevent').val($(this).find(":selected").text());
});
// Обработка изменения типа события
$('select[name="event_type"]').on('change', function() {
const selectedValue = $(this).val();
// Скрываем все дополнительные поля
$('.connection-fields, .connection-date-fields, .cancel-flight-docs').hide();
// Меняем лейблы в зависимости от выбора
if (selectedValue === 'miss_connection') {
$('#transport_number_label').text('Укажите номер рейса прибытия');
$('#insurence_date_label').text('Дата рейса прибытия');
$('.connection-fields, .connection-date-fields').show();
} else if (selectedValue === 'cancel_flight') {
$('#transport_number_label').text('Номер рейса/поезда/парома');
$('#insurence_date_label').text('Дата наступления страхового случая');
$('.cancel-flight-docs').show();
} else {
$('#transport_number_label').text('Номер рейса/поезда/парома');
$('#insurence_date_label').text('Дата наступления страхового случая');
}
});
function validate_step(step_index){
// B2: ветка НУ — на шаге hotel-2 требуется хотя бы один выбранный риск
if ($('.form-step.active[data-step="hotel-2"]').length) {
var riskChecked = $('.form-step.active').find('.js-enable-inputs input[type=checkbox]:checked').length;
if (riskChecked === 0) {
$('.form-step.active').find('.form-item__warning').first().text('Выберите хотя бы один тип риска');
return false;
}
}
// B3: для выбранных рисков в hotel-2 требуем файл
if ($('.form-step.active[data-step="hotel-2"]').length) {
$('.form-step.active').find('.form-item').each(function() {
var $item = $(this);
var $chk = $item.find('.js-enable-inputs input[type=checkbox]:checked');
if ($chk.length && $item.find('input[type=file].js-attach').length) {
var fileInput = $item.find('input[type=file].js-attach')[0];
var fileListCount = $item.find('.fileList li').length;
if (!fileInput.files.length && fileListCount === 0) {
$item.find('.form-item__warning').text('Загрузите подтверждающие документы по выбранному риску');
}
}
});
}
let inputs=$('.form-step.active').find('input[type="text"], input[type="tel"], input[type="file"], input[type="email"], textarea.form-input, input[type="checkbox"]');
let all_filled=false;
let res_array=[];
inputs.each(function(e){
let field_fill=false;
let $this = $(this);
// Пропускаем поля, которые помечены как не требующие валидации
if($this.hasClass('notvalidate')) {
field_fill=true; // Считаем невалидируемые поля валидными
res_array.push(field_fill);
return;
}
// Пропускаем поля, которые заблокированы (disabled или readonly)
if($this.prop('disabled') || $this.prop('readonly') || $this.hasClass('disabled')) {
field_fill=true; // Считаем заблокированные поля валидными
res_array.push(field_fill); // Добавляем в массив результатов
return; // Пропускаем дальнейшую проверку
}
// Пропускаем поля, которые находятся в скрытых блоках (d-none или display: none)
if($this.closest('.d-none').length > 0) {
field_fill=true; // Считаем скрытые поля валидными
res_array.push(field_fill);
return;
}
// Проверяем, скрыт ли родительский блок через inline стиль display: none
let $parentContainer = $this.closest('.form-item');
if($parentContainer.length > 0 && $parentContainer.is(':hidden')) {
field_fill=true; // Считаем скрытые поля валидными
res_array.push(field_fill);
return;
}
if(($this.val()=='' && !$this.hasClass('disabled') && !$this.hasClass('notvalidate') && !$this.hasClass('error') )) {
$this.closest('.form-item').find('.form-item__warning').text('Пожалуйста, заполните все обязательные поля');
field_fill=false;
} else {
$this.closest('.form-item').find('.form-item__warning').text('');
if($this.attr('type')=='email'){
var emailVal = ($this.val() || '').trim();
if(emailVal && validateEmail(emailVal)) {
field_fill=true;
} else if(!emailVal) {
field_fill=false;
$this.closest('.form-item').find('.form-item__warning').text('Пожалуйста, заполните все обязательные поля');
} else {
field_fill=false;
$this.closest('.form-item').find('.form-item__warning').text($this.data('warmes') || 'Укажите корректный email');
}
} else if($this.hasClass('js-phone-mask') || $this.attr('name') === 'phonenumber') {
var digits = ($this.val() || '').replace(/\D/g, '');
if (digits.length === 11 && (digits[0] === '7' || digits[0] === '8')) digits = digits.slice(1);
if (digits.length === 10) {
field_fill = true;
$this.closest('.form-item').find('.form-item__warning').text('');
} else {
field_fill = false;
$this.closest('.form-item').find('.form-item__warning').text('Укажите номер телефона: 10 цифр без 8 или +7');
}
} else if($this.hasClass('js-place-phone')) {
var digitsPlace = ($this.val() || '').replace(/\D/g, '');
if (digitsPlace.length >= 10 && digitsPlace.length <= 15) {
field_fill = true;
$this.closest('.form-item').find('.form-item__warning').text('');
} else if (digitsPlace.length === 0) {
field_fill = false;
$this.closest('.form-item').find('.form-item__warning').text('Пожалуйста, заполните все обязательные поля');
} else {
field_fill = false;
$this.closest('.form-item').find('.form-item__warning').text('Номер телефона: от 10 до 15 цифр');
}
} else if($this.attr('type')=='file') {
// Специальная валидация для файлов
var fileInput = this;
var filesCount = fileInput.files ? fileInput.files.length : 0;
// Проверяем также через fileList, если файлы уже обработаны
var fileListItems = $this.closest('.form-item').find('.fileList li').length;
// Если поле находится в скрытом блоке, но есть другое видимое поле с таким же name - пропускаем
var fieldName = $this.attr('name');
var isHidden = $this.closest('.d-none').length > 0;
if(isHidden && fieldName) {
// Проверяем, есть ли видимое поле с таким же name
var visibleField = $('.form-step.active').find('input[name="' + fieldName + '"]').not($this).filter(function() {
return $(this).closest('.d-none').length === 0;
});
if(visibleField.length > 0) {
// Есть видимое поле с таким же name - пропускаем скрытое
field_fill=true;
res_array.push(field_fill);
return;
}
}
// Для видимых полей проверяем наличие файлов
if(!isHidden) {
if(filesCount > 0 || fileListItems > 0) {
field_fill=true;
} else {
field_fill=false;
$this.closest('.form-item').find('.form-item__warning').text('Пожалуйста, загрузите файлы');
}
} else {
// Скрытое поле без видимого дубликата - считаем валидным
field_fill=true;
}
} else {
// Специальная валидация для поля банка
if($this.hasClass('js-bank-autocomplete')) {
var bankId = $this.closest('.form-item').find('input[name="bank_id"]').val();
if(bankId && bankId !== '') {
field_fill=true;
} else {
field_fill=false;
$this.closest('.form-item').find('.form-item__warning').text('Пожалуйста, выберите банк из списка');
}
} else {
field_fill=true;
}
}
if($this.attr('type')=='checkbox'){
if($this.is(':checked')){
field_fill=true;
$this.parent().parent().find('.form-item__warning').text();
} else {
field_fill=false;
$this.parent().parent().find('.form-item__warning').text('Пожалуйста, заполните все обязательные поля');
}
if(($this.parent().hasClass('js-enable-inputs'))){
field_fill=true;
$this.parent().parent().find('.form-item__warning').text('');
}
}
}
res_array.push(field_fill);
// Отладочный вывод для незаполненных полей отключен
});
// C3: проверка длины описания (502000 символов) на шагах, где есть textarea[name=description]
var $descField = $('.form-step.active').find('textarea[name=description]');
if ($descField.length && $descField.closest('.d-none').length === 0) {
var len = ($descField.val() || '').length;
if (len < 50) {
$descField.closest('.form-item').find('.form-item__warning').text('Опишите ситуацию: не менее 50 символов (сейчас ' + len + ')');
return false;
}
if (len > 2000) {
$descField.closest('.form-item').find('.form-item__warning').text('Описание не должно превышать 2000 символов');
return false;
}
}
// Согласие на обработку ПД (последний шаг):
// - в старом трёхшаговом потоке — на шаге 3
// - в miniapp — только на общем финальном шаге js-step-common-final
var isFinalStep = (!isMiniapp && step_index === 3) || $('.form-step.active.js-step-common-final').length > 0;
if (isFinalStep && $('.form-step.active').find('input[name=agree]:checked').length < 1) {
$('.form__warning').show();
$('.form__warning').text('Необходимо согласие с политикой обработки персональных данных');
return false;
} else {
$('.form__warning').text('Пожалуйста, заполните все обязательные поля');
}
if(!res_array.includes(false)){
$('.form__warning').hide();
return true;
} else {
$('.form__warning').show();
return false;
}
}
const validateEmail = (email) => {
return email.match(
/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
);
};
$('.js-enable-inputs input[type=checkbox]').on("change",function(e){
e.preventDefault();
var $formItem = $(this).closest('.form-item');
$formItem.find('input[type=file]').toggleClass('disabled');
$formItem.find('input[type=file]+label').toggleClass('disabled');
if (!$(this).is(':checked')) {
var $fileInput = $formItem.find('input[type=file].js-attach');
if ($fileInput.length) {
$fileInput[0].value = '';
$formItem.find('.fileList').empty();
$formItem.find('.form-item__warning').text('');
}
}
});
// start sms
// Глобальные переменные и помощники для SMS
var sms_verify_token = null;
var smsCooldownIntervalId = null;
var smsCooldownExpiresAt = null;
var smsIsSending = false;
function getSmsSecondsLeft() {
if (!smsCooldownExpiresAt) return 0;
var diff = Math.floor((smsCooldownExpiresAt - Date.now()) / 1000);
return diff > 0 ? diff : 0;
}
function updateSmsCountdownUI() {
var secondsLeft = getSmsSecondsLeft();
var $container = $('.sms-countdown');
if (!$container.length) return;
if (secondsLeft <= 0) {
$container.hide();
$container.find('.time').text('');
$('.modal .js-send-sms').show();
$('.sms-checking button.js-accept-sms').hide();
return;
}
$container.show();
$container.find('.time').text(secondsLeft + 'с');
// Пока таймер тикает, кнопка повторной отправки скрыта
$('.modal .js-send-sms').hide();
$('.sms-checking button.js-accept-sms').show();
}
function startSmsCooldown(seconds) {
if (!seconds || seconds <= 0) return;
smsCooldownExpiresAt = Date.now() + seconds * 1000;
if (smsCooldownIntervalId) {
clearInterval(smsCooldownIntervalId);
smsCooldownIntervalId = null;
}
updateSmsCountdownUI();
smsCooldownIntervalId = setInterval(function() {
if (getSmsSecondsLeft() <= 0) {
clearInterval(smsCooldownIntervalId);
smsCooldownIntervalId = null;
updateSmsCountdownUI();
} else {
updateSmsCountdownUI();
}
}, 1000);
}
// Нормализация номера телефона для SMS (приводим к виду +7XXXXXXXXXX)
function getPhoneForSms($phoneInput) {
let raw = ($phoneInput && $phoneInput.length) ? ($phoneInput.val() || '') : '';
// Пробуем взять номер через intlTelInput (если он инициализирован)
if ($phoneInput && $phoneInput.length && window.intlTelInput && window.intlTelInputGlobals) {
const iti = window.intlTelInputGlobals.getInstance($phoneInput[0]);
if (iti) {
try {
const fullNumber = iti.getNumber(); // обычно возвращает +7...
if (fullNumber) raw = fullNumber;
} catch (e) {
// игнорируем
}
}
}
raw = (raw || '').trim();
if (!raw) return '';
// Оставляем только цифры
let digits = raw.replace(/\D/g, '');
// Фикс кейса "+77..." (двойная 7 из-за некорректной нормализации на фронте)
// Примеры:
// - +77927961181 -> digits=77927961181 (11) -> должно стать 7927961181 (10)
// - +77XXXXXXXXXX -> digits=77.......... (12) -> должно стать 7.......... (11), далее доведём до 10
if (digits.startsWith('77') && (digits.length === 11 || digits.length === 12)) {
digits = '7' + digits.slice(2);
}
// РФ: 11 цифр с лидирующей 7 или 8 -> приводим к 10 цифрам
if (digits.length === 11 && (digits[0] === '7' || digits[0] === '8')) {
digits = digits.slice(1);
}
// РФ: 10 цифр -> +7 + 10 цифр
if (digits.length === 10) {
return '+7' + digits;
}
// Если вдруг осталось 11 цифр и начинается с 7 (редкий случай) — возвращаем как +7XXXXXXXXXX
if (digits.length === 11 && digits.startsWith('7')) {
return '+' + digits;
}
// Fallback: если цифр >= 10 — берём последние 10 как РФ-номер
if (digits.length >= 10) {
return '+7' + digits.slice(-10);
}
return raw;
}
function isValidSmsPhone(phone) {
if (!phone) return false;
var digits = String(phone).replace(/\D/g, '');
// Для РФ требуем строго 11 цифр и первую 7 (формат +7XXXXXXXXXX)
return digits.length === 11 && digits[0] === '7';
}
function validateSmsPhone($phoneInput, options) {
options = options || {};
var phone = getPhoneForSms($phoneInput);
var $warning = $phoneInput.closest('.form-item').find('.form-item__warning');
if (!phone || !isValidSmsPhone(phone)) {
if (options.showError) {
$warning.text('Пожалуйста, укажите полный номер телефона');
}
return null;
}
$warning.text('');
return phone;
}
function updateSmsButtonState() {
var $phoneInput = $('input[name=\"phonenumber\"]');
if (!$phoneInput.length) return;
var phone = validateSmsPhone($phoneInput, { showError: false });
var isValid = !!phone && getSmsSecondsLeft() === 0;
var $btn = $('.sms-check .js-send-sms');
$btn.prop('disabled', !isValid).toggleClass('disabled', !isValid);
}
if (typeof window !== 'undefined') { window.updateSmsButtonState = updateSmsButtonState; }
function send_sms(){
var $phoneInput = $('input[name=\"phonenumber\"]');
var phone = validateSmsPhone($phoneInput, { showError: true });
if (!phone) {
return false;
}
// Блокируем повторные отправки, пока идёт запрос или работает таймер
if (smsIsSending || getSmsSecondsLeft() > 0) {
return false;
}
smsIsSending = true;
// Показываем загрузку
$('.sms-check .js-send-sms').prop('disabled', true).addClass('disabled').text('Отправка...');
$.ajax({
url: 'sms-verify.php?action=send',
method: 'post',
data: {
phonenumber: phone
},
dataType: 'json',
success: function(data) {
if (data.success) {
smsIsSending = false;
// После успешной отправки запускаем единый таймер повторной отправки
startSmsCooldown(30);
updateSmsButtonState();
$('.sms-check .js-send-sms').text('Отправить смс');
if (data.demo_code) {
$('.js-code-warning').text('Режим без SMS: введите код из модалки').show();
$('#confirm_sms .js-code-mask').val(data.demo_code);
$('#confirm_sms .js-demo-code-display').remove();
$('#confirm_sms .form-item.sms-checking').first().prepend('<div class="js-demo-code-display" style="margin-bottom:12px;padding:10px;background:#f0f9ff;border:1px solid #0ea5e9;border-radius:6px;font-weight:600;">Код для проверки: ' + data.demo_code + '</div>');
} else {
$('.js-code-warning').text('Код отправлен на ваш номер телефона');
}
$.fancybox.open({
src: '#confirm_sms',
type: 'inline'
});
} else {
var $warning = $('input[name=\"phonenumber\"]').closest('.form-item').find('.form-item__warning');
$warning.text(data.message || 'Ошибка отправки SMS');
smsIsSending = false;
updateSmsButtonState();
}
},
error: function (jqXHR, exception) {
var errorMsg = 'Ошибка отправки SMS';
if (jqXHR.responseJSON && jqXHR.responseJSON.message) {
errorMsg = jqXHR.responseJSON.message;
}
var $warning = $('input[name=\"phonenumber\"]').closest('.form-item').find('.form-item__warning');
$warning.text(errorMsg);
smsIsSending = false;
updateSmsButtonState();
}
});
return null; // Код больше не генерируется на клиенте
}
// Функция countDown больше не используется напрямую, оставлена как заглушка
function countDown(elm, duration, fn){
startSmsCooldown(duration);
}
// Отправка SMS из основного блока (после проверки полиса и выбора банка)
$('.sms-check .js-send-sms').on('click', function(e) {
e.preventDefault();
// Не даём кликать, пока идёт запрос или работает таймер
if (smsIsSending || getSmsSecondsLeft() > 0) {
return false;
}
// Проверка валидности полиса перед отправкой SMS
var indatabase = $('.js-indatabase').val();
// Проверяем, был ли полис загружен вручную (через policy-upload-section)
var polisInput = $('#polis_upload')[0];
var polisUploaded = polisInput && polisInput.files && polisInput.files.length > 0;
// Если полис невалидный И не загружен вручную - блокируем отправку
if((indatabase == '0' || indatabase == '' || indatabase == undefined) && !polisUploaded) {
$('.form__warning').show();
$('.form__warning').text('Пожалуйста, проверьте полис. Ваш полис не покрывает данный вид обращения.');
return false;
}
// Валидация телефона перед отправкой SMS
var $phoneInput = $('input[name=\"phonenumber\"]');
var phone = validateSmsPhone($phoneInput, { showError: true });
if (!phone) {
return false;
}
// Валидация поля банка перед отправкой SMS
var bankInput = $('.js-bank-autocomplete');
var bankId = $('input[name="bank_id"]').val();
if (!bankInput.val() || !bankId || bankId === '') {
bankInput.closest('.form-item').find('.form-item__warning').text('Пожалуйста, выберите банк из списка');
bankInput.focus();
return false;
} else {
bankInput.closest('.form-item').find('.form-item__warning').text('');
}
// Отправляем SMS через новый безопасный API (только после успешной валидации)
send_sms();
// Старт таймера будет выполнен в send_sms() при успешном ответе
$('.modal .form-item__warning').text("");
});
// Обработчик для повторной отправки SMS из модального окна
$(document).on('click', '.modal .js-send-sms', function(e) {
e.preventDefault();
// Не даём кликать, пока идёт запрос или работает таймер
if (smsIsSending || getSmsSecondsLeft() > 0) {
return false;
}
var $phoneInput = $('input[name="phonenumber"]');
var phone = validateSmsPhone($phoneInput, { showError: true });
if (!phone) {
return false;
}
// Отправляем SMS
$('.modal .js-send-sms').prop('disabled', true).text('Отправка...');
$('.modal .form-item__warning').text('');
$.ajax({
url: 'sms-verify.php?action=send',
method: 'post',
data: {
phonenumber: phone
},
dataType: 'json',
success: function(data) {
if (data.success) {
smsIsSending = false;
$('.modal .form-item__warning').text('').removeClass('form-item__warning--error');
if (data.demo_code) {
$('.js-code-warning').text('Режим без SMS: введите код из модалки').show();
$('#confirm_sms .js-code-mask').val(data.demo_code);
$('#confirm_sms .js-demo-code-display').remove();
$('#confirm_sms .form-item.sms-checking').first().prepend('<div class="js-demo-code-display" style="margin-bottom:12px;padding:10px;background:#f0f9ff;border:1px solid #0ea5e9;border-radius:6px;font-weight:600;">Код для проверки: ' + data.demo_code + '</div>');
} else {
$('.js-code-warning').text('Код отправлен на ваш номер телефона').show();
}
// После успешной повторной отправки запускаем/продлеваем таймер
startSmsCooldown(30);
updateSmsButtonState();
} else {
$('.modal .form-item__warning').text(data.message || 'Ошибка отправки SMS');
$('.modal .js-send-sms').prop('disabled', false).text('Отправить повторно');
}
},
error: function (jqXHR, exception) {
var errorMsg = 'Ошибка отправки SMS';
if (jqXHR.responseJSON && jqXHR.responseJSON.message) {
errorMsg = jqXHR.responseJSON.message;
}
$('.modal .form-item__warning').text(errorMsg);
$('.modal .js-send-sms').prop('disabled', false).text('Отправить повторно');
smsIsSending = false;
}
});
});
$('.sms-checking .js-accept-sms').on('click', function(e) {
e.preventDefault();
var code = $('.sms-checking input[type="text"]').val();
var $phoneInput = $('input[name="phonenumber"]');
var phone = validateSmsPhone($phoneInput, { showError: true });
if (!code || !phone) {
$('.modal .form-item__warning').text("Введите код подтверждения");
return false;
}
// Показываем загрузку
$('.js-accept-sms').prop('disabled', true).text('Проверка...');
$('.modal .form-item__warning').text('');
// Проверяем код на сервере
$.ajax({
url: 'sms-verify.php?action=verify',
method: 'post',
data: {
phonenumber: phone,
code: code
},
dataType: 'json',
success: function(data) {
if (data.success) {
// Код подтвержден (токен больше не используется)
// sms_verify_token = data.token; // Убрано - токен больше не нужен
$('.sms-success').removeClass('d-none');
// Проверяем, был ли полис уже проверен
var indatabase = $('.js-indatabase').val();
if(indatabase == '1') {
// Если полис валидный, сразу показываем форму для заполнения
$('.db-success').removeClass('d-none');
$('.form-step[data-step=1]').removeClass('disabled');
// Инициализируем автодополнение адресов после показа формы
setTimeout(function() {
initAddressSuggestions();
}, 500);
} else {
// Если полис невалидный, но был загружен через policy-upload-section, показываем форму
var polisInput = $('#polis_upload')[0];
var polisUploaded = polisInput && polisInput.files && polisInput.files.length > 0;
if(polisUploaded) {
$('.db-success').removeClass('d-none');
$('.form-step[data-step=1]').removeClass('disabled');
// Инициализируем автодополнение адресов
setTimeout(function() {
initAddressSuggestions();
}, 500);
}
}
$('.modal .js-send-sms').show();
$('.sms-check .form-item > .js-send-sms').hide();
$.fancybox.close();
$.fancybox.close();
$('.sms-check').addClass("disabled");
// G: скрываем блок проверки полиса, показываем только шаг выбора
$('.sms-check').addClass('d-none');
// Инициализируем шаги miniapp: choice — первый логический шаг
if (typeof isMiniapp !== 'undefined' && isMiniapp) {
miniappStepList = ['choice', 'applicant', 'avia-1', 'final'];
miniappStepIndex = 0;
$('.span-progress .total').text(miniappStepList.length);
$('.span-progress .current').text(1);
$('.js-btn-prev').hide();
$('.js-btn-next').show();
}
// Только у поля «Ваш номер телефона» (phonenumber), не у телефона отеля
var $phoneField = $('input[name="phonenumber"]');
$phoneField.closest('.form-item').find('.form-item__warning')
.addClass('form-item__warning--success')
.text("Вы успешно подтвердили номер");
// Блокируем только поле своего телефона после подтверждения
var confirmedPhone = $phoneField.val();
$phoneField.attr('data-confirmed-phone', confirmedPhone)
// .attr('data-verify-token', sms_verify_token) // Убрано - токен больше не нужен
.prop('readonly', true)
.attr('autocomplete', 'off');
$('.js-accept-sms').prop('disabled', false).text('Подтвердить');
} else {
$('.modal .form-item__warning').text(data.message || "Неверный код");
$('.sms-success').addClass('d-none');
$('.js-accept-sms').prop('disabled', false).text('Подтвердить');
}
},
error: function (jqXHR, exception) {
var errorMsg = "Ошибка проверки кода";
if (jqXHR.responseJSON && jqXHR.responseJSON.message) {
errorMsg = jqXHR.responseJSON.message;
}
$('.modal .form-item__warning').text(errorMsg);
$('.sms-success').addClass('d-none');
$('.js-accept-sms').prop('disabled', false).text('Подтвердить');
}
});
});
$('.form.active form').submit(function(e){
if(!validate_step(index)){ e.preventDefault(); } else {
e.preventDefault();
$('button[type="submit"]').attr("disabled", true);
if(1) {
$('.js-code-warning').text('');
$('.js-code-warning').hide();
$('.js-send-sms').hide();
$.fancybox.open({
src: '#confirm_sms',
type: 'inline'
});
$('.loader-wrap').removeClass('d-none');
$('button[type="submit"]').attr("disabled", false);
$('button[type="submit"]').text("Данные отправляются...");
var formData = new FormData();
let fileIndex = 0; // Счетчик для правильной индексации файлов
// Отправляем файлы напрямую как бинарные данные (без предварительной загрузки через fileupload_v2.php)
jQuery.each(jQuery('input[type=file].js-attach').not('.disabled'), function(i, file) {
if(!$(this).hasClass('disabled')) {
// Используем field-type или name для группировки файлов
let field_name=jQuery(this).data('field-type') || jQuery(this).attr('name');
let docname=jQuery(this).data('docname');
// Отправляем файлы напрямую как бинарные данные в submit.php
jQuery.each(jQuery(this)[0].files, function(i, file) {
formData.append(field_name+'-'+i, file);
});
// УБРАНО: старая система загрузки через fileupload_v2.php
// Теперь файлы отправляются напрямую в submit.php как бинарные данные
// n8n будет обрабатывать файлы сам
}
});
jQuery.each(jQuery('.js-append'), function(i, file) {
let ws_name=jQuery(this).data('ws_name');
let ws_type=jQuery(this).data('ws_type');
let val="";
if(jQuery(this).attr('type') == 'checkbox'){
if(jQuery(this).is(':checked')){
val=jQuery(this).val();
}
} else {
val=jQuery(this).val();
}
let array={
ws_name : ws_name,
ws_type: ws_type,
field_val : val
};
formData.append('appends[]',JSON.stringify(array));
});
formData.append('lastname',jQuery('[name="lastname"]').val());
formData.append('getservice',jQuery('[name="getservice"]').val()); //Если есть агент посредник
let sub_dir=jQuery('input[name=sub_dir]').val();
formData.append('sub_dir',sub_dir);
if (typeof isMiniapp !== 'undefined' && isMiniapp && miniappClaimType) {
formData.append('claim_type', miniappClaimType);
}
// Отладочный вывод отключен
// for (var pair of formData.entries()) {
// console.log(pair[0]+ ', ' + pair[1]);
// }
$.ajax({
url: 'submit.php',
method: 'post',
cache: false,
contentType: false,
processData: false,
data: formData,
dataType: 'json',
success: function(data) {
// Отладочный вывод отключен
// console.log(data);
$('.loader-wrap').addClass('d-none');
$.fancybox.close();
$.fancybox.open({
src: '#success_modal',
type: 'inline'
});
setTimeout(function(){
$.fancybox.close();
},30)
setTimeout(function(){
window.location.href = "https://lexpriority.ru/ok";
},30)
$('button[type="submit"]').text("Отправить");
},
error: function (jqXHR, exception) {
// Отладочный вывод отключен
// console.log(jqXHR);
if (jqXHR.status === 0) {
alert('Not connect. Verify Network.');
} else if (jqXHR.status == 404) {
alert('Requested page not found (404).');
} else if (jqXHR.status == 500) {
alert('Internal Server Error (500).');
} else if (exception === 'parsererror') {
} else if (exception === 'timeout') {
alert('Time out error.');
} else if (exception === 'abort') {
alert('Ajax request aborted.');
} else {
alert('Uncaught Error. ' + jqXHR.responseText);
}
}
});
return false;
} else {
$('.js-code-warning').text('Неверный код');
return false;
}
}
});
});
$('input[name=place],input[name=place_adres],input[name=place_inn]').keyup(function(e){
var sourceInput = $(this);
var query = $(this).val();
var settings = {
"url": "https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/party",
"method": "POST",
"timeout": 0,
"headers": {
"Authorization": "Token d2fa8613e186d54c6c62fc321414552353ffdfa8",
"Content-Type": "application/json"
},
"data": JSON.stringify({
"query": query
}),
};
$('.autocomplete__item').remove();
var address_array = [];
$.ajax(settings).done(function (response) {
for(let i=0; i<response.suggestions.length; i++) {
$('<div class="autocomplete__item" data-address="'+response.suggestions[i].data.address.value+'" data-inn="'+response.suggestions[i].data.inn+'">'+response.suggestions[i].value+'</div>').appendTo(sourceInput.closest('.form-item').find('.form-item__dropdown'));
}
});
});
$(document).on('click', '.autocomplete__item', function() {
let currentAutocompleteItem=$(this);
let prefix = $(this).closest('.autocomplete').data('groupename');
$('.'+prefix+'_name').val(currentAutocompleteItem.text());
$('.'+prefix+'_adres').val(currentAutocompleteItem.attr('data-address'));
$('.'+prefix+'_inn').val(currentAutocompleteItem.attr('data-inn'));
currentAutocompleteItem.closest('.form-item').find('.form-item__dropdown').empty();
});
// Автоподстановка банков из API
let banksList = []; // Кэш списка банков
let banksLoading = false; // Флаг загрузки
// Загрузка списка банков через прокси на сервере (обход CORS)
function loadBanksList() {
if (banksLoading) return; // Предотвращаем множественные запросы
banksLoading = true;
$.ajax({
url: 'load_banks.php', // PHP скрипт на сервере для обхода CORS
method: 'GET',
dataType: 'json',
timeout: 15000, // 15 секунд таймаут
success: function(data) {
banksLoading = false;
if (Array.isArray(data)) {
banksList = data;
// Отладочный вывод отключен
// console.log('Загружено банков:', banksList.length);
// Убираем предупреждение об ошибке, если оно было
$('.js-bank-autocomplete').closest('.form-item').find('.form-item__warning').text('');
} else if (data && data.error) {
// Отладочный вывод отключен
// console.error('Ошибка от сервера:', data.error);
showBanksLoadError('Ошибка сервера: ' + data.error);
} else {
// Отладочный вывод отключен
// console.error('Неверный формат данных:', data);
showBanksLoadError('Неверный формат данных от сервера');
}
},
error: function(jqXHR, exception) {
banksLoading = false;
// Отладочный вывод отключен
// console.error('Ошибка загрузки списка банков:', exception, jqXHR);
var errorMsg = 'Не удалось загрузить список банков';
if (jqXHR.status === 0) {
errorMsg += ' (нет соединения)';
} else if (jqXHR.status === 404) {
errorMsg += ' (файл прокси не найден)';
} else if (jqXHR.status === 500) {
errorMsg += ' (ошибка сервера)';
} else if (exception === 'timeout') {
errorMsg += ' (превышено время ожидания)';
}
showBanksLoadError(errorMsg);
}
});
}
// Показать ошибку загрузки банков
function showBanksLoadError(message) {
var bankInput = $('.js-bank-autocomplete');
if (bankInput.length) {
var warningText = message || 'Не удалось загрузить список банков. Пожалуйста, обновите страницу или введите название банка вручную.';
bankInput.closest('.form-item').find('.form-item__warning')
.text(warningText)
.css('color', '#dc3545');
}
}
// Загружаем банки при загрузке страницы
$(document).ready(function() {
// Небольшая задержка, чтобы убедиться, что DOM готов
setTimeout(function() {
loadBanksList();
}, 100);
});
// Популярные банки (показываются первыми)
var popularBanks = ['Сбербанк', 'ВТБ', 'Альфа-Банк', 'Тинькофф', 'Райффайзен Банк', 'Газпромбанк', 'Россельхозбанк', 'ПСБ', 'МКБ', 'ЮМани'];
// Функция для сортировки банков (популярные вверху)
function sortBanks(banks) {
return banks.sort(function(a, b) {
var aIndex = popularBanks.findIndex(function(name) {
return a.bankName.indexOf(name) !== -1;
});
var bIndex = popularBanks.findIndex(function(name) {
return b.bankName.indexOf(name) !== -1;
});
if (aIndex === -1 && bIndex === -1) return 0;
if (aIndex === -1) return 1;
if (bIndex === -1) return -1;
return aIndex - bIndex;
});
}
// Автоподстановка банков
$('.js-bank-autocomplete').on('input keyup', function(e) {
var sourceInput = $(this);
var query = $(this).val().toLowerCase().trim();
var formItem = sourceInput.closest('.form-item');
var dropdown = formItem.find('.form-item__dropdown');
// При ручном изменении поля убираем подпись «Банк выбран»
formItem.find('.form-item__warning').removeClass('form-item__warning--success').text('');
// Очищаем предыдущие результаты
dropdown.empty();
// Если запрос пустой, показываем больше банков (30) с популярными вверху
if (query.length === 0) {
var sortedBanks = sortBanks(banksList.slice());
showBanksDropdown(sortedBanks.slice(0, 30), dropdown, sourceInput, banksList.length, true);
return;
}
// Фильтруем банки по запросу
var filteredBanks = banksList.filter(function(bank) {
return bank.bankName.toLowerCase().indexOf(query) !== -1;
});
// Показываем результаты (максимум 50 при поиске)
showBanksDropdown(filteredBanks.slice(0, 50), dropdown, sourceInput, filteredBanks.length, false);
});
// Функция для отображения выпадающего списка банков
function showBanksDropdown(banks, dropdown, sourceInput, totalCount, showHint) {
dropdown.empty();
if (banks.length === 0) {
dropdown.append('<div class="autocomplete__item" style="padding: 10px; color: #999;">Банки не найдены</div>');
return;
}
banks.forEach(function(bank) {
var item = $('<div class="autocomplete__item" data-bank-id="' + bank.bankId + '" data-bank-name="' + bank.bankName + '" style="cursor: pointer;">' + bank.bankName + '</div>');
dropdown.append(item);
});
// Добавляем подсказку внизу списка
if (showHint && totalCount > banks.length) {
var hint = $('<div class="autocomplete__hint" style="padding: 12px 15px; background: #f8f9fa; border-top: 1px solid #e9ecef; font-size: 12px; color: #6c757d; text-align: center; border-radius: 0 0 4px 4px;">' +
'<strong>Показано ' + banks.length + ' из ' + totalCount + ' банков</strong><br>' +
'Начните вводить название банка для поиска по всем ' + totalCount + ' банкам'
+ '</div>');
dropdown.append(hint);
} else if (!showHint && totalCount > banks.length) {
var hint = $('<div class="autocomplete__hint" style="padding: 10px 15px; background: #f8f9fa; border-top: 1px solid #e9ecef; font-size: 12px; color: #6c757d; text-align: center;">' +
'Найдено: ' + totalCount + ' банков. Показано ' + banks.length + '. Уточните запрос для более точного поиска.'
+ '</div>');
dropdown.append(hint);
}
}
// Обработчик выбора банка - используем mousedown для надежности
$(document).on('mousedown', '.form-item__dropdown .autocomplete__item', function(e) {
e.preventDefault();
e.stopPropagation();
var selectedItem = $(this);
var bankId = selectedItem.attr('data-bank-id');
var bankName = selectedItem.attr('data-bank-name');
var formItem = selectedItem.closest('.form-item');
// Проверяем, что это не подсказка
if (selectedItem.hasClass('autocomplete__hint')) {
return false;
}
// Заполняем поля
var bankInput = formItem.find('.js-bank-autocomplete');
var bankIdInput = formItem.find('input[name="bank_id"]');
bankInput.val(bankName);
bankIdInput.val(bankId);
// Очищаем выпадающий список
formItem.find('.form-item__dropdown').empty();
// Показываем подтверждение выбора банка
formItem.find('.form-item__warning').removeClass('form-item__warning--error').addClass('form-item__warning--success').text('Банк выбран');
// Убираем фокус с input
bankInput.blur();
// Отладочный вывод отключен
// console.log('Банк выбран:', bankName, 'ID:', bankId);
return false;
});
// Дублируем обработчик на click для совместимости
$(document).on('click', '.form-item__dropdown .autocomplete__item', function(e) {
e.preventDefault();
e.stopPropagation();
var selectedItem = $(this);
// Проверяем, что это не подсказка
if (selectedItem.hasClass('autocomplete__hint')) {
return false;
}
// Если mousedown не сработал, обрабатываем здесь
var bankId = selectedItem.attr('data-bank-id');
var bankName = selectedItem.attr('data-bank-name');
var formItem = selectedItem.closest('.form-item');
if (bankId && bankName) {
formItem.find('.js-bank-autocomplete').val(bankName);
formItem.find('input[name="bank_id"]').val(bankId);
formItem.find('.form-item__dropdown').empty();
formItem.find('.form-item__warning').removeClass('form-item__warning--error').addClass('form-item__warning--success').text('Банк выбран');
}
return false;
});
// При фокусе показываем список банков
$('.js-bank-autocomplete').on('focus', function() {
var sourceInput = $(this);
var dropdown = sourceInput.closest('.form-item').find('.form-item__dropdown');
var query = $(this).val().toLowerCase().trim();
if (banksList.length === 0) {
// Если банки еще не загружены, пробуем загрузить
loadBanksList();
return;
}
if (query.length === 0) {
var sortedBanks = sortBanks(banksList.slice());
showBanksDropdown(sortedBanks.slice(0, 30), dropdown, sourceInput, banksList.length, true);
} else {
// Триггерим событие input для фильтрации
$(this).trigger('input');
}
});
// Скрываем выпадающий список при потере фокуса (с задержкой для клика)
$('.js-bank-autocomplete').on('blur', function(e) {
var sourceInput = $(this);
var dropdown = sourceInput.closest('.form-item').find('.form-item__dropdown');
// Увеличиваем задержку, чтобы клик успел обработаться
setTimeout(function() {
// Проверяем, не кликнули ли мы на элемент списка или внутри dropdown
var activeElement = document.activeElement;
var relatedTarget = e.relatedTarget;
// Если фокус перешел на элемент из dropdown, не скрываем
if (relatedTarget && $(relatedTarget).closest('.form-item__dropdown').length) {
return;
}
if (!$(activeElement).hasClass('autocomplete__item') &&
!$(activeElement).closest('.form-item__dropdown').length) {
dropdown.empty();
}
}, 200);
});
// Предотвращаем blur при клике на dropdown
$(document).on('mousedown', '.form-item__dropdown', function(e) {
// Останавливаем всплытие, чтобы blur не сработал на input
e.stopPropagation();
});
// Инициализация автодополнения адресов при загрузке страницы
setTimeout(function() {
initAddressSuggestions();
}, 1000);
// $('input[name=db_birthday],input[name=db_inn]').keyup(function(e){
$(document).on('click', '.js-check-in', function(e) {
e.preventDefault();
let birthday=$('input[name=birthday]').val();
let police_number=$('input[name=police_number]').val();
if(police_number.slice(0,1)=="Е"){
police_number=police_number.replace(/Е/g, 'E');
}
if(police_number.slice(0,1)=="А"){
police_number=police_number.replace(/А/g, 'A');
}
let dbdata={
"action" : "user_verify",
'birthday' : birthday.replace(/-/g, '.'),
'inn' : police_number
}
// Показываем загрузку
$('.js-check-in').prop('disabled', true).text('Проверка...');
$('.js-result').html('').removeClass('danger form-item__warning--success');
$.ajax({
url: 'database.php',
method: 'post',
data: dbdata,
dataType: 'json',
success: function(data) {
$('.js-check-in').prop('disabled', false).text('Проверить наличие полиса');
// Если data уже объект, не парсим
let res = typeof data === 'string' ? JSON.parse(data) : data;
if(res.success=="true"){
// Полис валидный - показываем успешное сообщение
$('.js-result').html(res.message);
$('.js-result').removeClass("danger");
$('.js-result').addClass("form-item__warning--success");
$('input[name=insured_from]').val(res.result.insured_from.replace(/\./g, '-'));
$('input[name=insured_to]').val(res.result.insured_to.replace(/\./g, '-'));
$('.js-indatabase').val('1');
$('.policy-upload-section').addClass('d-none');
// Показываем поля телефона и банка после успешной проверки полиса
$('.policy-validated-fields').removeClass('d-none');
// Скрываем кнопку «Проверить наличие полиса» — полис уже проверен
$('.js-check-in').closest('.form-item').addClass('d-none');
// Разблокируем кнопку \"Отправить смс\" если полис валидный (с учётом валидности номера и cooldown)
if (typeof window.updateSmsButtonState === 'function') window.updateSmsButtonState();
$('.form__warning').hide();
// Если SMS уже подтверждено, сразу показываем форму для заполнения
if($('.sms-success').is(':visible') || !$('.sms-success').hasClass('d-none')) {
$('.db-success').removeClass('d-none');
$('.form-step[data-step=1]').removeClass('disabled');
}
// Инициализируем автодополнение адресов после проверки полиса
setTimeout(function() {
initAddressSuggestions();
}, 500);
} else {
// Полис не найден - показываем ТОЛЬКО поле для загрузки скана полиса
$('.js-indatabase').val('0');
// Убираем сообщение об ошибке из .js-result
$('.js-result').html('');
$('.js-result').removeClass("danger form-item__warning--success");
// НЕ показываем форму (.sms-success), только блок загрузки полиса
$('.sms-success').addClass('d-none');
$('.db-success').addClass('d-none');
// Показываем ТОЛЬКО блок для загрузки полиса
$('.policy-upload-section').removeClass('d-none');
$('.policy-upload-section').find('input[type=file]').removeClass("notvalidate");
$('.policy-upload-section').find('input[type=file]').removeClass("disabled");
// Показываем уведомление о необходимости загрузить полис
$('.policy-upload-section').find('.form-item__warning')
.text('Загрузите скан полиса для продолжения')
.css('color', '#856404')
.show();
// Скрываем поля телефона и банка
$('.policy-validated-fields').addClass('d-none');
// Показываем кнопку «Проверить наличие полиса» снова (полис не найден)
$('.js-check-in').closest('.form-item').removeClass('d-none');
// Блокируем кнопку "Отправить смс"
$('.js-send-sms').addClass('disabled');
$('.js-send-sms').prop('disabled', true);
$('.form__warning').hide();
}
return false;
},
error: function (jqXHR, exception) {
$('.js-check-in').prop('disabled', false).text('Проверить наличие полиса');
var errorMsg = 'Ошибка при проверке полиса';
if (jqXHR.responseText) {
try {
var errorData = JSON.parse(jqXHR.responseText);
if (errorData.message) {
errorMsg = errorData.message;
}
} catch(e) {
errorMsg = jqXHR.responseText.substring(0, 100);
}
}
$('.js-result').html(errorMsg)
.removeClass('form-item__warning--success')
.addClass('danger');
console.error('Ошибка проверки полиса:', jqXHR, exception);
return false;
}
});
});
$('input[name=birthday]').on("change input", function (e) {
// Отладочный вывод отключен
// console.log("Date changed: ", e.target.value);
let birthday=$(this).val();
if(getAge(birthday)<18) {
// Если возраст меньше 18 - разблокируем поле
$("input[data-enableby=birthday]").removeClass('disabled');
$("input[data-disabledby=birthday]").removeClass('disabled');
$("input[data-enableby=birthday]").prop('disabled', false);
$("input[data-enableby=birthday]").prop('readonly', false);
} else {
// Если возраст 18 и больше - блокируем поле
$("input[data-enableby=birthday]").addClass('disabled');
$("input[data-disabledby=birthday]").addClass('disabled');
$("input[data-enableby=birthday]").prop('disabled', true);
$("input[data-enableby=birthday]").prop('readonly', true);
$("input[data-enableby=birthday]").val(''); // Очищаем значение при блокировке
}
});
$('input[name=lastname],input[name=firstname],input[name=patronymic]').keyup(function(e){
let full_name=$('input[name=lastname]').val()+" "+$('input[name=firstname]').val()+" "+$('input[name=patronymic]').val();
$("input[data-enableby=birthday]").val(full_name);
});
// C3: счётчик и ограничение описания (502000)
$('textarea[name=description]').on('input', function() {
var len = (this.value || '').length;
$(this).closest('.form-item').find('.js-description-counter').text(len + ' / 2000');
}).trigger('input');
// C4: серия и номер документа — макс. 20 символов, только буквы/цифры/пробелы
$('.js-doc-number').on('input', function() {
var val = this.value.replace(/[^\d A-Za-zА-Яа-яЁё]/g, '').slice(0, 20);
if (val !== this.value) this.value = val;
});
// Загрузка файлов
function declOfNum(number, words) {
return words[(number % 100 > 4 && number % 100 < 20) ? 2 : [2, 0, 1, 1, 1, 2][(number % 10 < 5) ? Math.abs(number) % 10 : 5]];
}
function updateSize(elem) {
var filesQty = elem[0].files.length;
if(filesQty>10) {
elem.closest('.form-item').find('.form-item__warning').text("Разрешено не более 10 файлов");
return;
}
elem.closest('.form-item').find('.form-item__warning').text('');
let file_status=[];
var formats = ['pdf','jpg','png','jpeg'];
for(var i=0; i<filesQty; i++) {
var file = elem[0].files[i],
ext = "не определилось",
parts = file.name.split('.');
if (parts.length > 1) ext = parts.pop();
if(!formats.includes((ext || '').toLowerCase())) {
elem.closest('.form-item').find('.form-item__warning').append('<div> Файл '+file.name+' не подходит по формату. Допустимые форматы: pdf, jpg, png </div>');
elem.addClass('error');
file_status.push(false);
} else {
// elem.closest('.form-item').find('.form-item__warning').text();
if((file.size/1024/1024) > 20){
file_status.push(false);
elem.closest('.form-item').find('.form-item__warning').append('<div>Размер файла '+file.name+' превышает 20 Мб. </div>');
} else {
elem.removeClass('error');
file_status.push(true);
}
}
}
// ОТКЛЮЧЕНО: старая система загрузки файлов через fileupload_v2.php
// Файлы теперь отправляются напрямую в submit.php как бинарные данные
if(file_status.every(val => val === true))
{
// upload_file(elem); // ОТКЛЮЧЕНО - файлы отправляются напрямую при submit формы
$('.form__action').find('.js-btn-next').removeClass('disabled');
} else {
$('.form__action').find('.js-btn-next').addClass('disabled');
}
}
function upload_file(thisfile) {
let formData = new FormData();
let field_name=thisfile.data('crmname') || thisfile.data('field-type');
let docname=thisfile.data('docname');
// Отладочный вывод отключен
// console.log('=== UPLOAD_FILE FUNCTION ===');
// console.log('Uploading for field:', field_name, 'docname:', docname);
// console.log('File input element:', thisfile[0]);
// console.log('Files in input:', thisfile[0].files);
// console.log('Field type:', thisfile.data('field-type'));
// console.log('Form item:', thisfile.closest('.form-item')[0]);
let sub_dir=jQuery('input[name=sub_dir]').val();
jQuery.each(thisfile[0].files, function(i, file) {
formData.append(field_name+'-'+i, file);
});
thisfile.closest('.form-item').find('.suсcess-upload').remove();
formData.append('lastname',jQuery('input[name=lastname]').val());
formData.append('files_names[]',field_name);
formData.append('docs_names[]',docname);
formData.append('sub_dir',sub_dir);
thisfile.closest('.form-item').append("<p class='info-upload'></p>");
// for (var pair of formData.entries()) {
// console.log(pair[0]+ ', ' + pair[1]);
// }
$.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
// Upload progress
xhr.upload.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
//Do something with upload progress
let complete=Math.round(percentComplete * 100);
// Отладочный вывод отключен
// console.log(complete);
thisfile.closest('.form-item').find(".info-upload").text("Загружено "+complete+" %");
}
}, false);
// Download progress
xhr.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
// Do something with download progress
// Отладочный вывод отключен
// console.log(percentComplete);
}
}, false);
return xhr;
},
url: 'https://form.clientright.ru/fileupload_v2.php',
method: 'post',
cache: false,
contentType: false,
processData: false,
data: formData,
// dataType : 'json',
beforeSend : function (){
$('.form__action').find('.js-btn-next').addClass('disabled');
$('.form__action').find('.btn--submit').addClass('disabled');
},
success: function(data) {
let res=JSON.parse(data);
if(res.success=="true"){
// Отладочный вывод отключен
// console.log(res);
// thisfile.closest('.form-item').append("<p class='suсcess-upload'>Файл успешно загружен на сервер.</p>");
thisfile.attr('data-uploadurl',res.empty_file);
thisfile.attr('data-uploadurl_real',res.real_file);
// thisfile.closest('.form-item').append("<p class='suсcess-upload'>"+res.message+"</p>");
thisfile.closest('.form-item').find('.info-upload').remove();
$('.form__action').find('.js-btn-next').removeClass('disabled');
$('.form__action').find('.btn--submit').removeClass('disabled');
} else {
}
return false;
},
error: function (jqXHR, exception) {
return false;
}
});
}
function formatBytes(bytes, decimals = 2) {
if (!+bytes) return '0 Bytes'
const k = 1024
const dm = decimals < 0 ? 0 : decimals
const sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`
}
var fileIdCounter = 0;
jQuery('.js-attach').each(function() {
var fieldType = $(this).data('field-type'); // Получаем тип поля
let filethis = $(this);
// Создаем изолированное хранилище файлов для каждого поля
var fieldFiles = {
filesToUpload: [],
fieldType: fieldType
};
filethis.change(function (evt) {
var output = [];
let elem= $(this);
let currentFieldFiles = fieldFiles; // Используем изолированное хранилище
let currentFormItem = elem.closest('.form-item');
// Очищаем предупреждения только для текущего поля
currentFormItem.find('.form-item__warning').text('');
let file_status=[];
var formats = ['pdf','jpg','png','jpeg'];
// Отладочный вывод отключен
// console.log('=== FILE UPLOAD START ===');
// console.log('Processing files for field type:', currentFieldFiles.fieldType);
// console.log('Field element:', elem[0]);
// console.log('Form item:', currentFormItem[0]);
// console.log('Files to process:', evt.target.files);
// console.log('Current fieldFiles state:', currentFieldFiles);
if(evt.target.files.length>10) {
elem.closest('.form-item').find('.form-item__warning').text("Разрешено не более 10 файлов");
return;
}
// Очищаем предыдущий список файлов для этого поля
currentFormItem.find('.fileList').empty();
currentFieldFiles.filesToUpload = [];
for (var i = 0; i < evt.target.files.length; i++) {
fileIdCounter++;
var file = evt.target.files[i];
var fileId = "fileid_" + fileIdCounter;
// Отладочный вывод отключен
// console.log(file);
let ext = "не определилось";
let parts = file.name.split('.');
if (parts.length > 1) ext = parts.pop();
if(!formats.includes((ext || '').toLowerCase())) {
elem.closest('.form-item').find('.form-item__warning').append('<div> Файл '+file.name+' не подходит по формату. Допустимые форматы: pdf, jpg, png </div>');
elem.addClass('error');
file_status.push(false);
} else {
if((file.size/1024/1024) > 20){
file_status.push(false);
elem.closest('.form-item').find('.form-item__warning').append('<div>Размер файла '+file.name+' превышает 20 Мб. </div>');
} else {
elem.removeClass('error');
file_status.push(true);
var removeLink = "<a class=\"removefile\" href=\"#\" data-fileid=\"" + fileId + "\"></a>";
output.push("<li><strong>", file.name, "</strong> <span class='size'> ", formatBytes(file.size) , " </span> ", removeLink, "</li> ");
currentFieldFiles.filesToUpload.push({
id: fileId,
file: file
});
}
}
//evt.target.value = null;
// elem.closest('.form-item').find('.upload-action').removeClass('d-none');
};
currentFormItem.find(".fileList").append(output.join(""));
let container = new DataTransfer();
for (var i = 0, len = currentFieldFiles.filesToUpload.length; i < len; i++) {
container.items.add(currentFieldFiles.filesToUpload[i].file);
}
elem[0].files = container.files;
if(file_status.every(val => val === true))
{
// Отладочный вывод отключен
// console.log('=== FILE UPLOAD SUCCESS ===');
// console.log('Uploading files for field type:', currentFieldFiles.fieldType);
// console.log('Final fieldFiles state:', currentFieldFiles);
// console.log('Files in DataTransfer:', elem[0].files);
// upload_file(elem); // ОТКЛЮЧЕНО - файлы отправляются напрямую при submit формы
$('.form__action').find('.js-btn-next').removeClass('disabled');
// Если загружен полис из блока policy-upload-section, показываем телефон и банк
if(currentFieldFiles.fieldType === 'polis' && elem.closest('.policy-upload-section').length > 0) {
// Полис остаётся виден в блоке загрузки (список файлов остаётся на экране),
// дополнительно показываем поля телефона и банка
$('.policy-validated-fields').removeClass('d-none');
// Разблокируем кнопку "Отправить смс" (с учётом дальнейшей валидации номера)
if (typeof window.updateSmsButtonState === 'function') window.updateSmsButtonState();
// Убираем уведомление
$('.policy-upload-section').find('.form-item__warning').text('').hide();
}
} else {
// Отладочный вывод отключен
// console.log('=== FILE UPLOAD FAILED ===');
// console.log('File status:', file_status);
$('.form__action').find('.js-btn-next').addClass('disabled');
}
});
// Обработчик удаления файлов с доступом к fieldFiles через замыкание
$(this).closest('.form-item').on("click", ".removefile", function (e) {
let elem = $(this);
e.preventDefault();
var fileId = elem.data("fileid");
// Находим соответствующий input файла для этого .form-item
let fileInput = elem.closest('.form-item').find('input[type="file"].js-attach');
let fieldType = fileInput.data('field-type');
// Отладочный вывод отключен
// console.log('=== REMOVE FILE ===');
// console.log('Removing file with ID:', fileId);
// console.log('From field type:', fieldType);
// console.log('Current fieldFiles:', fieldFiles);
// Используем fieldFiles из замыкания
for (var i = 0; i < fieldFiles.filesToUpload.length; ++i) {
if (fieldFiles.filesToUpload[i].id === fileId) {
fieldFiles.filesToUpload.splice(i, 1);
// Отладочный вывод отключен
// console.log('File removed from fieldFiles');
break;
}
}
elem.parent().remove();
if(fieldFiles.filesToUpload.length == 0) {
elem.closest('.form-item').find('.upload-action').addClass('d-none');
elem.closest('.form-item').find('.suсcess-upload').text('');
} else {
let container = new DataTransfer();
for (var i = 0, len = fieldFiles.filesToUpload.length; i < len; i++) {
container.items.add(fieldFiles.filesToUpload[i].file);
}
fileInput[0].files = container.files;
updateSize(fileInput);
}
});
});
// End Загрузка файлов
});