Essensbestellung

Lade…

Lade Daten…

`); w.document.close(); } function shareWhatsApp() { const s = state.currentSession; const p = state.currentProvider; let msg = `🍕 *Essensbestellung*\n\n📋 ${s?.name || 'Session'}\n🏪 ${p?.name || ''}\n`; if (s?.deadline) msg += `⏰ bis ${new Date(s.deadline).toLocaleString('de-DE')}\n`; msg += `\n👉 ${generateShareLink()}`; window.open('https://wa.me/?text=' + encodeURIComponent(msg), '_blank'); } /* ============================== Render ================================== */ function render() { const app = el('app'); let html = ''; if (state.view === 'login') html = loginViewHTML(); else if (state.view === 'admin' && state.currentUser) html = adminViewHTML(); else html = orderViewHTML(); app.innerHTML = html; lucide.createIcons(); attachAutocomplete(); updateTimer(); // Admin: Menü-Caches der Anbieter nachladen (für Badges + Bearbeitung). // WICHTIG: ausserhalb von render() – kein render() im Callback, sonst Render-Loop! if (state.view === 'admin' && state.adminTab === 'menu') { setTimeout(async () => { const targets = state.providers.filter(p => !state.menuCache[String(p.id)]); await Promise.all(targets.map(async p => { try { const r = await fetch(`api.php?action=get-menu&providerId=${encodeURIComponent(p.id)}`); const json = await r.json(); if (json.success && json.data?.items) state.menuCache[String(p.id)] = json.data; } catch (e) { /* still */ } })); // Nur das Status-Badge aktualisieren – NIEMALS render(), das würde // offene Eingaben im Menü-Tab zerstören (der Original-Bug) updateMenuStatus(); }, 0); } } /* ============================== Init ==================================== */ window.addEventListener('DOMContentLoaded', async () => { // Dark mode if (localStorage.getItem('pizza_dark') === '1') applyDark(true); el('btn-darkmode').addEventListener('click', () => applyDark(!document.documentElement.classList.contains('dark'))); // Eingeloggten Benutzer wiederherstellen try { const saved = JSON.parse(localStorage.getItem('pizza_user') || 'null'); if (saved) { // Session serverseitig prüfen (ping benötigt keinen Login, aber ein Login-Check geht via load) state.currentUser = saved; } } catch (e) {} // Session-ID aus URL + Einladungs-Link (?invite=CODE&u=NAME) const params = new URLSearchParams(location.search); if (params.get('session')) state.sessionId = params.get('session'); if (params.get('invite')) { state.inviteMode = true; state.inviteCode = params.get('invite') || ''; state.inviteUser = params.get('u') || ''; state.view = 'login'; history.replaceState({}, '', location.pathname); // Code aus der URL entfernen } const fy = document.getElementById('footer-year'); if (fy) fy.textContent = String(new Date().getFullYear()); // PWA if ('serviceWorker' in navigator) { navigator.serviceWorker.register('sw.js').catch(() => {}); } let deferredPrompt = null; window.addEventListener('beforeinstallprompt', (e) => { e.preventDefault(); deferredPrompt = e; el('btn-install').style.display = ''; }); el('btn-install').addEventListener('click', async () => { if (!deferredPrompt) return; deferredPrompt.prompt(); await deferredPrompt.userChoice; deferredPrompt = null; el('btn-install').style.display = 'none'; }); el('btn-admin').addEventListener('click', () => { if (state.currentUser) { state.view = 'admin'; render(); } else setView('login'); }); // Daten laden await loadData(); await refreshMenuIfPresent(); render(); // Timer + Auto-Refresh (mit Guard gegen Doppel-Init) if (!window.__pizzaTimers) { window.__pizzaTimers = true; setInterval(updateTimer, 1000); // Auto-Refresh nur wenn nichts fokussiert ist setInterval(() => { const ae = document.activeElement; const typing = ae && ['INPUT', 'TEXTAREA', 'SELECT'].includes(ae.tagName); if (!typing && !state.editingOrder && !el('modal-overlay')) loadData(true); }, 10000); } });