feat: add second questionnaire with clarifying questions

This commit is contained in:
Anton
2026-05-12 21:29:45 +03:00
parent 9f25c4c049
commit 03facb5db8
2 changed files with 378 additions and 0 deletions
+270
View File
@@ -0,0 +1,270 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; form-action https://formspree.io; script-src 'self'; style-src 'self'; img-src 'self' data:; connect-src https://formspree.io">
<title>Sunset Pass — Уточняющий опросник</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Шапка компании -->
<div class="company-header">
<img src="logo.jpg" alt="Kot Kanagrilli Oy" class="company-logo">
<div class="company-info">
<div class="company-name">Kot Kanagrilli Oy</div>
<a href="mailto:kotkanagrilli@gmail.com" class="company-email">kotkanagrilli@gmail.com</a>
</div>
</div>
<!-- Тулбар -->
<div class="toolbar">
<div class="toolbar-left">
<span class="toolbar-title">Saarijärven koirapuisto — Уточняющий опросник</span>
<span class="save-status" id="saveStatus"></span>
</div>
<div class="toolbar-right">
<button class="toolbar-btn" id="btnSave" title="Сохранить"><span class="btn-icon">💾</span><span class="btn-text"> Сохранить</span></button>
</div>
</div>
<!-- Flash сообщение -->
<div class="flash" id="flash"></div>
<!-- Основной макет -->
<div class="app-layout">
<div class="form-column">
<header>
<div class="progress-bar">
<div class="progress-fill" id="progressFill"></div>
</div>
<p class="progress-text" id="progressText">Заполнено: 0 из 16</p>
</header>
<form id="questionnaireForm" action="https://formspree.io/f/xrejjoav" method="POST">
<input type="hidden" name="_replyto" id="_replyto">
<input type="hidden" name="sender_time" id="sender_time">
<input type="hidden" name="sender_timezone" id="sender_timezone">
<input type="hidden" name="anton_time" id="anton_time">
<input type="hidden" name="questionnaire_number" value="2">
<!-- О воротах -->
<section class="section" data-section-id="gates">
<div class="section-header">
<h2>О воротах</h2>
</div>
<p style="font-size:0.88rem;color:#888;margin-bottom:16px;">Вы указали: <em>оборудования нет, нужно закупить с нуля.</em></p>
<div class="question" data-index="1">
<label for="gate_type">8а. Какой тип ворот на входе в парк?</label>
<textarea id="gate_type" name="gate_type" placeholder="Например: калитка / распашные / раздвижные"></textarea>
</div>
<div class="question" data-index="2">
<label for="gate_electricity">8б. Есть ли электричество рядом с воротами?</label>
<textarea id="gate_electricity" name="gate_electricity" placeholder="Например: да, розетка есть / нет, нужен аккумулятор"></textarea>
</div>
<div class="question" data-index="3">
<label for="gate_internet">8в. Достигает ли WiFi или мобильный интернет до ворот?</label>
<textarea id="gate_internet" name="gate_internet" placeholder="Например: да, WiFi есть / есть мобильная сеть 4G"></textarea>
</div>
<div class="question" data-index="4">
<label for="gate_camera">8г. Нужна ли камера видеонаблюдения у входа?</label>
<textarea id="gate_camera" name="gate_camera" placeholder="Например: да / нет / возможно позже"></textarea>
</div>
</section>
<!-- Об оплате -->
<section class="section" data-section-id="payment">
<div class="section-header">
<h2>Об оплате</h2>
</div>
<p style="font-size:0.88rem;color:#888;margin-bottom:16px;">Вы указали: <em>онлайн.</em></p>
<div class="question" data-index="5">
<label for="payment_provider">5а. Какой платёжный сервис предпочитаете?</label>
<textarea id="payment_provider" name="payment_provider" placeholder="Например: Paytrail (финский стандарт, поддерживает все банки) / Stripe / другой"></textarea>
</div>
<div class="question" data-index="6">
<label for="price_per_hour">5б. Сколько стоит один час аренды парка?</label>
<textarea id="price_per_hour" name="price_per_hour" placeholder="Например: 15€ за час"></textarea>
</div>
<div class="question" data-index="7">
<label for="price_tiers">5в. Будут ли разные тарифы?</label>
<textarea id="price_tiers" name="price_tiers" placeholder="Например: будни дешевле / выходные дороже / ночной тариф / один тариф для всех"></textarea>
</div>
<div class="question" data-index="8">
<label for="invoice">5г. Нужен ли счёт-фактура (lasku) для корпоративных клиентов?</label>
<textarea id="invoice" name="invoice" placeholder="Например: да / нет / не знаю пока"></textarea>
</div>
</section>
<!-- О бронировании -->
<section class="section" data-section-id="booking">
<div class="section-header">
<h2>О бронировании</h2>
</div>
<p style="font-size:0.88rem;color:#888;margin-bottom:16px;">Вы указали: <em>минимум 1 час, максимум 1 день.</em></p>
<div class="question" data-index="9">
<label for="closing_time">3а. Ворота закрываются автоматически в 23:00 или клиент может бронировать до конца суток?</label>
<textarea id="closing_time" name="closing_time" placeholder="Например: последний слот должен заканчиваться в 23:00 / можно до полуночи"></textarea>
</div>
<div class="question" data-index="10">
<label for="advance_booking">3б. Как далеко вперёд можно бронировать?</label>
<textarea id="advance_booking" name="advance_booking" placeholder="Например: максимум 30 дней / 2 месяца / без ограничений"></textarea>
</div>
</section>
<!-- О PIN-коде -->
<section class="section" data-section-id="pin">
<div class="section-header">
<h2>О PIN-коде и уведомлениях</h2>
</div>
<p style="font-size:0.88rem;color:#888;margin-bottom:16px;">Вы указали: <em>система генерирует PIN автоматически после оплаты.</em></p>
<div class="question" data-index="11">
<label for="pin_delivery">9а. Как клиент получает PIN — по email или в мобильном приложении?</label>
<textarea id="pin_delivery" name="pin_delivery" placeholder="Например: по email / в приложении / SMS"></textarea>
</div>
<div class="question" data-index="12">
<label for="time_warning">9б. Нужно ли уведомление клиенту когда время заканчивается?</label>
<textarea id="time_warning" name="time_warning" placeholder="Например: да, за 15 минут / да, за 30 минут / нет"></textarea>
</div>
<div class="question" data-index="13">
<label for="park_signal">9в. Будет ли сигнал на территории парка когда время вышло?</label>
<textarea id="park_signal" name="park_signal" placeholder="Например: да, лампочка / звуковой сигнал / нет, только уведомление в телефоне"></textarea>
</div>
</section>
<!-- Об управлении -->
<section class="section" data-section-id="admin">
<div class="section-header">
<h2>Об управлении бронированиями</h2>
</div>
<div class="question" data-index="14">
<label for="admin_view">10а. Как вы хотите видеть список бронирований?</label>
<textarea id="admin_view" name="admin_view" placeholder="Например: достаточно письма на email / нужна отдельная панель управления / оба варианта"></textarea>
</div>
<div class="question" data-index="15">
<label for="block_dates">10б. Нужна ли возможность заблокировать определённые дни?</label>
<textarea id="block_dates" name="block_dates" placeholder="Например: да, для техработ и отпуска / нет"></textarea>
</div>
<div class="question" data-index="16">
<label for="support_phone">10в. Если PIN не сработает — есть ли телефон поддержки, который мы укажем на сайте?</label>
<textarea id="support_phone" name="support_phone" placeholder="Например: да, мой номер +358 XX XXX XXXX / нет, только email"></textarea>
</div>
</section>
<!-- Юридическое -->
<section class="section" data-section-id="legal">
<div class="section-header">
<h2>Юридическое</h2>
</div>
<p style="font-size:0.88rem;color:#888;margin-bottom:16px;">В Финляндии по закону ЕС (GDPR) сайт обязан иметь политику конфиденциальности.</p>
<div class="question">
<label for="legal_terms">13а. Вы составите текст правил пользования парком самостоятельно или нам подготовить шаблон?</label>
<textarea id="legal_terms" name="legal_terms" placeholder="Например: подготовьте шаблон, я дополню / составлю сам / что это вообще такое?"></textarea>
</div>
</section>
<!-- О дизайне -->
<section class="section" data-section-id="design">
<div class="section-header">
<h2>О дизайне</h2>
</div>
<p style="font-size:0.88rem;color:#888;margin-bottom:16px;">Вы указали: <em>название Saarijärven koirapuisto, логотипа пока нет.</em></p>
<div class="question">
<label for="logo">14а. Логотип нужен? Если да — вы найдёте дизайнера или нам создать простой вариант?</label>
<textarea id="logo" name="logo" placeholder="Например: да, сделайте простой / найду дизайнера сам / логотип не нужен"></textarea>
</div>
<div class="question">
<label for="design_style">14б. Есть ли пожелания по цветам или стилю сайта?</label>
<textarea id="design_style" name="design_style" placeholder="Например: природные цвета, зелёный / современный минимализм / нет предпочтений"></textarea>
</div>
</section>
<!-- О формате продукта -->
<section class="section" data-section-id="product">
<div class="section-header">
<h2>О формате продукта</h2>
</div>
<p style="font-size:0.88rem;color:#888;margin-bottom:16px;">Мы можем реализовать проект в нескольких вариантах:</p>
<div style="background:#f8fffe;border:1.5px solid #c8e6c9;border-radius:10px;padding:16px 20px;margin-bottom:12px;">
<strong>Вариант 1 — Простой сайт</strong> <em style="color:#888;">(быстро, дёшево)</em><br>
<span style="font-size:0.9rem;">Сайт на финском: календарь слотов, онлайн-оплата, PIN по email. Работает на любом телефоне через браузер.</span>
</div>
<div style="background:#f0faf4;border:2px solid #2d6a4f;border-radius:10px;padding:16px 20px;margin-bottom:12px;">
<strong>Вариант 2 — Продвинутый сайт</strong> <em style="color:#2d6a4f;">(рекомендуем)</em><br>
<span style="font-size:0.9rem;">То же + SMS-уведомления, напоминания перед концом слота, панель управления для вас (блокировка дат, просмотр бронирований, статистика).</span>
</div>
<div style="background:#fff8f0;border:1.5px solid #ffe0b2;border-radius:10px;padding:16px 20px;margin-bottom:20px;">
<strong>Вариант 3 — Сайт + мобильное приложение</strong> <em style="color:#888;">(максимум)</em><br>
<span style="font-size:0.9rem;">То же + приложение для iOS и Android. PIN приходит в приложение, уведомления через приложение. Самый удобный вариант для клиентов.</span>
</div>
<div class="question">
<label for="product_choice">16а. Какой вариант вам ближе?</label>
<textarea id="product_choice" name="product_choice" placeholder="Например: вариант 2 / вариант 3 / хочу обсудить на звонке / не знаю пока"></textarea>
</div>
</section>
<!-- Контактные данные -->
<section class="section" data-section-id="contacts">
<div class="section-header">
<h2>Ваши контактные данные</h2>
</div>
<div class="question">
<label for="client_name">Имя</label>
<input type="text" id="client_name" name="client_name" required placeholder="Ваше имя" value="Sirpa Lehtinen">
</div>
<div class="question">
<label for="client_email">Email</label>
<input type="email" id="client_email" name="client_email" required placeholder="ваш@email.com" value="sirpulik@gmail.com">
</div>
<div class="question">
<label for="client_phone">Телефон (необязательно)</label>
<input type="tel" id="client_phone" name="client_phone" placeholder="+358 XX XXX XXXX">
</div>
</section>
<button type="submit" id="submitBtn">Отправить ответы</button>
<p class="submit-note">После отправки мы свяжемся с вами в течение 1-2 рабочих дней.</p>
</form>
</div>
<!-- Панель предпросмотра -->
<div class="preview-column">
<div class="preview-panel">
<div class="preview-header">Предпросмотр</div>
<div class="preview-a4" id="previewContent">
<p class="preview-empty">Начните заполнять форму — здесь появится предпросмотр</p>
</div>
</div>
</div>
</div>
<script src="script2.js"></script>
</body>
</html>
+108
View File
@@ -0,0 +1,108 @@
// ─── Поля прогресса ───────────────────────────────────────────────────────────
const TRACKED_FIELDS = [
'gate_type','gate_electricity','gate_internet','gate_camera',
'payment_provider','price_per_hour','price_tiers','invoice',
'closing_time','advance_booking',
'pin_delivery','time_warning','park_signal',
'admin_view','block_dates','support_phone',
'product_choice'
];
// ─── Инициализация ────────────────────────────────────────────────────────────
document.addEventListener('DOMContentLoaded', function () {
updateProgress();
updatePreview();
document.getElementById('client_email').addEventListener('input', function () {
document.getElementById('_replyto').value = this.value;
});
document.getElementById('_replyto').value = document.getElementById('client_email').value;
document.getElementById('questionnaireForm').addEventListener('input', function () {
updateProgress();
updatePreview();
});
document.getElementById('questionnaireForm').addEventListener('submit', function () {
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);
document.getElementById('btnSave').addEventListener('click', function () {
showFlash('Сохранено!');
});
});
// ─── Прогресс ─────────────────────────────────────────────────────────────────
function updateProgress() {
let filled = 0;
TRACKED_FIELDS.forEach(name => {
const el = document.getElementById(name);
if (el && el.value.trim()) filled++;
});
const total = TRACKED_FIELDS.length;
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 sections = document.querySelectorAll('.section');
let html = '';
sections.forEach(section => {
const title = section.querySelector('h2');
const questions = section.querySelectorAll('.question');
let sectionHtml = '';
questions.forEach(q => {
const input = q.querySelector('textarea, input[type="text"], input[type="email"], input[type="tel"]');
const label = q.querySelector('label');
if (!input || !label) return;
const val = input.value.trim();
if (val) {
sectionHtml += `<div class="preview-item">
<div class="preview-item-label">${label.textContent.trim()}</div>
<div class="preview-item-value">${escapeHtml(val)}</div>
</div>`;
}
});
if (sectionHtml && title) {
html += `<div class="preview-section">
<div class="preview-section-title">${title.textContent.trim()}</div>
${sectionHtml}
</div>`;
}
});
container.innerHTML = html || '<p class="preview-empty">Начните заполнять форму — здесь появится предпросмотр</p>';
}
// ─── Flash ────────────────────────────────────────────────────────────────────
function showFlash(msg) {
const el = document.getElementById('flash');
el.textContent = msg;
el.classList.add('show');
setTimeout(() => el.classList.remove('show'), 2500);
}
function escapeHtml(str) {
return str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}