Wykrywanie imienia i nazwiska kelnera oraz info czy sesja dostala sie do aplikacji
This commit is contained in:
@@ -135,11 +135,22 @@ requireAdminAuth(true);
|
||||
color: var(--accent);
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 15px;
|
||||
margin-bottom: 8px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.order-operator {
|
||||
color: var(--text-muted);
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.order-operator strong {
|
||||
color: #cbd5e1;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.order-items {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -226,6 +237,68 @@ requireAdminAuth(true);
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.guest-alerts {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.guest-alert {
|
||||
border-radius: 14px;
|
||||
padding: 16px 18px;
|
||||
border: 1px solid #334155;
|
||||
background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
|
||||
animation: slideIn 0.3s ease-out;
|
||||
}
|
||||
|
||||
.guest-alert-waiter {
|
||||
border-left: 5px solid var(--danger);
|
||||
box-shadow: 0 0 24px rgba(239, 68, 68, 0.15);
|
||||
}
|
||||
|
||||
.guest-alert-bill {
|
||||
border-left: 5px solid var(--warning);
|
||||
}
|
||||
|
||||
.guest-alert-title {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 800;
|
||||
margin-bottom: 6px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.4px;
|
||||
}
|
||||
|
||||
.guest-alert-waiter .guest-alert-title {
|
||||
color: #fca5a5;
|
||||
}
|
||||
|
||||
.guest-alert-bill .guest-alert-title {
|
||||
color: #fcd34d;
|
||||
}
|
||||
|
||||
.guest-alert-operator {
|
||||
font-size: 0.95rem;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.guest-alert-operator strong {
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
.guest-alert-msg {
|
||||
font-size: 0.9rem;
|
||||
color: #cbd5e1;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.guest-alert-time {
|
||||
margin-top: 8px;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -242,6 +315,8 @@ requireAdminAuth(true);
|
||||
<a href="logout.php" style="color:#cbd5e1; text-decoration:none; border:1px solid #334155; padding:8px 12px; border-radius:10px;">Wyloguj</a>
|
||||
</div>
|
||||
|
||||
<div id="guest-alerts" class="guest-alerts"></div>
|
||||
|
||||
<div id="kds-grid" class="kds-grid">
|
||||
<div id="loading">
|
||||
<div class="loader-spinner"></div>
|
||||
@@ -254,6 +329,74 @@ requireAdminAuth(true);
|
||||
const lastSyncEl = document.getElementById('last-sync');
|
||||
const dotEl = document.getElementById('connection-dot');
|
||||
let previousDataString = "";
|
||||
let previousAlertsString = "";
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value ?? "")
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">");
|
||||
}
|
||||
|
||||
function formatOtwierajacy(item) {
|
||||
const imie = (item.OtwierajacyImie || "").trim();
|
||||
const nazwisko = (item.OtwierajacyNazwisko || "").trim();
|
||||
const pelne = `${imie} ${nazwisko}`.trim();
|
||||
if (pelne) return pelne;
|
||||
return (item.OtwierajacyNick || "").trim();
|
||||
}
|
||||
|
||||
function formatQueueOperator(row) {
|
||||
const imie = (row.otwierajacy_imie || "").trim();
|
||||
const nazwisko = (row.otwierajacy_nazwisko || "").trim();
|
||||
return `${imie} ${nazwisko}`.trim();
|
||||
}
|
||||
|
||||
async function fetchGuestAlerts() {
|
||||
try {
|
||||
const response = await fetch("../../api/guest_action_queue.php?kds_secret=karczma_kuchnia");
|
||||
const result = await response.json();
|
||||
if (result.status !== "success") return;
|
||||
|
||||
const alertsString = JSON.stringify(result.data || []);
|
||||
if (alertsString !== previousAlertsString) {
|
||||
renderGuestAlerts(result.data || []);
|
||||
previousAlertsString = alertsString;
|
||||
}
|
||||
} catch {
|
||||
// best effort
|
||||
}
|
||||
}
|
||||
|
||||
function renderGuestAlerts(items) {
|
||||
const container = document.getElementById("guest-alerts");
|
||||
if (!items.length) {
|
||||
container.innerHTML = "";
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = items.map(row => {
|
||||
const isWaiter = row.message_type === "waiter_call";
|
||||
const typeLabel = isWaiter ? "Wezwanie kelnera" : "Prośba o rachunek";
|
||||
const operator = formatQueueOperator(row);
|
||||
const operatorHtml = operator
|
||||
? `<div class="guest-alert-operator">Kelner stolika: <strong>${escapeHtml(operator)}</strong></div>`
|
||||
: "";
|
||||
const dt = row.created_at ? new Date(String(row.created_at).replace(" ", "T")) : null;
|
||||
const when = dt && !Number.isNaN(dt.getTime())
|
||||
? dt.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
|
||||
: "";
|
||||
|
||||
return `
|
||||
<div class="guest-alert ${isWaiter ? "guest-alert-waiter" : "guest-alert-bill"}">
|
||||
<div class="guest-alert-title">${typeLabel} · STOLIK ${escapeHtml(row.table_id || "?")}</div>
|
||||
${operatorHtml}
|
||||
<div class="guest-alert-msg">${escapeHtml(row.message_text || "")}</div>
|
||||
<div class="guest-alert-time">${when}</div>
|
||||
</div>
|
||||
`;
|
||||
}).join("");
|
||||
}
|
||||
|
||||
async function fetchOrders() {
|
||||
try {
|
||||
@@ -303,6 +446,7 @@ requireAdminAuth(true);
|
||||
stolik: item.NazwaStolika || item.StolikID,
|
||||
stolikId: item.StolikID,
|
||||
time: item.DataDodania,
|
||||
otwierajacy: formatOtwierajacy(item),
|
||||
groups: {}
|
||||
};
|
||||
}
|
||||
@@ -338,6 +482,9 @@ requireAdminAuth(true);
|
||||
const timeStr = new Date(order.time).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
|
||||
const stolikLink = order.stolikId ? `<a href="../app.html?h=${order.stolikId}" target="_blank" style="color: var(--accent); text-decoration: underline;">STOLIK: ${order.stolik}</a>` : `STOLIK: ${order.stolik}`;
|
||||
const stolikText = order.stolik ? stolikLink : 'BRAK STOLIKA';
|
||||
const operatorHtml = order.otwierajacy
|
||||
? `<div class="order-operator">Kelner: <strong>${order.otwierajacy}</strong></div>`
|
||||
: '';
|
||||
|
||||
let itemsHtml = '';
|
||||
|
||||
@@ -375,6 +522,7 @@ requireAdminAuth(true);
|
||||
<div class="order-time">${timeStr}</div>
|
||||
</div>
|
||||
<div class="order-table">${stolikText}</div>
|
||||
${operatorHtml}
|
||||
<div class="order-items">
|
||||
${itemsHtml}
|
||||
</div>
|
||||
@@ -384,11 +532,11 @@ requireAdminAuth(true);
|
||||
});
|
||||
}
|
||||
|
||||
// Pierwsze pobranie
|
||||
fetchOrders();
|
||||
|
||||
// Pętla odświeżania co 3 sekundy
|
||||
fetchGuestAlerts();
|
||||
|
||||
setInterval(fetchOrders, 3000);
|
||||
setInterval(fetchGuestAlerts, 3000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user