{% sw_extends "@Storefront/storefront/base.html.twig" %}
{% block base_main %}
{{ parent() }}
{# Ein modales Fenster zum Zurücksetzen der Lieferoptionen #}
<div class="modal" id="resetDeliveryOptionsModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<div class="deliverySelectorModal">
<img src="{{ asset('/assets/DALL·E 2023-11-21 13.37.49 - Ausrufebrot.svg', 'theme') }}"
alt="Lieferart zurücksetzen Bild" id="reset-delivery-options-spinner">
<div class="deliverySelectorModalContent">
<div class="deliverySelectorModalHeadline">{{ "brandstetter.desiredDeliveryResetDescription"|trans|sw_sanitize }}</div>
<button class="deliverySelectorButton" type="button"
data-dismiss="modal">{{ "brandstetter.desiredDeliveryResetCancel"|trans|sw_sanitize }}</button>
<button class="deliverySelectorButton" type="submit"
id="deliverySelectorReset">{{ "brandstetter.desiredDeliveryReset"|trans|sw_sanitize }}</button>
</div>
</div>
</div>
</div>
</div>
</div>
{# Hier wird der DeliverySelector angezeigt #}
<div class="deliverySelector" id="deliverySelector">
{% sw_include '@DreiwmBrandstetterPlugin/storefront/component/brandstetter/delivery-selector/loading-spinner.html.twig' %}
<div class="deliverySelectorContent" id="deliverySelectorContent">
{% if app.request.cookies.get('CustomerHasSelectedDelivery') == 'true' and app.request.cookies.get('CustomerHasSelectedDelivery')!= 'false' and app.request.cookies.get('customerSelectedDeliveryId') %}
{% sw_include '@DreiwmBrandstetterPlugin/storefront/component/brandstetter/delivery-selector/user-has-selected-delivery.html.twig' %}
{% else %}
{% sw_include '@DreiwmBrandstetterPlugin/storefront/component/brandstetter/delivery-selector/user-has-not-selected-delivery.html.twig' %}
{% endif %}
</div>
</div>
<script>
(function () {
'use strict';
// ===== Helpers =====
const WRAP_ID = 'delivery-selector-wrapper';
const SPIN_ID = 'delivery-selector-spinner';
function readCookies() {
return document.cookie.split('; ').reduce((acc, c) => {
const i = c.indexOf('=');
if (i > -1) acc[decodeURIComponent(c.slice(0, i))] = decodeURIComponent(c.slice(i + 1));
return acc;
}, {});
}
function hasSelectedDeliveryCookie() {
const c = readCookies();
const v = (c['CustomerHasSelectedDelivery'] || '').toLowerCase();
return v === 'true' || v === '1' || v === 'yes' || !!c['customerSelectedDeliveryId'];
}
// Großes "nicht gewählt"-Widget zuverlässig erkennen (beide Varianten + Fallback-Klasse)
function domShowsNotSelected() {
const camel = document.getElementById('deliverySelectorContent');
return !!(
document.getElementById('delivery-selector-content') ||
(camel && camel.querySelector && camel.querySelector('#delivery-selector-content')) ||
document.querySelector('.delivery-selector-content')
);
}
function isBackForward(evt) {
const nav = (performance.getEntriesByType && performance.getEntriesByType('navigation')[0]) || null;
return (evt && evt.persisted === true) || (nav && nav.type === 'back_forward');
}
function isPDS() {
return document.body.classList.contains('is-ctl-product') || !!document.querySelector('.product-detail');
}
function isListing() {
const b = document.body.classList;
return b.contains('is-ctl-navigation') || b.contains('is-ctl-search') || !!document.querySelector('.cms-element-product-listing');
}
function restoreDeliverySelectorUI() {
const wrap = document.getElementById(WRAP_ID);
const spin = document.getElementById(SPIN_ID);
if (wrap) wrap.style.visibility = 'visible';
if (spin) spin.style.display = 'none';
}
// Cookies/URL-Helpers (auch global verfügbar)
function getCookie(name) {
const m = document.cookie.match(new RegExp('(?:^|; )' + name.replace(/([.$?*|{}()[\]\\/+^])/g, '\\$1') + '=([^;]*)'));
return m ? decodeURIComponent(m[1]) : undefined;
}
function setCookie(name, value) {
const date = new Date();
date.setTime(date.getTime() + (24 * 60 * 60 * 1000));
document.cookie = name + '=' + (value || '') + '; expires=' + date.toUTCString() + '; path=/; SameSite=None; Secure';
}
function deleteCookie(name) {
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
}
function updateURLParameter(url, param, val) {
const [base, query = ''] = url.split('?');
const parts = query ? query.split('&').filter(p => p.split('=')[0] !== param) : [];
parts.push(param + '=' + encodeURIComponent(val));
return base + '?' + parts.join('&');
}
window.updateURLParameter = updateURLParameter;
window.setCookie = setCookie;
window.deleteCookie = deleteCookie;
// ===== Positions & Drag =====
function updatePositions() {
const positions = JSON.parse(localStorage.getItem('positions') || '{}');
document.querySelectorAll('.deliverySelector').forEach(el => {
const pos = positions[el.id];
if (pos) {
let newLeft = (parseFloat(pos.left) * window.innerWidth) / 100;
let newTop = (parseFloat(pos.top) * window.innerHeight) / 100;
newLeft = Math.min(window.innerWidth - el.clientWidth, Math.max(0, newLeft));
newTop = Math.min(window.innerHeight - el.clientHeight, Math.max(0, newTop));
el.style.left = newLeft + 'px';
el.style.top = newTop + 'px';
}
});
}
window.addEventListener('resize', updatePositions);
document.addEventListener('DOMContentLoaded', function () {
updatePositions();
const positions = JSON.parse(localStorage.getItem('positions') || '{}');
const els = document.querySelectorAll('.deliverySelector');
els.forEach(el => {
const pos = positions[el.id];
if (pos) {
el.style.left = (parseFloat(pos.left) * window.innerWidth / 100) + 'px';
el.style.top = (parseFloat(pos.top) * window.innerHeight / 100) + 'px';
} else {
const elementWidth = 350, elementHeight = 420;
el.style.left = (window.innerWidth - elementWidth) + 'px';
el.style.top = (window.innerHeight - elementHeight) + 'px';
}
});
els.forEach(el => {
let isDragging = false, startX = 0, startY = 0, initialLeft = 0, initialTop = 0;
el.addEventListener('mousedown', ev => {
isDragging = true;
startX = ev.clientX; startY = ev.clientY;
initialLeft = parseFloat(el.style.left) || 0;
initialTop = parseFloat(el.style.top) || 0;
});
document.addEventListener('mousemove', ev => {
if (!isDragging) return;
let newLeft = initialLeft + (ev.clientX - startX);
let newTop = initialTop + (ev.clientY - startY);
newLeft = Math.min(window.innerWidth - el.clientWidth, Math.max(0, newLeft));
newTop = Math.min(window.innerHeight - el.clientHeight, Math.max(0, newTop));
el.style.left = newLeft + 'px';
el.style.top = newTop + 'px';
});
document.addEventListener('mouseup', () => {
if (!isDragging) return;
isDragging = false;
positions[el.id] = {
left: (100 * (parseFloat(el.style.left) / window.innerWidth)) + '%',
top: (100 * (parseFloat(el.style.top) / window.innerHeight)) + '%'
};
localStorage.setItem('positions', JSON.stringify(positions));
});
});
// "Lieferart zurücksetzen"
const resetBtn = document.getElementById('deliverySelectorReset');
if (resetBtn) {
resetBtn.addEventListener('click', function () {
const spinner = document.getElementById('reset-delivery-options-spinner');
if (spinner) spinner.style.animation = 'spin 1s linear infinite';
const xhr = new XMLHttpRequest();
xhr.open('POST', '/resetCustomerDeliveryChoice', true);
xhr.setRequestHeader('Content-type', 'application/json; charset=UTF-8');
xhr.onload = function () {
if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
const content = document.getElementById('deliverySelectorContent');
if (content) content.innerHTML = xhr.responseText;
setCookie('CustomerHasSelectedDelivery', 'false');
setCookie('customerSelectedDeliveryId', '');
setCookie('customerSelectedDate', '');
}
location.reload();
};
xhr.send(JSON.stringify({ date: 'inputValue' }));
});
}
});
// ===== Auto-Add nach Overlay-Flow =====
window.addEventListener('load', function () {
// Back-Reload-Flag für diese URL bei normalem Load zurücksetzen (neuer Zyklus)
const backKey = 'backReloadedOnce:' + location.pathname + location.search;
sessionStorage.removeItem(backKey);
if (sessionStorage.getItem('detailAutoAdd') !== '1') return;
sessionStorage.removeItem('detailAutoAdd');
// (1) Shopware-Buy-Form (häufigster Fall)
let form = document.querySelector('form.buy-widget[data-add-to-cart]');
// (2) Fallback: generischer Add-to-Cart Endpoint
if (!form) form = document.querySelector('form[action*="/checkout/line-item/add"]');
if (form) {
form.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
return;
}
// (3) Fallback: Button klicken
let btn = document.querySelector('form.buy-widget button.btn-buy, button.btn-buy, button[name="add-to-cart"]');
if (btn) {
btn.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }));
return;
}
console.warn('Auto-Add: Kein Buy-Form/-Button gefunden.');
});
// ===== Nur bei Zurück/Vorwärts: Reload, wenn DOM ≠ Cookies =====
function scheduleBackFix(trigger) {
if (!(isPDS() || isListing())) return;
const key = 'backReloadedOnce:' + location.pathname + location.search;
const already = sessionStorage.getItem(key) === '1';
function needReloadNow() {
return hasSelectedDeliveryCookie() && domShowsNotSelected();
}
function doReload() {
if (already) return;
sessionStorage.setItem(key, '1'); // Loop verhindern
location.reload(); // EIN Reload; Verlauf bleibt korrekt
}
// 1) Sofort prüfen
if (needReloadNow()) { doReload(); return; }
// 2) Kurze Nachchecks (DOM/BFCACHE Timing)
const delays = [0, 120, 350, 900];
let i = 0;
(function again(){
if (needReloadNow()) { doReload(); return; }
if (i < delays.length) setTimeout(() => { i++; again(); }, delays[i]);
})();
// 3) DOM-Mutationen kurz beobachten
const obs = new MutationObserver(() => {
if (needReloadNow()) { obs.disconnect(); doReload(); }
});
obs.observe(document.documentElement, { childList: true, subtree: true });
setTimeout(() => obs.disconnect(), 1500);
}
// Back/Forward & Normal-Show unterscheiden
window.addEventListener('pageshow', function (e) {
if (isBackForward(e)) {
// Nur bei Back/Forward: Auto-Flags aufräumen & ggf. Back-Fix starten
sessionStorage.removeItem('autoAddProductName');
sessionStorage.removeItem('autoClickOnReload');
sessionStorage.removeItem('detailAutoAdd');
scheduleBackFix('pageshow');
} else {
// Normaler Load: pfadbezogenes Back-Flag löschen (neuer Zyklus)
const backKey = 'backReloadedOnce:' + location.pathname + location.search;
sessionStorage.removeItem(backKey);
}
restoreDeliverySelectorUI();
});
window.addEventListener('popstate', () => scheduleBackFix('popstate'));
// Fallback: wenn Tab wieder sichtbar wird
document.addEventListener('visibilitychange', function () {
if (document.visibilityState === 'visible') restoreDeliverySelectorUI();
});
// ===== Optional: Listing-Filter p=1 setzen =====
window.setfilter = function (name, value) {
setCookie(name, value);
const isListingPage = ({{ page.cmsPage.type|json_encode()|raw }}) === 'product_list';
if (isListingPage) {
location.href = updateURLParameter(window.location.href, 'p', 1);
}
};
})();
</script>
{% endblock %}
{# Der Scroll-up-Button soll nur im Footer erscheinen #}
{% block base_scroll_up %}
{% endblock %}
{% block base_pseudo_modal %}
{# Muss in ein include sein und kein sw_include, da sonst Shopware die Original-Datei auch lädt und das
Pseudo-Modal leine Blöcke zum Überschreiben hat für BFSG #}
{% include "@DreiwmBrandstetterPlugin/storefront/component/pseudo-modal.html.twig" %}
{% endblock %}