/* global $, window, document, showAlert, showConfirm, showQRCodeModal */ $(document).ready(function() { const adminLink = window.location.pathname.split('/').pop(); let questionnaireData = null; // Получаем базовый путь API (для работы и с /questioneer, и с /ms/questioneer) const getApiPath = () => { const pathParts = window.location.pathname.split('/'); // Убираем последние две части пути (admin/:adminLink) pathParts.pop(); pathParts.pop(); return pathParts.join('/') + '/api'; }; // Загрузка данных опроса const loadQuestionnaire = () => { $.ajax({ url: `${getApiPath()}/questionnaires/admin/${adminLink}`, method: 'GET', success: function(result) { if (result.success) { questionnaireData = result.data; renderQuestionnaire(); } else { $('#loading').text(`Ошибка: ${result.error}`); } }, error: function(error) { console.error('Error loading questionnaire:', error); $('#loading').text('Не удалось загрузить опрос. Пожалуйста, попробуйте позже.'); } }); }; // Отображение данных опроса const renderQuestionnaire = () => { // Заполняем основные данные $('#questionnaire-title').text(questionnaireData.title); $('#questionnaire-description').text(questionnaireData.description || 'Нет описания'); // Формируем ссылки const baseUrl = window.location.origin; const baseQuestionnairePath = window.location.pathname.split('/admin')[0]; const publicUrl = `${baseUrl}${baseQuestionnairePath}/poll/${questionnaireData.publicLink}`; const adminUrl = `${baseUrl}${baseQuestionnairePath}/admin/${questionnaireData.adminLink}`; $('#public-link').val(publicUrl); $('#admin-link').val(adminUrl); // Отображаем статистику renderStats(questionnaireData.questions); // Показываем контейнер с данными $('#loading').hide(); $('#questionnaire-container').show(); }; // Отображение статистики опроса const renderStats = (questions) => { const $statsContainer = $('#stats-container'); $statsContainer.empty(); // Проверяем, есть ли ответы let hasAnyResponses = false; // Проверяем наличие ответов для каждого типа вопросов for (const question of questions) { if (question.type === 'single' || question.type === 'multiple') { if (question.options && question.options.some(option => option.votes && option.votes > 0)) { hasAnyResponses = true; break; } } else if (question.type === 'tagcloud') { if (question.tags && question.tags.some(tag => tag.count && tag.count > 0)) { hasAnyResponses = true; break; } } else if (question.type === 'scale' || question.type === 'rating') { if (question.responses && question.responses.length > 0) { hasAnyResponses = true; break; } } else if (question.type === 'text') { if (question.textAnswers && question.textAnswers.length > 0) { hasAnyResponses = true; break; } } } if (!hasAnyResponses) { $statsContainer.html('
Пока нет ответов на опрос
'); return; } // Для каждого вопроса создаем блок статистики questions.forEach((question, index) => { const $questionStats = $('
', { class: 'question-stats' }); const $questionTitle = $('

', { text: `${index + 1}. ${question.text}` }); $questionStats.append($questionTitle); // В зависимости от типа вопроса отображаем разную статистику if (question.type === 'single' || question.type === 'multiple') { // Для вопросов с выбором вариантов const totalVotes = question.options.reduce((sum, option) => sum + (option.votes || 0), 0); if (totalVotes === 0) { $questionStats.append($('
', { class: 'no-votes', text: 'Нет голосов' })); } else { const $table = $('', { class: 'stats-table' }); const $thead = $('').append( $('').append( $(''); question.options.forEach(option => { const votes = option.votes || 0; const percent = totalVotes > 0 ? Math.round((votes / totalVotes) * 100) : 0; const $tr = $('').append( $('
', { text: 'Вариант' }), $('', { text: 'Голоса' }), $('', { text: '%' }), $('', { text: 'Визуализация' }) ) ); const $tbody = $('
', { text: option.text }), $('', { text: votes }), $('', { text: `${percent}%` }), $('').append( $('
', { class: 'bar-container' }).append( $('
', { class: 'bar', css: { width: `${percent}%` } }) ) ) ); $tbody.append($tr); }); $table.append($thead, $tbody); $questionStats.append($table); $questionStats.append($('
', { class: 'total-votes', text: `Всего голосов: ${totalVotes}` })); } } else if (question.type === 'tagcloud') { // Для облака тегов if (!question.tags || question.tags.length === 0 || !question.tags.some(tag => tag.count > 0)) { $questionStats.append($('
', { class: 'no-votes', text: 'Нет выбранных тегов' })); } else { const $tagCloud = $('
', { class: 'tag-cloud-stats' }); // Находим максимальное количество для масштабирования const maxCount = Math.max(...question.tags.map(tag => tag.count || 0)); // Сортируем теги по популярности const sortedTags = [...question.tags].sort((a, b) => (b.count || 0) - (a.count || 0)); sortedTags.forEach(tag => { if (tag.count && tag.count > 0) { const fontSize = maxCount > 0 ? 1 + (tag.count / maxCount) * 1.5 : 1; // от 1em до 2.5em $tagCloud.append( $('', { class: 'tag-item', text: `${tag.text} (${tag.count})`, css: { fontSize: `${fontSize}em` } }) ); } }); $questionStats.append($tagCloud); } } else if (question.type === 'scale' || question.type === 'rating') { // Для шкалы и рейтинга if (!question.responses || question.responses.length === 0) { $questionStats.append($('
', { class: 'no-votes', text: 'Нет оценок' })); } else { const values = question.responses; const sum = values.reduce((a, b) => a + b, 0); const avg = sum / values.length; const min = Math.min(...values); const max = Math.max(...values); const $scaleStats = $('
', { class: 'scale-stats' }); $scaleStats.append( $('
', { class: 'stat-item' }).append( $('', { class: 'stat-label', text: 'Среднее значение:' }), $('', { class: 'stat-value', text: avg.toFixed(1) }) ), $('
', { class: 'stat-item' }).append( $('', { class: 'stat-label', text: 'Минимум:' }), $('', { class: 'stat-value', text: min }) ), $('
', { class: 'stat-item' }).append( $('', { class: 'stat-label', text: 'Максимум:' }), $('', { class: 'stat-value', text: max }) ), $('
', { class: 'stat-item' }).append( $('', { class: 'stat-label', text: 'Количество оценок:' }), $('', { class: 'stat-value', text: values.length }) ) ); $questionStats.append($scaleStats); } } else if (question.type === 'text') { // Для текстовых ответов if (!question.textAnswers || question.textAnswers.length === 0) { $questionStats.append($('
', { class: 'no-votes', text: 'Нет текстовых ответов' })); } else { const $textAnswers = $('
', { class: 'text-answers-list' }); question.textAnswers.forEach((answer, i) => { $textAnswers.append( $('
', { class: 'text-answer-item' }).append( $('
', { class: 'answer-number', text: `#${i + 1}` }), $('
', { class: 'answer-text', text: answer }) ) ); }); $questionStats.append($textAnswers); } } $statsContainer.append($questionStats); }); }; // Копирование ссылок $('#copy-public-link').on('click', function() { $('#public-link').select(); document.execCommand('copy'); showAlert('Ссылка для голосования скопирована в буфер обмена', 'Копирование', null, true); }); $('#copy-admin-link').on('click', function() { $('#admin-link').select(); document.execCommand('copy'); showAlert('Административная ссылка скопирована в буфер обмена', 'Копирование', null, true); }); // Отображение QR-кода $('#show-qr-code').on('click', function() { const publicUrl = $('#public-link').val(); showQRCodeModal(publicUrl, 'QR-код для голосования'); }); // Редактирование опроса $('#edit-questionnaire').on('click', function() { const basePath = window.location.pathname.split('/admin')[0]; window.location.href = `${basePath}/edit/${adminLink}`; }); // Удаление опроса $('#delete-questionnaire').on('click', function() { showConfirm('Вы уверены, что хотите удалить опрос? Все ответы будут удалены безвозвратно.', function(confirmed) { if (confirmed) { deleteQuestionnaire(); } }, 'Удаление опроса'); }); // Функция удаления опроса const deleteQuestionnaire = () => { $.ajax({ url: `${getApiPath()}/questionnaires/admin/${adminLink}`, method: 'DELETE', success: function(result) { if (result.success) { showAlert('Опрос успешно удален', 'Удаление опроса', function() { window.location.href = window.location.pathname.split('/admin')[0]; }, true); } else { showAlert(`Ошибка при удалении опроса: ${result.error}`, 'Ошибка'); } }, error: function(error) { console.error('Error deleting questionnaire:', error); showAlert('Не удалось удалить опрос. Пожалуйста, попробуйте позже.', 'Ошибка'); } }); }; // Инициализация loadQuestionnaire(); // Обновление данных каждые 10 секунд setInterval(loadQuestionnaire, 10000); });