This commit is contained in:
@@ -49,6 +49,15 @@ body {
|
||||
.nav-links a:hover { color: var(--color-primary); }
|
||||
|
||||
.nav-actions { display: flex; align-items: center; gap: 10px; }
|
||||
.profile-menu { position: relative; }
|
||||
.profile-menu__trigger { display: inline-flex; align-items: center; gap: 10px; padding: 6px 10px 6px 6px; border: 1px solid var(--color-border); border-radius: 999px; background: #fff; color: var(--color-text); cursor: pointer; font: inherit; }
|
||||
.profile-menu__trigger:hover { border-color: var(--color-primary); }
|
||||
.profile-menu__avatar { width: 34px; height: 34px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; background: var(--color-primary); color: var(--color-primary-contrast); font-weight: 700; }
|
||||
.profile-menu__name { font-weight: 600; }
|
||||
.profile-menu__dropdown { position: absolute; top: calc(100% + 10px); right: 0; min-width: 220px; padding: 10px; display: none; background: #fff; border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-card); }
|
||||
.profile-menu.is-open .profile-menu__dropdown { display: grid; gap: 4px; }
|
||||
.profile-menu__dropdown a { display: block; padding: 10px 12px; border-radius: 10px; font-weight: 600; color: var(--color-text); }
|
||||
.profile-menu__dropdown a:hover { background: #f8f4ec; color: var(--color-primary); }
|
||||
.menu-toggle { display: none; background: transparent; border: 1px solid var(--color-border); padding: 8px 10px; border-radius: var(--radius-sm); }
|
||||
.mobile-menu { display: none; padding: 12px 16px; border-top: 1px solid var(--color-border); background: #fff; }
|
||||
.mobile-menu a, .mobile-menu button { display: block; width: 100%; text-align: left; margin-bottom: 10px; }
|
||||
@@ -56,7 +65,8 @@ body {
|
||||
@media (max-width: 900px){
|
||||
.nav-links { display: none; }
|
||||
.menu-toggle { display: inline-flex; }
|
||||
.nav-actions .btn { display: none; }
|
||||
.nav-actions .btn,
|
||||
.profile-menu { display: none; }
|
||||
.mobile-menu.open { display: block; }
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const locationPreference = body.dataset.locationPreference || 'prompt';
|
||||
const header = document.querySelector('.site-header');
|
||||
const headerSentinel = document.getElementById('headerSentinel');
|
||||
const matomoConfigNode = document.getElementById('matomoConfig');
|
||||
const consentStateKey = 'pkt_cookie_consent';
|
||||
let matomoLoaded = false;
|
||||
|
||||
// Logo-Logik
|
||||
const pickLogo = (gender) => {
|
||||
@@ -41,6 +44,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
mobileMenu?.classList.toggle('open');
|
||||
});
|
||||
});
|
||||
const profileMenu = document.querySelector('[data-profile-menu]');
|
||||
const profileMenuTrigger = document.querySelector('[data-profile-menu-trigger]');
|
||||
profileMenuTrigger?.addEventListener('click', () => {
|
||||
const next = !profileMenu?.classList.contains('is-open');
|
||||
profileMenu?.classList.toggle('is-open', next);
|
||||
profileMenuTrigger.setAttribute('aria-expanded', next ? 'true' : 'false');
|
||||
});
|
||||
document.addEventListener('click', (event) => {
|
||||
if (!profileMenu || !profileMenuTrigger) return;
|
||||
if (profileMenu.contains(event.target)) return;
|
||||
profileMenu.classList.remove('is-open');
|
||||
profileMenuTrigger.setAttribute('aria-expanded', 'false');
|
||||
});
|
||||
|
||||
// Scroll zu Events
|
||||
const scrollBtn = document.getElementById('scrollToEvents');
|
||||
@@ -78,8 +94,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
quickGeo: document.getElementById('quickGeo'),
|
||||
eventsSection: document.getElementById('events'),
|
||||
locationPreferenceModal: document.getElementById('locationPreferenceModal'),
|
||||
consentBanner: document.getElementById('cookieConsentBanner'),
|
||||
consentModal: document.getElementById('cookieConsentModal'),
|
||||
consentAnalytics: document.getElementById('consentAnalytics'),
|
||||
consentExternalServices: document.getElementById('consentExternalServices'),
|
||||
};
|
||||
let effectiveLocationPreference = locationPreference;
|
||||
let consentState = null;
|
||||
|
||||
const fmtDate = (iso) => {
|
||||
const d = new Date(iso);
|
||||
@@ -88,6 +109,127 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
const now = () => new Date();
|
||||
|
||||
const deleteCookie = (name) => {
|
||||
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; SameSite=Lax`;
|
||||
};
|
||||
|
||||
const readConsent = () => {
|
||||
try {
|
||||
const raw = window.localStorage.getItem(consentStateKey);
|
||||
if (!raw) return null;
|
||||
const parsed = JSON.parse(raw);
|
||||
if (!parsed || typeof parsed !== 'object') return null;
|
||||
return {
|
||||
necessary: true,
|
||||
analytics: Boolean(parsed.analytics),
|
||||
external_services: Boolean(parsed.external_services),
|
||||
updatedAt: parsed.updatedAt || null,
|
||||
};
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const writeConsent = (nextState) => {
|
||||
consentState = {
|
||||
necessary: true,
|
||||
analytics: Boolean(nextState.analytics),
|
||||
external_services: Boolean(nextState.external_services),
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
try {
|
||||
window.localStorage.setItem(consentStateKey, JSON.stringify(consentState));
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
window.PKTConsent = window.PKTConsent || {};
|
||||
window.PKTConsent.get = () => consentState;
|
||||
window.PKTConsent.has = (category) => {
|
||||
if (category === 'necessary') return true;
|
||||
return Boolean(consentState?.[category]);
|
||||
};
|
||||
};
|
||||
|
||||
const closeConsentModal = () => {
|
||||
el.consentModal?.classList.remove('open');
|
||||
};
|
||||
|
||||
const openConsentModal = () => {
|
||||
if (el.consentAnalytics) el.consentAnalytics.checked = Boolean(consentState?.analytics);
|
||||
if (el.consentExternalServices) el.consentExternalServices.checked = Boolean(consentState?.external_services);
|
||||
el.consentModal?.classList.add('open');
|
||||
};
|
||||
|
||||
const deleteMatomoCookies = () => {
|
||||
['_pk_id', '_pk_ses', '_pk_ref', '_pk_cvar', 'mtm_consent', 'mtm_consent_removed'].forEach((prefix) => {
|
||||
deleteCookie(prefix);
|
||||
const hostParts = window.location.hostname.split('.');
|
||||
while (hostParts.length > 1) {
|
||||
document.cookie = `${prefix}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${hostParts.join('.')}; SameSite=Lax`;
|
||||
hostParts.shift();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const loadMatomo = () => {
|
||||
if (matomoLoaded || !matomoConfigNode || !consentState?.analytics) return;
|
||||
try {
|
||||
const cfg = JSON.parse(matomoConfigNode.textContent || '{}');
|
||||
if (!cfg.url || !cfg.siteId) return;
|
||||
const _paq = window._paq = window._paq || [];
|
||||
_paq.push(['setDomains', Array.isArray(cfg.domains) ? cfg.domains : []]);
|
||||
_paq.push(['trackPageView']);
|
||||
_paq.push(['enableLinkTracking']);
|
||||
_paq.push(['setTrackerUrl', cfg.url + 'matomo.php']);
|
||||
_paq.push(['setSiteId', cfg.siteId]);
|
||||
const script = document.createElement('script');
|
||||
script.async = true;
|
||||
script.src = cfg.url + 'matomo.js';
|
||||
document.head.appendChild(script);
|
||||
matomoLoaded = true;
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
};
|
||||
|
||||
const showConsentBannerIfNeeded = () => {
|
||||
if (!consentState && el.consentBanner) {
|
||||
el.consentBanner.removeAttribute('hidden');
|
||||
}
|
||||
};
|
||||
|
||||
const applyConsent = (nextState, options = {}) => {
|
||||
const previous = consentState;
|
||||
writeConsent(nextState);
|
||||
if (!consentState.external_services) {
|
||||
clearStoredLocation();
|
||||
}
|
||||
if (!consentState.analytics) {
|
||||
deleteMatomoCookies();
|
||||
} else {
|
||||
loadMatomo();
|
||||
}
|
||||
el.consentBanner?.setAttribute('hidden', 'hidden');
|
||||
closeConsentModal();
|
||||
|
||||
if (previous && options.reloadOnChange !== false) {
|
||||
const analyticsChanged = previous.analytics !== consentState.analytics;
|
||||
const externalChanged = previous.external_services !== consentState.external_services;
|
||||
if (analyticsChanged || externalChanged) {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const requireExternalServicesConsent = (message = 'Für diese Funktion werden externe Dienste benötigt.') => {
|
||||
if (consentState?.external_services) {
|
||||
return true;
|
||||
}
|
||||
alert(message);
|
||||
openConsentModal();
|
||||
return false;
|
||||
};
|
||||
|
||||
const setCookie = (name, value, days = 30) => {
|
||||
const expires = new Date(Date.now() + (days * 86400000)).toUTCString();
|
||||
document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/; SameSite=Lax`;
|
||||
@@ -142,7 +284,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
document.cookie = 'pkt_user_location=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; SameSite=Lax';
|
||||
deleteCookie('pkt_user_location');
|
||||
if (el.quickLat) el.quickLat.value = '';
|
||||
if (el.quickLng) el.quickLng.value = '';
|
||||
if (el.quickLoc) el.quickLoc.value = '';
|
||||
@@ -465,6 +607,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
renderSlider(null);
|
||||
return null;
|
||||
}
|
||||
if (!requireExternalServicesConsent('Für standortbezogene Treffen werden Standort- und Kartendienste erst nach deiner Einwilligung aktiviert.')) {
|
||||
renderSlider(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
const stored = applyStoredLocationToForm();
|
||||
if (stored && effectiveLocationPreference !== 'enabled' && sessionPreference !== 'session') {
|
||||
@@ -511,6 +657,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
};
|
||||
|
||||
el.quickGeo?.addEventListener('click', () => {
|
||||
if (!requireExternalServicesConsent('Für die Standortermittlung benötigen wir deine Einwilligung zu externen Diensten und Standortfunktionen.')) {
|
||||
return;
|
||||
}
|
||||
if (!navigator.geolocation) {
|
||||
alert('Geolocation wird nicht unterstützt.');
|
||||
return;
|
||||
@@ -554,6 +703,28 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
btn.addEventListener('click', () => el.modal?.classList.remove('open'));
|
||||
});
|
||||
el.modal?.addEventListener('click', (e) => { if (e.target === el.modal) el.modal.classList.remove('open'); });
|
||||
document.querySelectorAll('[data-consent-open]').forEach(btn => {
|
||||
btn.addEventListener('click', openConsentModal);
|
||||
});
|
||||
document.querySelectorAll('[data-consent-close]').forEach(btn => {
|
||||
btn.addEventListener('click', closeConsentModal);
|
||||
});
|
||||
document.querySelectorAll('[data-consent-necessary]').forEach(btn => {
|
||||
btn.addEventListener('click', () => applyConsent({ analytics: false, external_services: false }));
|
||||
});
|
||||
document.querySelector('[data-consent-accept-all]')?.addEventListener('click', () => {
|
||||
applyConsent({ analytics: true, external_services: true });
|
||||
});
|
||||
document.querySelector('[data-consent-save]')?.addEventListener('click', () => {
|
||||
applyConsent({
|
||||
analytics: Boolean(el.consentAnalytics?.checked),
|
||||
external_services: Boolean(el.consentExternalServices?.checked),
|
||||
});
|
||||
});
|
||||
el.consentModal?.addEventListener('click', (e) => {
|
||||
if (e.target === el.consentModal) closeConsentModal();
|
||||
});
|
||||
document.addEventListener('pkt:open-consent', openConsentModal);
|
||||
|
||||
document.querySelectorAll('[data-nav-events]').forEach(link => {
|
||||
link.addEventListener('click', async () => {
|
||||
@@ -563,6 +734,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
});
|
||||
|
||||
consentState = readConsent();
|
||||
if (consentState?.analytics) {
|
||||
loadMatomo();
|
||||
}
|
||||
showConsentBannerIfNeeded();
|
||||
|
||||
try {
|
||||
if (!isLoggedIn) {
|
||||
const guestPreference = window.localStorage.getItem('pkt_location_preference_guest');
|
||||
@@ -581,7 +758,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
renderSlider(initialLocation);
|
||||
renderThreadSlider();
|
||||
|
||||
if (effectiveLocationPreference === 'enabled' && window.location.pathname === '/') {
|
||||
if (effectiveLocationPreference === 'enabled' && window.location.pathname === '/' && consentState?.external_services) {
|
||||
ensureEventsLocation();
|
||||
} else if (window.location.hash === '#events' || window.location.hash === '#quicksearch') {
|
||||
ensureEventsLocation();
|
||||
|
||||
Reference in New Issue
Block a user