diff --git a/.htaccess b/.htaccess
new file mode 100644
index 0000000..313fc43
--- /dev/null
+++ b/.htaccess
@@ -0,0 +1,5 @@
+# Gdy ten plik leży w public_html/biesiada.menu/ (nad katalogiem app/)
+
+ RewriteEngine On
+ RewriteRule ^app/public/app\.html$ app/public/app.php [L,QSA]
+
diff --git a/api/geo_bypass.php b/api/geo_bypass.php
new file mode 100644
index 0000000..f2132eb
--- /dev/null
+++ b/api/geo_bypass.php
@@ -0,0 +1,22 @@
+ 'error',
+ 'message' => 'Method not allowed',
+ ], JSON_UNESCAPED_UNICODE);
+ exit;
+}
+
+$clientIp = getRequestClientIp();
+$bypass = isGeoBypassTrustedIp($clientIp);
+
+echo json_encode([
+ 'status' => 'success',
+ 'bypassGeo' => $bypass,
+ 'clientIp' => $clientIp,
+], JSON_UNESCAPED_UNICODE);
diff --git a/api/request_ip.php b/api/request_ip.php
new file mode 100644
index 0000000..d76f5a6
--- /dev/null
+++ b/api/request_ip.php
@@ -0,0 +1,94 @@
+ 32) {
+ return false;
+ }
+
+ $ipLong = ip2long($ip);
+ $subnetLong = ip2long($subnet);
+ if ($ipLong === false || $subnetLong === false) {
+ return false;
+ }
+
+ $mask = $bits === 0 ? 0 : (-1 << (32 - $bits)) & 0xFFFFFFFF;
+
+ return ($ipLong & $mask) === ($subnetLong & $mask);
+}
+
+function isGeoBypassTrustedIp(string $ip): bool
+{
+ $ip = normalizeClientIp($ip);
+ if ($ip === '') {
+ return false;
+ }
+
+ if (in_array($ip, getGeoBypassTrustedIps(), true)) {
+ return true;
+ }
+
+ if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
+ foreach (getGeoBypassTrustedCidrs() as $cidr) {
+ if (ipv4InCidr($ip, $cidr)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
diff --git a/api/waiter_feed.php b/api/waiter_feed.php
new file mode 100644
index 0000000..f2b4650
--- /dev/null
+++ b/api/waiter_feed.php
@@ -0,0 +1,77 @@
+ 'error',
+ 'message' => 'Method not allowed',
+ ], JSON_UNESCAPED_UNICODE);
+ exit;
+}
+
+try {
+ $pdo = getAnalyticsPdo();
+ $stmt = $pdo->query("
+ SELECT
+ id,
+ table_id,
+ message_type,
+ message_text,
+ otwierajacy_imie,
+ otwierajacy_nazwisko,
+ status_kds,
+ api_sent,
+ created_at,
+ updated_at
+ FROM guest_action_queue
+ WHERE DATE(created_at) = CURDATE()
+ ORDER BY created_at DESC
+ LIMIT 500
+ ");
+ $rows = $stmt->fetchAll();
+
+ $pending = 0;
+ $waiterCalls = 0;
+ $billRequests = 0;
+
+ foreach ($rows as &$row) {
+ $row['id'] = (int) $row['id'];
+ $row['status_kds'] = (int) $row['status_kds'];
+ $row['api_sent'] = (int) $row['api_sent'];
+ $row['message_text'] = normalizeQueueMessageText((string) ($row['message_text'] ?? ''));
+
+ if ($row['status_kds'] === 0) {
+ $pending++;
+ }
+ if ($row['message_type'] === 'waiter_call') {
+ $waiterCalls++;
+ } elseif ($row['message_type'] === 'bill_request') {
+ $billRequests++;
+ }
+ }
+ unset($row);
+
+ echo json_encode([
+ 'status' => 'success',
+ 'date' => date('Y-m-d'),
+ 'count' => count($rows),
+ 'summary' => [
+ 'pending' => $pending,
+ 'waiter_calls' => $waiterCalls,
+ 'bill_requests' => $billRequests,
+ ],
+ 'polled_at' => date('Y-m-d H:i:s'),
+ 'poll_interval_seconds' => 15,
+ 'data' => $rows,
+ ], JSON_UNESCAPED_UNICODE);
+} catch (Throwable $e) {
+ http_response_code(500);
+ echo json_encode([
+ 'status' => 'error',
+ 'message' => 'Waiter feed fetch failed',
+ ], JSON_UNESCAPED_UNICODE);
+}
diff --git a/app/.htaccess b/app/.htaccess
new file mode 100644
index 0000000..cbd8e41
--- /dev/null
+++ b/app/.htaccess
@@ -0,0 +1,5 @@
+# Gdy document root wskazuje na katalog app/ (URL: /public/app.html)
+
+ RewriteEngine On
+ RewriteRule ^public/app\.html$ public/app.php [L,QSA]
+
diff --git a/index.php b/index.php
index 7b07512..87e4de1 100644
--- a/index.php
+++ b/index.php
@@ -74,6 +74,9 @@
🍳 Ekran KDS (Kuchnia)
+
+ 🛎️ Panel Kelnera (wezwania)
+
📱 Aplikacja dla Gościa (Poprosi o Hash)
diff --git a/public/.htaccess b/public/.htaccess
new file mode 100644
index 0000000..54d65a7
--- /dev/null
+++ b/public/.htaccess
@@ -0,0 +1,17 @@
+# Aplikacja gościa: świeży HTML/PHP (w app.php dynamiczne ?v= z filemtime)
+
+
+ Header set Cache-Control "no-store, no-cache, must-revalidate, max-age=0"
+ Header set Pragma "no-cache"
+ Header set Expires "0"
+
+
+
+# Nie serwuj app.html zamiast reguły rewrite / app.php
+Options -MultiViews
+
+# QR: app.html → app.php (gdy mod_rewrite działa; inaczej app.html robi redirect w JS)
+
+ RewriteEngine On
+ RewriteRule ^app\.html$ app.php [L,QSA]
+
diff --git a/public/app.html b/public/app.html
index 000f363..ac2b0cf 100644
--- a/public/app.html
+++ b/public/app.html
@@ -1,340 +1,24 @@
-
+
-
-
-
- Karczma Biesiada – Twoje Zamówienie
-
-
-
-
-
-
+
+
+
+
+
+ Karczma Biesiada – przekierowanie
+
+
-
-
-
-
-
Karczma Biesiada
-
Łączenie z kuchnią...
-
-
-
-
-
📍
-
-
Prywatność i Lokalizacja
-
- Aby zapewnić bezpieczeństwo Twojego zamówienia, musimy upewnić się, że znajdujesz się na terenie
- restauracji. Prosimy o udzielenie zgody na dostęp do lokalizacji w przeglądarce.
-
-
Udziel zgody / Sprawdź
-
- Status zamówienia, kelner i rachunek wymagają potwierdzenia, że jesteś w restauracji.
-
-
-
-
-
-
-
- Karczma Biesiada
- Wybierz stolik
-
-
-
-
-
-
-
-
-
-
-
-
- Sprawdzamy co pysznego się przygotowuje...
-
-
-
-
- Twoje zamówione dania
-
-
📖
-
Jeśli właśnie złożyłeś zamówienie, daj nam chwilkę na jego
- przetworzenie.
-
Przeglądaj menu
-
-
-
-
-
- Twoje poprzednie zamówienia
- To są pozycje z innych wizyt, które były widoczne na tym telefonie po zeskanowaniu
- kodów QR. Jeśli kiedyś byłeś w restauracji bez skanowania kodu, tych pozycji tu nie będzie 🙂
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 🍽️
- Zamówienie
-
-
-
- 🛎️
- Kelner
-
-
- 💳
- Rachunek
-
-
-
-
-
-
-
🛎️
-
- Przywołać obsługę?
-
- Kelner otrzyma natychmiastowe powiadomienie na swoim panelu i podejdzie do Twojego stolika najszybciej jak to
- możliwe.
-
-
- Tak,
- poproś kelnera
- Anuluj
-
-
-
-
-
-
-
-
-
-
-
-
×
-
-
-
-
-
-
-
-
-
-
-
-
-
- ⏳ Pobieranie rachunków...
-
-
-
Mamy kilka otwartych
- rachunków na tym stoliku. Który chcesz opłacić?
-
-
-
-
-
-
-
Podsumowanie rachunku:
-
-
-
-
- Do zapłaty:
- 0.00 PLN
-
-
- Wróć
- Poproś rachunek
-
-
-
-
-
-
Wybierz preferowaną formę
- płatności:
-
-
- 💳
- Karta
-
-
- 💵
- Gotówka
-
-
-
Wróć do
- podsumowania
-
-
-
-
-
Jakiego dokumentu
- potrzebujesz?
-
-
- 🧾
- Paragon
-
-
- 📄
- Faktura
-
-
-
Wróć
-
-
-
-
-
Wprowadź NIP firmy,
- abyśmy mogli automatycznie pobrać dane.
-
- Numer NIP
-
-
-
- Wróć
- Pobierz z GUS
-
-
-
-
-
-
Czy poniższe dane do
- faktury są prawidłowe?
-
-
-
-
-
Tak, poproszę fakturę!
-
- Zmień NIP
- Popraw ręcznie
-
-
-
-
-
-
-
-
-
- ✓ Wysłano!
-
-
-
+
+ Przekierowanie do aplikacji…
+
+ Kliknij tutaj, jeśli nic się nie dzieje
+
-
-