import { endpoints, loaderMinMs } from "./config.js"; import { runPendingProtectedAction, updateNavAccessState } from "./access.js"; import { refreshGuestPendingActions, startGuestPendingPoll, } from "./queue.js"; import { getAppAccessLevel, getHashParam, getPendingProtectedAction, getTableParam, setTableParam, } from "./state.js"; const loadingScreen = document.getElementById("loadingScreen"); const loaderMsg = document.getElementById("loaderMsg"); const tableLabel = document.getElementById("tableLabel"); const prepStatus = document.getElementById("prepStatus"); const progressBar = document.getElementById("progressBar"); const statusMeta = document.getElementById("statusMeta"); const itemsList = document.getElementById("itemsList"); const emptyState = document.getElementById("emptyState"); const metaFooter = document.getElementById("metaFooter"); const statusIcon = document.getElementById("statusIcon"); const historyKey = "stolik2_global_history"; const historySection = document.getElementById("historySection"); const historyList = document.getElementById("historyList"); const SIX_MONTHS_MS = 180 * 24 * 60 * 60 * 1000; const LOADER_MIN_MS = loaderMinMs; const loadStartTime = Date.now(); const msgs = ["Rozgrzewamy piece...", "Szef kuchni sprawdza składniki...", "Łączenie z sercem restauracji...", "Prawie gotowe..."]; let msgIdx = 0; const msgInterval = setInterval(() => { msgIdx = (msgIdx + 1) % msgs.length; if (loaderMsg) loaderMsg.textContent = msgs[msgIdx]; }, 4000); // Initial State if (getTableParam()) { const tableParam = getTableParam(); tableLabel.textContent = tableParam.toUpperCase().startsWith("STOLIK") ? tableParam : `Stolik ${tableParam}`; } /** Storage key must follow current hash (fallback: table), not a frozen empty tableParam at init. */ export function getOrderStorageKey() { const key = (getHashParam() || getTableParam() || "unknown").toLowerCase(); return `stolik2_state_${key}`; } export function hideLoader() { const elapsed = Date.now() - loadStartTime; const remaining = Math.max(0, LOADER_MIN_MS - elapsed); setTimeout(() => { loadingScreen.classList.add("hidden"); clearInterval(msgInterval); const bottomNav = document.getElementById("bottomNav"); if (bottomNav) { bottomNav.style.display = ""; } updateNavAccessState(); if (getPendingProtectedAction() && getAppAccessLevel() === "full") { runPendingProtectedAction(); } }, remaining); } export async function resolveTableLabel() { const hashParam = getHashParam(); if (!hashParam) return; try { const response = await fetch(`${endpoints.kds}?h=${encodeURIComponent(hashParam)}`); const result = await response.json(); if (result.status === "success" && result.tableName && result.tableName !== "") { tableLabel.textContent = result.tableName.toUpperCase().startsWith("STOLIK") ? result.tableName : `Stolik ${result.tableName}`; setTableParam(result.tableName); } } catch { // best effort } } export function updateUI(bills) { // Hide loader after minimum display time hideLoader(); const allArticles = bills.flatMap((b) => (Array.isArray(b?.Articles) ? b.Articles : [])); const items = mergeWithPersistedItems(allArticles); renderGlobalHistory(); if (items.length === 0) { showEmptyState(); return; } renderItems(items); updateStatus(bills, items); } function showEmptyState() { const title = document.getElementById("ordersTitle"); if (title) title.classList.add("hidden"); emptyState.classList.remove("hidden"); itemsList.innerHTML = ""; prepStatus.textContent = "Brak aktywnych zamówień"; statusIcon.textContent = "🍃"; progressBar.style.width = "0%"; statusMeta.textContent = "Zapraszamy do sprawdzenia naszego menu."; // Historia może istnieć nawet gdy brak bieżących pozycji renderGlobalHistory(); } function normalizeArticleName(rawName) { const name = String(rawName || "Pozycja"); // Usuwa gramatury typu: "300G", "250 G", "500/200/150G". const withoutWeight = name.replace( /\b\d+(?:[.,]\d+)?(?:\s*\/\s*\d+(?:[.,]\d+)?)*\s*[gG]\b/g, "" ); return withoutWeight .replace(/\s{2,}/g, " ") .replace(/\s+([,.;:!?])/g, "$1") .trim() || "Pozycja"; } function loadPersistedItems() { try { const raw = localStorage.getItem(getOrderStorageKey()); if (!raw) return []; const parsed = JSON.parse(raw); return Array.isArray(parsed) ? parsed : []; } catch { return []; } } function savePersistedItems(items) { try { localStorage.setItem(getOrderStorageKey(), JSON.stringify(items)); } catch { // brak miejsca/tryb prywatny } } function loadGlobalHistory() { try { const raw = localStorage.getItem(historyKey); if (!raw) return []; const parsed = JSON.parse(raw); return Array.isArray(parsed) ? parsed : []; } catch { return []; } } function saveGlobalHistory(entries) { const now = Date.now(); const cleaned = entries .filter((e) => e && e.name && Number.isFinite(e.archivedAt)) .filter((e) => now - e.archivedAt <= SIX_MONTHS_MS); try { localStorage.setItem(historyKey, JSON.stringify(cleaned)); } catch { // ignore storage errors } } function addItemsToGlobalHistory(items, sourceTable) { if (!items.length) return; const now = Date.now(); const existing = loadGlobalHistory(); // zapobiegamy dokładnym duplikatom (ta sama nazwa + qty + stół blisko czasu) const dedupWindowMs = 2 * 60 * 1000; const toAdd = items .filter((item) => { return !existing.some( (h) => h.name === item.name && Number(h.qty) === Number(item.qty) && String(h.sourceTable || "") === String(sourceTable || "") && Math.abs((h.archivedAt || 0) - now) <= dedupWindowMs ); }) .map((item) => ({ name: item.name, qty: item.qty, sourceTable: sourceTable || "?", archivedAt: now, })); if (!toAdd.length) return; saveGlobalHistory([...existing, ...toAdd]); } export function renderGlobalHistory() { const now = Date.now(); const history = loadGlobalHistory() .filter((e) => now - (e.archivedAt || 0) <= SIX_MONTHS_MS) .sort((a, b) => (b.archivedAt || 0) - (a.archivedAt || 0)); saveGlobalHistory(history); if (!history.length) { historySection.classList.add("hidden"); historyList.innerHTML = ""; return; } historySection.classList.remove("hidden"); historyList.innerHTML = ""; history.forEach((entry) => { const dt = new Date(entry.archivedAt || Date.now()); const div = document.createElement("div"); div.className = "item-card archived ready"; div.innerHTML = `