const TOTAL = 24; document.addEventListener('DOMContentLoaded', function () { // Добавить поле комментария под каждый вопрос document.querySelectorAll('.question[data-index]').forEach(q => { const name = (q.querySelector('[name]') || {}).name || ''; const ta = document.createElement('textarea'); ta.className = 'question-comment'; ta.name = name + '_comment'; ta.placeholder = 'Свой комментарий или уточнение (необязательно)...'; q.appendChild(ta); }); updateProgress(); document.getElementById('client_email').addEventListener('input', function () { document.getElementById('_replyto').value = this.value; }); document.getElementById('_replyto').value = document.getElementById('client_email').value; document.getElementById('btnReset').addEventListener('click', function () { if (!confirm('Очистить всю форму? Это действие нельзя отменить.')) return; document.getElementById('questionnaireForm').querySelectorAll('input[type="radio"], input[type="checkbox"]').forEach(el => el.checked = false); document.getElementById('questionnaireForm').querySelectorAll('textarea, input[type="text"], input[type="tel"], input[type="email"]').forEach(el => { if (!['client_name','client_email'].includes(el.id)) el.value = ''; }); document.querySelectorAll('.other-input').forEach(el => el.classList.remove('visible')); updateProgress(); updatePreview(); showFlash('Форма очищена'); }); document.getElementById('btnSave').addEventListener('click', function () { updateURL(); showFlash('Сохранено!'); document.getElementById('saveStatus').textContent = 'Сохранено ' + formatTime(); }); document.getElementById('btnShare').addEventListener('click', function () { updateURL(); const url = window.location.href; if (navigator.clipboard) { navigator.clipboard.writeText(url).then(() => showFlash('Ссылка скопирована!')); } else { const ta = document.createElement('textarea'); ta.value = url; ta.style.position = 'fixed'; ta.style.opacity = '0'; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); showFlash('Ссылка скопирована!'); } }); // Модальное окно const generalForm = document.getElementById('generalForm'); if (generalForm) { generalForm.addEventListener('submit', async function (e) { e.preventDefault(); const btn = document.getElementById('generalSubmitBtn'); btn.disabled = true; btn.textContent = 'Отправляем...'; document.getElementById('general_replyto').value = document.getElementById('g_email').value; try { const res = await fetch(generalForm.action, { method: 'POST', body: new FormData(generalForm), headers: { 'Accept': 'application/json' } }); if (res.ok) { generalForm.style.display = 'none'; document.getElementById('modalSuccess').style.display = 'block'; } else throw new Error(); } catch { btn.disabled = false; btn.textContent = 'Отправить обращение'; showFlash('Ошибка. Попробуйте ещё раз.'); } }); } document.addEventListener('keydown', e => { if (e.key === 'Escape') closeModal(); }); document.getElementById('questionnaireForm').addEventListener('change', function () { updateProgress(); updatePreview(); handleConditionals(); }); document.getElementById('questionnaireForm').addEventListener('input', function () { updateProgress(); updatePreview(); }); document.getElementById('questionnaireForm').addEventListener('submit', function (e) { // Собрать чекбоксы в одно скрытое поле const checked = [...document.querySelectorAll('input[name="admin_features"]:checked')].map(el => el.value); let hidden = document.getElementById('admin_features_combined'); if (!hidden) { hidden = document.createElement('input'); hidden.type = 'hidden'; hidden.id = 'admin_features_combined'; hidden.name = 'admin_features_combined'; document.getElementById('questionnaireForm').appendChild(hidden); } hidden.value = checked.join(', '); const now = new Date(); const tz = Intl.DateTimeFormat().resolvedOptions().timeZone; const offsetMin = -now.getTimezoneOffset(); const offsetSign = offsetMin >= 0 ? '+' : '-'; const offsetHours = String(Math.floor(Math.abs(offsetMin) / 60)).padStart(2, '0'); const offsetMins = String(Math.abs(offsetMin) % 60).padStart(2, '0'); document.getElementById('sender_time').value = now.toLocaleString('ru-RU', { hour12: false }) + ` (UTC${offsetSign}${offsetHours}:${offsetMins}, ${tz})`; document.getElementById('sender_timezone').value = tz; document.getElementById('anton_time').value = now.toLocaleString('ru-RU', { timeZone: 'Europe/Helsinki', hour12: false, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }) + ' (UTC+3, Финляндия)'; }, true); handleConditionals(); }); function handleConditionals() { // Показать поле "свой вариант" для радио с value="other"/"limited" const conditionals = [ { radio: 'price_per_hour', value: 'other', inputId: 'price_other' }, { radio: 'lock_system', value: 'other', inputId: 'lock_other' }, { radio: 'design_style', value: 'other', inputId: 'design_other' }, { radio: 'multi_hour', value: 'limited', inputId: 'multi_hour_limit' }, ]; conditionals.forEach(({ radio, value, inputId }) => { const selected = document.querySelector(`input[name="${radio}"]:checked`); const input = document.getElementById(inputId); if (!input) return; if (selected && selected.value === value) { input.classList.add('visible'); } else { input.classList.remove('visible'); } }); } function updateProgress() { const radioGroups = [ 'slot_type','multi_hour','calendar_view','advance_booking','self_cancel', 'price_per_hour','price_tiers','refund_policy','invoice', 'lock_system','pin_length','pin_delivery', 'booking_confirm','reminder_before','time_warning','admin_notify', 'client_history', 'product_format','language', 'logo','design_style', 'terms','privacy' ]; let filled = 0; // Радио (23 группы) radioGroups.forEach(name => { if (document.querySelector(`input[name="${name}"]:checked`)) filled++; }); // Чекбокс (1 группа) if (document.querySelector('input[name="admin_features"]:checked')) filled++; const pct = Math.round((filled / TOTAL) * 100); document.getElementById('progressFill').style.width = pct + '%'; document.getElementById('progressText').textContent = `Заполнено: ${filled} из ${TOTAL}`; } function updatePreview() { const container = document.getElementById('previewContent'); const labels = { slot_type: 'Тип слотов', multi_hour: 'Несколько часов подряд', calendar_view: 'Вид календаря', advance_booking: 'Бронирование вперёд', self_cancel: 'Самостоятельная отмена', price_per_hour: 'Цена за час', price_tiers: 'Тарифы', refund_policy: 'Возврат при отмене', invoice: 'Счёт-фактура', lock_system: 'Система замка', pin_length: 'Длина PIN', pin_delivery: 'Доставка PIN', booking_confirm: 'Подтверждение бронирования', reminder_before: 'Напоминание перед слотом', time_warning: 'Предупреждение о конце', admin_notify: 'Уведомления для вас', client_history: 'История клиентов', product_format: 'Формат приложения', language: 'Язык', logo: 'Логотип', design_style: 'Стиль дизайна', terms: 'Правила пользования', privacy: 'Политика конфиденциальности', }; let html = ''; Object.entries(labels).forEach(([name, label]) => { const checked = document.querySelector(`input[name="${name}"]:checked`); if (checked) { const spanText = checked.closest('label').querySelector('span')?.textContent || checked.value; html += `
Начните заполнять форму — здесь появится предпросмотр
'; } function escapeHtml(str) { return str.replace(/&/g,'&').replace(//g,'>'); } function updateURL() { const data = {}; document.querySelectorAll('input[type="radio"]:checked, input[type="checkbox"]:checked').forEach(el => { if (!data[el.name]) data[el.name] = []; data[el.name].push(el.value); }); const b64 = btoa(unescape(encodeURIComponent(JSON.stringify(data)))); const url = new URL(window.location.href); url.searchParams.set('d', b64); window.history.replaceState(null, '', url.toString()); } function formatTime() { const d = new Date(); return d.getHours().toString().padStart(2,'0') + ':' + d.getMinutes().toString().padStart(2,'0'); } function openModal() { document.getElementById('modalOverlay').classList.add('open'); document.body.style.overflow = 'hidden'; } function closeModal() { document.getElementById('modalOverlay').classList.remove('open'); document.body.style.overflow = ''; } function closeModalOutside(e) { if (e.target === document.getElementById('modalOverlay')) closeModal(); } function showFlash(msg) { const el = document.getElementById('flash'); el.textContent = msg; el.classList.add('show'); setTimeout(() => el.classList.remove('show'), 2500); }