/* global $, window, document, alert, showAlert, showConfirm */ $(document).ready(function() { const form = $('#create-questionnaire-form'); const questionsList = $('#questions-list'); const addQuestionBtn = $('#add-question'); let questionCount = 0; // Функция для получения базового пути API const getApiPath = () => { // Проверяем, содержит ли путь /ms/ (продакшн на dev.bro-js.ru) const pathname = window.location.pathname; const isMsPath = pathname.includes('/ms/questioneer'); if (isMsPath) { // Для продакшна: если в пути есть /ms/, то API доступно по /ms/questioneer/api return '/ms/questioneer/api'; } else { // Для локальной разработки: формируем путь к API без учета текущей страницы // Извлекаем базовый путь из URL страницы до /create const basePath = pathname.split('/create')[0]; // Путь до API приложения return basePath + '/api'; } }; // Добавление нового вопроса addQuestionBtn.on('click', function() { addQuestion(); }); // Обработка отправки формы form.on('submit', function(e) { e.preventDefault(); saveQuestionnaire(); }); // Делегирование событий для динамических элементов questionsList.on('click', '.delete-question', function() { // Удаление вопроса const questionItem = $(this).closest('.question-item'); showConfirm('Вы уверены, что хотите удалить этот вопрос?', function(confirmed) { if (confirmed) { questionItem.remove(); renumberQuestions(); // Вызываем функцию обновления атрибутов required updateRequiredAttributes(); } }); }); questionsList.on('click', '.add-option', function() { // Добавление варианта ответа const questionIndex = $(this).data('question-index'); addOption(questionIndex); }); questionsList.on('click', '.delete-option', function() { // Удаление варианта ответа $(this).closest('.option-item').remove(); // Вызываем функцию обновления атрибутов required updateRequiredAttributes(); }); // Делегирование для изменения типа вопроса questionsList.on('change', '.question-type-select', function() { const questionItem = $(this).closest('.question-item'); const questionIndex = questionItem.data('index'); const optionsContainer = $(`#options-container-${questionIndex}`); const scaleContainer = $(`#scale-container-${questionIndex}`); // Скрыть/показать варианты ответа в зависимости от типа вопроса const questionType = $(this).val(); if (['single_choice', 'multiple_choice', 'tag_cloud'].includes(questionType)) { optionsContainer.show(); scaleContainer.hide(); // Если нет вариантов, добавляем два const optionsList = $(`#options-list-${questionIndex}`); if (optionsList.children().length === 0) { addOption(questionIndex); addOption(questionIndex); } // Включаем required для полей ввода вариантов optionsList.find('input[type="text"]').prop('required', true); } else if (questionType === 'scale') { optionsContainer.hide(); scaleContainer.show(); // Отключаем required для скрытых полей $(`#options-list-${questionIndex}`).find('input[type="text"]').prop('required', false); } else { optionsContainer.hide(); scaleContainer.hide(); // Отключаем required для скрытых полей $(`#options-list-${questionIndex}`).find('input[type="text"]').prop('required', false); } // Вызываем функцию обновления атрибутов required updateRequiredAttributes(); }); // Функция для добавления нового вопроса function addQuestion() { const template = $('#question-template').html(); const index = questionCount++; // Заменяем плейсхолдеры в шаблоне let questionHtml = template .replace(/\{\{index\}\}/g, index) .replace(/\{\{number\}\}/g, index + 1); questionsList.append(questionHtml); // Показываем/скрываем контейнер вариантов в зависимости от типа вопроса const questionType = $(`#question-type-${index}`).val(); if (!['single_choice', 'multiple_choice', 'tag_cloud'].includes(questionType)) { $(`#options-container-${index}`).hide(); // Отключаем required для скрытых полей $(`#options-list-${index}`).find('input[type="text"]').prop('required', false); } else { // Добавляем пару начальных вариантов ответа addOption(index); addOption(index); } if (questionType === 'scale') { $(`#scale-container-${index}`).show(); } else { $(`#scale-container-${index}`).hide(); } // Вызываем функцию обновления атрибутов required updateRequiredAttributes(); } // Функция для добавления варианта ответа function addOption(questionIndex) { const optionsList = $(`#options-list-${questionIndex}`); const template = $('#option-template').html(); const optionIndex = optionsList.children().length; // Заменяем плейсхолдеры в шаблоне let optionHtml = template .replace(/\{\{questionIndex\}\}/g, questionIndex) .replace(/\{\{optionIndex\}\}/g, optionIndex); optionsList.append(optionHtml); // Проверяем, видим ли контейнер опций const optionsContainer = $(`#options-container-${questionIndex}`); if (optionsContainer.is(':hidden')) { // Если контейнер скрыт, отключаем required у полей ввода optionsList.find('input[type="text"]').prop('required', false); } // Вызываем функцию обновления атрибутов required updateRequiredAttributes(); } // Перенумерация вопросов function renumberQuestions() { $('.question-item').each(function(index) { $(this).find('h3').text(`Вопрос ${index + 1}`); }); } // Функция для обновления нумерации вопросов function updateQuestionNumbers() { $('.question-item').each(function(index) { $(this).find('h3').text(`Вопрос ${index + 1}`); }); } // Сохранение опроса function saveQuestionnaire() { const questionnaire = { title: $('#title').val(), description: $('#description').val(), displayType: 'step_by_step', // Всегда устанавливаем пошаговый режим questions: [] }; // Собираем данные о вопросах $('.question-item').each(function() { const index = $(this).data('index'); const questionType = $(`#question-type-${index}`).val(); const question = { text: $(`#question-text-${index}`).val(), type: questionType, required: $(`input[name="questions[${index}][required]"]`).is(':checked'), options: [] }; // Добавляем настройки шкалы если нужно if (questionType === 'scale') { question.scaleMin = parseInt($(`#scale-min-${index}`).val()) || 0; question.scaleMax = parseInt($(`#scale-max-${index}`).val()) || 10; question.scaleMinLabel = $(`#scale-min-label-${index}`).val() || 'Минимум'; question.scaleMaxLabel = $(`#scale-max-label-${index}`).val() || 'Максимум'; } // Собираем варианты ответа если это не текстовый вопрос или шкала if (['single_choice', 'multiple_choice', 'tag_cloud'].includes(questionType)) { $(`#options-list-${index} .option-item`).each(function() { const optionText = $(this).find('input[type="text"]').val(); if (optionText) { question.options.push({ text: optionText, count: 0 }); } }); } questionnaire.questions.push(question); }); // Отправка на сервер $.ajax({ url: `${getApiPath()}/questionnaires`, method: 'POST', contentType: 'application/json', data: JSON.stringify(questionnaire), success: function(result) { if (result.success) { // Перенаправляем на страницу администратора const isMsPath = window.location.pathname.includes('/ms/questioneer'); let basePath; if (isMsPath) { // Для продакшна: используем /ms/questioneer basePath = '/ms/questioneer'; } else { // Для локальной разработки: используем текущий путь basePath = window.location.pathname.split('/create')[0]; } window.location.href = `${basePath}/admin/${result.data.adminLink}`; } else { showAlert(`Ошибка при создании опроса: ${result.error}`, 'Ошибка'); } }, error: function(error) { console.error('Error creating questionnaire:', error); showAlert('Не удалось создать опрос. Пожалуйста, попробуйте позже.', 'Ошибка'); } }); } // Функция для обновления атрибута required в зависимости от видимости полей function updateRequiredAttributes() { // Для полей вопросов $('.question-item').each(function() { const questionType = $(this).find('.question-type-select').val(); const textInput = $(this).find('.question-text'); const optionsContainer = $(this).find('.options-container'); // Обновляем required для текстового поля вопроса if (textInput.is(':visible')) { textInput.prop('required', true); } else { textInput.prop('required', false); } // Обновляем required для полей опций if (questionType === 'single_choice' || questionType === 'multiple_choice') { optionsContainer.find('input[type="text"]').each(function() { if ($(this).is(':visible')) { $(this).prop('required', true); } else { $(this).prop('required', false); } }); } else { optionsContainer.find('input[type="text"]').prop('required', false); } // Для шкалы оценки if (questionType === 'scale') { const minInput = $(this).find('.scale-min'); const maxInput = $(this).find('.scale-max'); const minLabelInput = $(this).find('.scale-min-label'); const maxLabelInput = $(this).find('.scale-max-label'); if (minInput.is(':visible')) minInput.prop('required', true); else minInput.prop('required', false); if (maxInput.is(':visible')) maxInput.prop('required', true); else maxInput.prop('required', false); if (minLabelInput.is(':visible')) minLabelInput.prop('required', true); else minLabelInput.prop('required', false); if (maxLabelInput.is(':visible')) maxLabelInput.prop('required', true); else maxLabelInput.prop('required', false); } }); // Для основных полей формы const titleInput = $('#title'); const descriptionInput = $('#description'); if (titleInput.is(':visible')) titleInput.prop('required', true); else titleInput.prop('required', false); if (descriptionInput.is(':visible')) descriptionInput.prop('required', false); // Описание не обязательно } // Инициализация с одним вопросом addQuestion(); // Обработчик отправки формы $('#create-questionnaire-form').on('submit', function(e) { // Обновляем атрибуты required перед отправкой updateRequiredAttributes(); // Проверяем валидность формы if (!this.checkValidity()) { e.preventDefault(); e.stopPropagation(); // Находим первый невалидный элемент и прокручиваем к нему const firstInvalid = $(this).find(':invalid').first(); if (firstInvalid.length) { $('html, body').animate({ scrollTop: firstInvalid.offset().top - 100 }, 500); // Добавляем класс ошибки к родительскому элементу вопроса firstInvalid.closest('.question-item').addClass('error'); setTimeout(() => { firstInvalid.closest('.question-item').removeClass('error'); }, 3000); } } $(this).addClass('was-validated'); }); // Инициализируем атрибуты required updateRequiredAttributes(); }); // Обработчик удаления вопроса $(document).on('click', '.remove-question', function() { $(this).closest('.question-item').remove(); updateQuestionNumbers(); // Вызываем функцию обновления атрибутов required updateRequiredAttributes(); }); // Обработчик удаления опции $(document).on('click', '.remove-option', function() { $(this).closest('.option-item').remove(); // Вызываем функцию обновления атрибутов required updateRequiredAttributes(); });