fix(14-mobile-modal-fix): Modal rezerwacji działa na mobile/tablet
Sekcja Elementor zawierająca modal miała elementor-hidden-mobile/tablet, co powodowało display:none na rodzicu. Modal position:fixed wewnątrz ukrytego elementu miał zerowe wymiary. Fix: przeniesienie overlay do document.body w initRefs(). Plan Phase 13 (pakiety ochronne) utworzony, BLOCKED — czeka na klienta. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -86,6 +86,10 @@
|
||||
|
||||
function initRefs() {
|
||||
overlay = document.querySelector('[data-carei-modal]');
|
||||
// Move overlay to body so it's not trapped inside Elementor hidden sections on mobile/tablet
|
||||
if (overlay && overlay.parentElement !== document.body) {
|
||||
document.body.appendChild(overlay);
|
||||
}
|
||||
form = document.getElementById('carei-reservation-form');
|
||||
segmentSelect = document.getElementById('carei-segment');
|
||||
dateFrom = document.getElementById('carei-date-from');
|
||||
@@ -166,6 +170,7 @@
|
||||
initDateLabels();
|
||||
dataLoaded = true;
|
||||
}
|
||||
enforceDateMin();
|
||||
|
||||
// Pre-select segment from trigger attribute
|
||||
var presetSegment = triggerBtn && triggerBtn.getAttribute('segment');
|
||||
@@ -312,6 +317,65 @@
|
||||
function showExtras() { if (extrasWrapper) extrasWrapper.style.display = ''; }
|
||||
function hideExtras() { if (extrasWrapper) extrasWrapper.style.display = 'none'; }
|
||||
|
||||
// ─── Past Date Prevention ────────────────────────────────────
|
||||
|
||||
function getNowLocal() {
|
||||
var d = new Date();
|
||||
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + 'T' + pad(d.getHours()) + ':' + pad(d.getMinutes());
|
||||
}
|
||||
|
||||
var dateMinListenersBound = false;
|
||||
|
||||
function warnPastDate(input, msg) {
|
||||
var wrap = input.closest('.carei-form__date-wrap') || input.parentNode;
|
||||
var existing = wrap.querySelector('.carei-form__error-msg');
|
||||
if (existing) existing.remove();
|
||||
var span = document.createElement('span');
|
||||
span.className = 'carei-form__error-msg';
|
||||
span.textContent = msg;
|
||||
wrap.appendChild(span);
|
||||
input.classList.add('carei-form__field--error');
|
||||
input.value = '';
|
||||
updateDateEmpty(input);
|
||||
}
|
||||
|
||||
function clearDateError(input) {
|
||||
var wrap = input.closest('.carei-form__date-wrap') || input.parentNode;
|
||||
var existing = wrap.querySelector('.carei-form__error-msg');
|
||||
if (existing) existing.remove();
|
||||
input.classList.remove('carei-form__field--error');
|
||||
}
|
||||
|
||||
function checkPastAndWarn(input, label) {
|
||||
if (!input || !input.value) return;
|
||||
if (input.value < getNowLocal()) {
|
||||
warnPastDate(input, label + ' — data lub godzina już minęły');
|
||||
} else {
|
||||
clearDateError(input);
|
||||
}
|
||||
}
|
||||
|
||||
function enforceDateMin() {
|
||||
var now = getNowLocal();
|
||||
if (dateFrom) dateFrom.setAttribute('min', now);
|
||||
if (dateTo) dateTo.setAttribute('min', now);
|
||||
|
||||
if (!dateMinListenersBound) {
|
||||
if (dateFrom) {
|
||||
dateFrom.addEventListener('change', function () {
|
||||
checkPastAndWarn(dateFrom, 'Rozpoczęcie');
|
||||
if (dateTo && dateFrom.value) dateTo.setAttribute('min', dateFrom.value);
|
||||
});
|
||||
}
|
||||
if (dateTo) {
|
||||
dateTo.addEventListener('change', function () {
|
||||
checkPastAndWarn(dateTo, 'Zakończenie');
|
||||
});
|
||||
}
|
||||
dateMinListenersBound = true;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Date Labels ──────────────────────────────────────────────
|
||||
|
||||
function initDateLabels() {
|
||||
@@ -502,8 +566,8 @@
|
||||
if (!items || items.length === 0) return;
|
||||
items.forEach(function (item) {
|
||||
var id = item.id || item.code;
|
||||
var isSelected = !!selectedCountries[id];
|
||||
abroadResults.appendChild(buildCountryCard(item, isSelected));
|
||||
if (selectedCountries[id]) return; // already selected — show only in "added" section
|
||||
abroadResults.appendChild(buildCountryCard(item, false));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -595,12 +659,8 @@
|
||||
{ id: 'carei-pickup-branch', type: 'select', msg: 'Wybierz miejsce odbioru' },
|
||||
{ id: 'carei-firstname', type: 'input', msg: 'Podaj imię' },
|
||||
{ id: 'carei-lastname', type: 'input', msg: 'Podaj nazwisko' },
|
||||
{ id: 'carei-city', type: 'input', msg: 'Podaj miejscowość' },
|
||||
{ id: 'carei-zipcode', type: 'input', msg: 'Podaj kod pocztowy' },
|
||||
{ id: 'carei-street', type: 'input', msg: 'Podaj ulicę' },
|
||||
{ id: 'carei-email', type: 'email', msg: 'Podaj poprawny adres e-mail' },
|
||||
{ id: 'carei-phone', type: 'phone', msg: 'Podaj numer telefonu (min. 9 cyfr)' },
|
||||
{ id: 'carei-pesel', type: 'pesel', msg: 'Podaj poprawny PESEL (11 cyfr)' },
|
||||
{ id: 'carei-privacy', type: 'checkbox', msg: 'Wymagana zgoda na Politykę Prywatności' }
|
||||
];
|
||||
|
||||
@@ -623,6 +683,13 @@
|
||||
if (hasError) { valid = false; markFieldError(el, f.msg, f.type); }
|
||||
});
|
||||
|
||||
var now = new Date();
|
||||
if (dateFrom && dateFrom.value && new Date(dateFrom.value) < now) {
|
||||
valid = false; markFieldError(dateFrom, 'Data lub godzina rozpoczęcia już minęły', 'input');
|
||||
}
|
||||
if (dateTo && dateTo.value && new Date(dateTo.value) < now) {
|
||||
valid = false; markFieldError(dateTo, 'Data lub godzina zakończenia już minęły', 'input');
|
||||
}
|
||||
if (dateFrom && dateTo && dateFrom.value && dateTo.value) {
|
||||
if (new Date(dateTo.value) <= new Date(dateFrom.value)) {
|
||||
valid = false; markFieldError(dateTo, 'Data zakończenia musi być po dacie rozpoczęcia', 'input');
|
||||
@@ -711,12 +778,8 @@
|
||||
returnBranch: (sameReturnCheck && !sameReturnCheck.checked && returnSelect) ? returnSelect.value : '',
|
||||
firstName: val('carei-firstname'),
|
||||
lastName: val('carei-lastname'),
|
||||
city: val('carei-city'),
|
||||
zipCode: val('carei-zipcode'),
|
||||
street: val('carei-street'),
|
||||
email: val('carei-email'),
|
||||
phone: '+48' + phoneRaw,
|
||||
pesel: val('carei-pesel'),
|
||||
message: val('carei-message'),
|
||||
privacy: document.getElementById('carei-privacy') ? document.getElementById('carei-privacy').checked : false
|
||||
};
|
||||
@@ -736,8 +799,8 @@
|
||||
lastName: fd.lastName,
|
||||
name: fd.firstName + ' ' + fd.lastName,
|
||||
isCompany: false,
|
||||
address: { city: fd.city, zipCode: fd.zipCode, street: fd.street, homeNo: '-' },
|
||||
pesel: fd.pesel,
|
||||
address: { city: '-', zipCode: '00-000', street: '-', homeNo: '-' },
|
||||
pesel: '00000000000',
|
||||
email: fd.email,
|
||||
phoneMobile: fd.phone,
|
||||
paymentMethod: 'GOTÓWKA',
|
||||
@@ -974,13 +1037,13 @@
|
||||
returnLocation: { branchName: returnBranch, outOfBranch: 'N' },
|
||||
carParameters: { categoryName: fd.segment },
|
||||
priceListId: currentPriceListId,
|
||||
validTime: 30,
|
||||
validTime: 1440,
|
||||
priceItems: getSelectedExtrasForApi(),
|
||||
drivers: [{
|
||||
firstName: fd.firstName,
|
||||
lastName: fd.lastName,
|
||||
address: { city: fd.city, zipCode: fd.zipCode, street: fd.street },
|
||||
pesel: fd.pesel,
|
||||
address: { city: '-', zipCode: '00-000', street: '-' },
|
||||
pesel: '00000000000',
|
||||
phone: fd.phone,
|
||||
email: fd.email
|
||||
}],
|
||||
@@ -997,9 +1060,8 @@
|
||||
apiPost('booking', bookingData).then(function (res) {
|
||||
if (res && res.success && res.reservationId) {
|
||||
currentReservationId = res.reservationId;
|
||||
return apiPost('booking/confirm', { reservationId: res.reservationId }).then(function () {
|
||||
showSuccessView(res.reservationNo || res.reservationId);
|
||||
});
|
||||
showSuccessView(res.reservationNo || res.reservationId);
|
||||
return;
|
||||
}
|
||||
throw new Error(translateRejectReason(res.rejectReason) || 'Rezerwacja nie powiodła się');
|
||||
}).catch(function (err) {
|
||||
@@ -1033,7 +1095,7 @@
|
||||
// ─── Success View ─────────────────────────────────────────────
|
||||
|
||||
function showSuccessView(reservationNo) {
|
||||
if (successNumber) successNumber.textContent = 'Nr rezerwacji: ' + reservationNo;
|
||||
if (successNumber) successNumber.textContent = 'Nr zamówienia: ' + reservationNo;
|
||||
transitionStep(summaryOverlay, successView, function () {
|
||||
announce('Rezerwacja potwierdzona');
|
||||
var title = successView.querySelector('.carei-success__title');
|
||||
@@ -1119,6 +1181,22 @@
|
||||
|
||||
var searchMapData = null;
|
||||
|
||||
// Enforce min dates on search form (no error messages — compact UI)
|
||||
var now = getNowLocal();
|
||||
if (searchDateFrom) {
|
||||
searchDateFrom.setAttribute('min', now);
|
||||
searchDateFrom.addEventListener('change', function () {
|
||||
if (searchDateFrom.value && searchDateFrom.value < getNowLocal()) searchDateFrom.value = '';
|
||||
if (searchDateTo && searchDateFrom.value) searchDateTo.setAttribute('min', searchDateFrom.value);
|
||||
});
|
||||
}
|
||||
if (searchDateTo) {
|
||||
searchDateTo.setAttribute('min', now);
|
||||
searchDateTo.addEventListener('change', function () {
|
||||
if (searchDateTo.value && searchDateTo.value < getNowLocal()) searchDateTo.value = '';
|
||||
});
|
||||
}
|
||||
|
||||
// Ładowanie danych do mini formularza
|
||||
function loadSearchData() {
|
||||
Promise.all([
|
||||
|
||||
Reference in New Issue
Block a user