Трансфер

До фестиваля «Красный Шатёр» — с комфортом

Организованный трансфер из Калининграда до фестиваля и обратно. Не нужно искать парковку и идти с вещами по лесной дороге.

  • Автобус привозит прямо ко входу в зону регистрации
  • Фиксированная цена делится между всеми пассажирами
  • Спокойный отдых на фестивале — без мыслей о дороге обратно
  • Дорога — это уже начало фестиваля
Посмотреть рейсы
Фестиваль Красный Шатёр
от 350 ₽ за рейс

Расписание рейсов

При наборе 50 пассажиров стоимость составит всего 350 ₽ за рейс. Цена делится между всеми участниками.

И самое приятное…

Для многих участниц трансфер становится первой частью фестиваля.

Именно в дороге начинаются знакомства, появляются первые разговоры и ощущение, что вы уже стали частью большого женского круга.

Начало пути — уже магия
Бронирование и оплата

Забронировать место в трансфере

Выберите рейс, заполните анкету и оплатите — место будет закреплено за вами сразу после оплаты

Один билет трансфера = одно пассажирское место.
Для каждого человека оформляется отдельное место, включая детей любого возраста — перевозчик учитывает количество пассажиров, а не возраст. После клика «Забронировать и оплатить» место резервируется за вами на 10 минут.
Место зарезервировано. Осталось 10:00 на оплату.

Оплата картой · СБП · Apple/Google Pay через Tilda Payments

Нажимая кнопку, вы подтверждаете согласие с Политикой обработки персональных данных и даёте согласие на получение коммуникаций по вашей заявке.

Трансфер

До фестиваля «Красный Шатёр» — с комфортом

Организованный трансфер из Калининграда до фестиваля и обратно. Не нужно искать парковку и идти с вещами по лесной дороге.

  • Автобус привозит прямо ко входу в зону регистрации
  • Фиксированная цена делится между всеми пассажирами
  • Спокойный отдых на фестивале — без мыслей о дороге обратно
  • Дорога — это уже начало фестиваля
Посмотреть рейсы
Фестиваль Красный Шатёр
от 350 ₽ за рейс

Расписание рейсов

При наборе 50 пассажиров стоимость составит всего 350 ₽ за рейс. Цена делится между всеми участниками.

И самое приятное…

Для многих участниц трансфер становится первой частью фестиваля.

Именно в дороге начинаются знакомства, появляются первые разговоры и ощущение, что вы уже стали частью большого женского круга.

Начало пути — уже магия
Бронирование и оплата

Забронировать место в трансфере

Выберите рейс, заполните анкету и оплатите — место будет закреплено за вами сразу после оплаты

Один билет трансфера = одно пассажирское место.
Для каждого человека оформляется отдельное место, включая детей любого возраста — перевозчик учитывает количество пассажиров, а не возраст. После клика «Забронировать и оплатить» место резервируется за вами на 10 минут.
Место зарезервировано. Осталось 10:00 на оплату.

Оплата картой · СБП · Apple/Google Pay через Tilda Payments

Нажимая кнопку, вы подтверждаете согласие с Политикой обработки персональных данных и даёте согласие на получение коммуникаций по вашей заявке.

