Wykrywanie imienia i nazwiska kelnera oraz info czy sesja dostala sie do aplikacji

This commit is contained in:
2026-05-28 20:46:35 +02:00
parent a72b5afcc7
commit d374723fd6
12 changed files with 467 additions and 30 deletions

View File

@@ -31,6 +31,8 @@ requireAdminAuth(true);
.chip.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.legend-list { margin: 0; padding-left: 18px; line-height: 1.6; color: #cbd5e1; }
.legend-list li { margin-bottom: 6px; }
.status-ok { color: #22c55e; font-weight: 700; }
.status-fail { color: #ef4444; font-weight: 700; }
@media (max-width: 900px) { .col-3,.col-4,.col-6,.col-8 { grid-column: span 12; } .top { flex-direction: column; align-items: flex-start; } }
</style>
</head>
@@ -98,8 +100,8 @@ requireAdminAuth(true);
<div class="card col-12">
<h3>Ostatnie otwarcia stron stolików</h3>
<table>
<thead><tr><th>Kiedy</th><th>Stolik</th><th>Strefa</th><th>Urządzenie</th><th>Przeglądarka</th><th>IP</th></tr></thead>
<tbody id="recentOpensBody"><tr><td colspan="6" class="muted">Ładowanie...</td></tr></tbody>
<thead><tr><th>Kiedy</th><th>Stolik</th><th>Strefa</th><th>Menu</th><th>Urządzenie</th><th>Przeglądarka</th><th>IP</th></tr></thead>
<tbody id="recentOpensBody"><tr><td colspan="7" class="muted">Ładowanie...</td></tr></tbody>
</table>
</div>
@@ -113,8 +115,8 @@ requireAdminAuth(true);
<tbody id="guestQueueSummaryBody"><tr><td colspan="4" class="muted">Ładowanie...</td></tr></tbody>
</table>
<table>
<thead><tr><th>ID</th><th>Kiedy</th><th>Stolik</th><th>Typ</th><th>Treść</th><th>Wysłane API</th><th>KDS gotowe</th></tr></thead>
<tbody id="guestQueueBody"><tr><td colspan="7" class="muted">Ładowanie...</td></tr></tbody>
<thead><tr><th>ID</th><th>Kiedy</th><th>Stolik</th><th>Kelner</th><th>Typ</th><th>Treść</th><th>Wysłane API</th><th>KDS gotowe</th></tr></thead>
<tbody id="guestQueueBody"><tr><td colspan="8" class="muted">Ładowanie...</td></tr></tbody>
</table>
</div>
@@ -127,6 +129,7 @@ requireAdminAuth(true);
<li><strong>Przywołania kelnera</strong> - ile razy gość poprosił o podejście obsługi.</li>
<li><strong>Top stoliki</strong> - które stoliki są najczęściej otwierane i używane.</li>
<li><strong>Lejek użycia</strong> - droga użytkownika: wejście -> start aplikacji -> menu -> rachunek.</li>
<li><strong>Kolumna Menu (✓/✗)</strong> - ✓ oznacza wejście do menu w tej sesji; ✗ oznacza brak wejścia do menu (w tym zatrzymanie na geo).</li>
</ul>
</div>
</div>
@@ -197,9 +200,17 @@ requireAdminAuth(true);
const when = dt && !Number.isNaN(dt.getTime()) ? dt.toLocaleString("pl-PL") : (r.created_at || "-");
const device = r.device_type || "-";
const browser = r.browser || "-";
return `<tr><td>${when}</td><td>${r.table_id || "-"}</td><td>${r.zone || "-"}</td><td>${device}</td><td>${browser}</td><td>${r.ip_address || "-"}</td></tr>`;
const enteredMenu = Number(r.entered_menu) === 1;
const reachedApp = Number(r.reached_app) === 1;
let menuCell = `<span class="status-fail" title="Zatrzymano na ekranie lokalizacji">✗</span>`;
if (enteredMenu) {
menuCell = `<span class="status-ok" title="Wszedł do menu">✓</span>`;
} else if (reachedApp) {
menuCell = `<span class="status-fail" title="Wszedł do aplikacji, ale nie otworzył menu">✗</span>`;
}
return `<tr><td>${when}</td><td>${r.table_id || "-"}</td><td>${r.zone || "-"}</td><td>${menuCell}</td><td>${device}</td><td>${browser}</td><td>${r.ip_address || "-"}</td></tr>`;
}).join("")
: `<tr><td colspan="6" class="muted">Brak danych</td></tr>`;
: `<tr><td colspan="7" class="muted">Brak danych</td></tr>`;
const queueSummary = data.guestQueueSummary || {};
document.getElementById("guestQueueSummaryBody").innerHTML = `
@@ -224,15 +235,19 @@ requireAdminAuth(true);
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
return `<tr><td>${row.id}</td><td>${when}</td><td>${row.table_id || "-"}</td><td>${typeLabel}</td><td>${messageText}</td><td>${apiSent}</td><td>${kdsDone}</td></tr>`;
const kelner = [row.otwierajacy_imie, row.otwierajacy_nazwisko]
.map(v => String(v || "").trim())
.filter(Boolean)
.join(" ") || "-";
return `<tr><td>${row.id}</td><td>${when}</td><td>${row.table_id || "-"}</td><td>${kelner}</td><td>${typeLabel}</td><td>${messageText}</td><td>${apiSent}</td><td>${kdsDone}</td></tr>`;
}).join("")
: `<tr><td colspan="7" class="muted">Brak danych</td></tr>`;
: `<tr><td colspan="8" class="muted">Brak danych</td></tr>`;
} catch (e) {
document.getElementById("topTablesBody").innerHTML = `<tr><td colspan="5" class="muted">Nie udało się załadować analityki.</td></tr>`;
document.getElementById("zonesBody").innerHTML = `<tr><td colspan="3" class="muted">Sprawdź połączenie/API.</td></tr>`;
document.getElementById("recentOpensBody").innerHTML = `<tr><td colspan="6" class="muted">Nie udało się pobrać ostatnich otwarć.</td></tr>`;
document.getElementById("recentOpensBody").innerHTML = `<tr><td colspan="7" class="muted">Nie udało się pobrać ostatnich otwarć.</td></tr>`;
document.getElementById("guestQueueSummaryBody").innerHTML = `<tr><td colspan="4" class="muted">Nie udało się pobrać podsumowania kolejki.</td></tr>`;
document.getElementById("guestQueueBody").innerHTML = `<tr><td colspan="7" class="muted">Nie udało się pobrać kolejki.</td></tr>`;
document.getElementById("guestQueueBody").innerHTML = `<tr><td colspan="8" class="muted">Nie udało się pobrać kolejki.</td></tr>`;
} finally {
isLoadingAnalytics = false;
}