${dirLabel(t.dir)}
${isBack ? 'Старт' : 'Выезд'} ${t.depart}${t.arrive && t.arrive !== 'Калининград' ? ' · прибытие к ' + t.arrive + '' : ' · прибытие в Калининград'}
${isFull ? 'Мест нет' : (isReserved ? 'Резервируется…' : 'Мест есть')}
${isFull ? '—' : priceFor(t.booked) + ' ₽'}за место
`; return row; } function renderTrips() { listEl.innerHTML = ''; TRIPS.forEach(t => listEl.appendChild(buildRow(t))); } renderTrips(); // ===== form references ===== const select = document.getElementById('tfTrip'); const summaryEl = document.getElementById('tfSummary'); const summaryTitle = document.getElementById('tfSummaryTitle'); const summaryMeta = document.getElementById('tfSummaryMeta'); const summaryPrice = document.getElementById('tfSummaryPrice'); const changeBtn = document.getElementById('tfSummaryChange'); const tripDateField = document.getElementById('tfTripDate'); const tripTimeField = document.getElementById('tfTripTime'); const tripRouteField = document.getElementById('tfTripRoute'); const tripPriceField = document.getElementById('tfTripPrice'); const payBtn = document.getElementById('tfPayBtn'); const consentPD = document.getElementById('tfAgreePD'); const reserveTimerEl = document.getElementById('tfReserveTimer'); const timerCountEl = document.getElementById('tfTimerCount'); const paymentStatusField = document.getElementById('tfPaymentStatus'); const form = document.getElementById('tfTransferForm'); function rebuildSelect() { const current = select.value; select.innerHTML = ''; TRIPS.forEach(t => { const isReserved = !!t.reservedUntil && t.reservedUntil > Date.now(); if (t.total - t.booked <= 0 || isReserved) return; const isBack = t.dir === 'back'; const timeNote = isBack ? 'старт ' + t.depart : 'выезд ' + t.depart; const opt = document.createElement('option'); opt.value = t.id; opt.textContent = `${t.day} (${t.weekday}) · ${timeNote} · ${dirLabel(t.dir)} — ${priceFor(t.booked)} ₽`; select.appendChild(opt); }); if (current && TRIPS.some(t => t.id === current && t.total - t.booked > 0 && !(t.reservedUntil > Date.now()))) { select.value = current; } } rebuildSelect(); function updateSummary(tripId) { const trip = TRIPS.find(x => x.id === tripId); if (!trip) { summaryEl.classList.remove('tf-summary--show'); tripDateField.value = ''; tripTimeField.value = ''; tripRouteField.value = ''; tripPriceField.value = ''; syncPayBtn(); return; } const price = priceFor(trip.booked); const timeNote = trip.dir === 'back' ? 'Старт ' + trip.depart : 'Выезд ' + trip.depart; const arriveNote = trip.arrive && trip.arrive !== 'Калининград' ? 'прибытие к ' + trip.arrive : 'прибытие в Калининград'; summaryTitle.textContent = `${trip.day} (${trip.weekday}) · ${dirLabel(trip.dir)}`; summaryMeta.textContent = `${timeNote} · ${arriveNote}`; summaryPrice.textContent = price + ' ₽'; summaryEl.classList.add('tf-summary--show'); // Скрытые поля → CRM tripDateField.value = trip.day + ' (' + trip.weekday + ')'; tripTimeField.value = trip.depart; tripRouteField.value = dirLabel(trip.dir); tripPriceField.value = price; syncPayBtn(); } select.addEventListener('change', function() { updateSummary(this.value); }); changeBtn.addEventListener('click', function() { select.value = ''; updateSummary(''); select.focus(); }); // ===== pick from schedule -> scroll ===== document.addEventListener('click', function(e) { const btn = e.target.closest('.tf-pick'); if (!btn || btn.disabled) return; const tripId = btn.dataset.trip; if (tripId) { select.value = tripId; updateSummary(tripId); } const target = document.getElementById('tfFormSection'); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); setTimeout(() => { const nameField = document.getElementById('tfName'); if (nameField) nameField.focus({ preventScroll: true }); }, 600); } }); // ===== pay button gate ===== function syncPayBtn() { const hasTrip = !!select.value; const hasConsent = consentPD && consentPD.checked; payBtn.disabled = !(hasTrip && hasConsent); } if (consentPD) consentPD.addEventListener('change', syncPayBtn); // ===== reservation timer ===== let reserveInterval = null; let currentReservationTrip = null; function startReservation(tripId) { const trip = TRIPS.find(x => x.id === tripId); if (!trip) return; trip.reservedUntil = Date.now() + RESERVE_MS; currentReservationTrip = tripId; reserveTimerEl.classList.add('tf-reservetimer--show'); paymentStatusField.value = 'резервируется, ждём оплату'; rebuildSelect(); renderTrips(); if (reserveInterval) clearInterval(reserveInterval); reserveInterval = setInterval(() => { const left = trip.reservedUntil - Date.now(); if (left <= 0) { clearInterval(reserveInterval); reserveInterval = null; trip.reservedUntil = null; currentReservationTrip = null; reserveTimerEl.classList.remove('tf-reservetimer--show'); paymentStatusField.value = 'резерв истёк'; rebuildSelect(); renderTrips(); return; } const m = Math.floor(left / 60000); const s = Math.floor((left % 60000) / 1000); timerCountEl.textContent = String(m).padStart(2, '0') + ':' + String(s).padStart(2, '0'); }, 1000); } function clearReservation() { if (reserveInterval) { clearInterval(reserveInterval); reserveInterval = null; } if (currentReservationTrip) { const trip = TRIPS.find(x => x.id === currentReservationTrip); if (trip) trip.reservedUntil = null; } currentReservationTrip = null; reserveTimerEl.classList.remove('tf-reservetimer--show'); } // ===== Tilda Pay integration ===== function openTildaPay() { const trip = TRIPS.find(x => x.id === select.value); if (!trip) return; const amount = priceFor(trip.booked); if (window.tildaPay && typeof window.tildaPay.open === 'function') { window.tildaPay.open({ product: 'Трансфер «' + dirLabel(trip.dir) + '» — ' + trip.day + ' ' + trip.depart, amount: amount, currency: 'RUB', email: document.getElementById('tfEmail').value || '', phone: document.getElementById('tfPhone').value || '', name: document.getElementById('tfName').value || '', onSuccess: function() { onPaymentSuccess(); }, onFail: function() { paymentStatusField.value = 'ошибка оплаты'; }, onClose: function() {} }); } else { // Fallback: если Tilda Payments не подгрузился — отправляем как заявку paymentStatusField.value = 'офлайн-заявка'; submitAsLead(); } } function submitAsLead() { if (window.t_forms__initBtnClick) { window.t_forms__initBtnClick({ target: payBtn, srcElement: payBtn, preventDefault: function() {} }); } } function onPaymentSuccess() { const trip = TRIPS.find(x => x.id === currentReservationTrip) || TRIPS.find(x => x.id === select.value); if (trip) { trip.booked = Math.min(trip.total, trip.booked + 1); paymentStatusField.value = 'оплачено'; document.getElementById('tfSuccessTrip').textContent = trip.day + ' ' + trip.depart + ' · ' + dirLabel(trip.dir); clearReservation(); renderTrips(); rebuildSelect(); submitAsLead(); const sb = form.querySelector('.js-successbox'); if (sb) { sb.style.display = 'block'; sb.scrollIntoView({ behavior: 'smooth', block: 'center' }); } } } window.onReceiverSuccess = function() { /* места уже обновлены в onPaymentSuccess */ }; payBtn.addEventListener('click', function() { if (payBtn.disabled) return; const reqFields = form.querySelectorAll('[data-tilda-req="1"]'); let valid = true; reqFields.forEach(function(f) { if (f.type === 'checkbox' && !f.checked) { valid = false; const lbl = f.closest('.tf-consent__row'); if (lbl) lbl.style.outline = '1px solid var(--red)'; } else if (f.type !== 'checkbox' && !f.value.trim()) { valid = false; f.style.borderColor = 'var(--red)'; } }); if (!valid) return; if (!select.value) { select.style.borderColor = 'var(--red)'; return; } startReservation(select.value); openTildaPay(); }); form.addEventListener('input', function(e) { if (e.target.matches('input, textarea, select')) { e.target.style.borderColor = ''; const lbl = e.target.closest('.tf-consent__row'); if (lbl) lbl.style.outline = ''; } }); })();