Wykrywanie i blokada po lokalizacji
This commit is contained in:
@@ -62,6 +62,44 @@ body {
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
#geoScreen {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 150;
|
||||
background: var(--bg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40px;
|
||||
text-align: center;
|
||||
transition: opacity 0.5s ease, visibility 0.5s;
|
||||
}
|
||||
|
||||
.geo-icon {
|
||||
font-size: 80px;
|
||||
margin-bottom: 16px;
|
||||
animation: bounce 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-15px); }
|
||||
}
|
||||
|
||||
.geo-text h2 {
|
||||
font-family: 'Playfair Display', serif;
|
||||
margin: 0 0 12px;
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.geo-msg {
|
||||
color: var(--text-muted);
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* --- MAIN LAYOUT --- */
|
||||
.container {
|
||||
max-width: 500px;
|
||||
|
||||
@@ -112,8 +112,8 @@ function showGreeting(name, firstVisitTime) {
|
||||
}
|
||||
}
|
||||
|
||||
// Call init
|
||||
initUserProfile();
|
||||
// Call init is now delayed until geolocation succeeds
|
||||
// initUserProfile();
|
||||
|
||||
// UI Elements
|
||||
const loadingScreen = document.getElementById("loadingScreen");
|
||||
@@ -196,7 +196,7 @@ function detectTableCandidates(bill) {
|
||||
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ń";
|
||||
@@ -322,7 +322,7 @@ function renderGlobalHistory() {
|
||||
});
|
||||
}
|
||||
|
||||
window.clearGlobalHistory = function(e) {
|
||||
window.clearGlobalHistory = function (e) {
|
||||
if (e) e.preventDefault();
|
||||
if (confirm("Czy na pewno chcesz usunąć historię swoich poprzednich zamówień?")) {
|
||||
localStorage.removeItem(historyKey);
|
||||
@@ -509,8 +509,8 @@ async function fetchOrders() {
|
||||
}
|
||||
}
|
||||
|
||||
fetchOrders();
|
||||
setInterval(fetchOrders, 10000);
|
||||
// fetchOrders();
|
||||
// setInterval(fetchOrders, 10000);
|
||||
|
||||
// --- CALL WAITER LOGIC ---
|
||||
let billState = { payment: '', doc: '', nip: '', company: null };
|
||||
@@ -690,14 +690,14 @@ window.switchTab = function (tabName) {
|
||||
};
|
||||
|
||||
// --- MENU LOGIC ---
|
||||
window.filterMenu = function() {
|
||||
window.filterMenu = function () {
|
||||
const query = document.getElementById('menuSearchInput').value.toLowerCase();
|
||||
const categories = document.querySelectorAll('.rm-category');
|
||||
|
||||
|
||||
categories.forEach(category => {
|
||||
let hasVisibleItems = false;
|
||||
const items = category.querySelectorAll('.rmc-position');
|
||||
|
||||
|
||||
items.forEach(item => {
|
||||
const title = item.querySelector('.rmc-title h4').textContent.toLowerCase();
|
||||
if (title.includes(query)) {
|
||||
@@ -707,7 +707,7 @@ window.filterMenu = function() {
|
||||
item.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (hasVisibleItems) {
|
||||
category.style.display = '';
|
||||
} else {
|
||||
@@ -716,15 +716,15 @@ window.filterMenu = function() {
|
||||
});
|
||||
};
|
||||
|
||||
window.showCategory = function(categoryId) {
|
||||
window.showCategory = function (categoryId) {
|
||||
document.querySelectorAll('.menu-categories-nav a').forEach(a => a.classList.remove('active'));
|
||||
|
||||
|
||||
const clickedLink = document.querySelector(`.menu-categories-nav a[data-category-badge="${categoryId}"]`);
|
||||
if (clickedLink) {
|
||||
clickedLink.classList.add('active');
|
||||
clickedLink.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
|
||||
}
|
||||
|
||||
|
||||
const categories = document.querySelectorAll('.rm-category');
|
||||
categories.forEach(cat => {
|
||||
if (categoryId === 0) {
|
||||
@@ -839,9 +839,98 @@ window.confirmInvoice = function () {
|
||||
showToast("Dziękujemy! Prośba o fakturę została wysłana.");
|
||||
};
|
||||
|
||||
// Fallback: If no data after 25s, show empty state anyway
|
||||
setTimeout(() => {
|
||||
if (!loadingScreen.classList.contains("hidden")) {
|
||||
updateUI([]);
|
||||
// --- GEOLOCATION LOGIC ---
|
||||
const RESTAURANT_LAT = 50.5624963;
|
||||
const RESTAURANT_LNG = 22.0608059;
|
||||
const MAX_DISTANCE_METERS = 200;
|
||||
|
||||
function haversineDistance(lat1, lon1, lat2, lon2) {
|
||||
const R = 6371e3;
|
||||
const p1 = lat1 * Math.PI / 180;
|
||||
const p2 = lat2 * Math.PI / 180;
|
||||
const dp = (lat2 - lat1) * Math.PI / 180;
|
||||
const dl = (lon2 - lon1) * Math.PI / 180;
|
||||
|
||||
const a = Math.sin(dp / 2) * Math.sin(dp / 2) +
|
||||
Math.cos(p1) * Math.cos(p2) *
|
||||
Math.sin(dl / 2) * Math.sin(dl / 2);
|
||||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
return R * c;
|
||||
}
|
||||
|
||||
function startApp() {
|
||||
document.getElementById("geoScreen").classList.add("hidden");
|
||||
document.getElementById("loadingScreen").classList.remove("hidden");
|
||||
|
||||
initUserProfile();
|
||||
fetchOrders();
|
||||
if (!window.ordersInterval) {
|
||||
window.ordersInterval = setInterval(fetchOrders, 10000);
|
||||
}
|
||||
}, 25000);
|
||||
|
||||
// Fallback: If no data after 25s, show empty state anyway
|
||||
setTimeout(() => {
|
||||
if (!document.getElementById("loadingScreen").classList.contains("hidden")) {
|
||||
updateUI([]);
|
||||
}
|
||||
}, 25000);
|
||||
}
|
||||
|
||||
window.initGeolocation = function () {
|
||||
const geoScreen = document.getElementById("geoScreen");
|
||||
const loadingScreen = document.getElementById("loadingScreen");
|
||||
const geoMsg = document.getElementById("geoMsg");
|
||||
|
||||
if (window.location.protocol === 'http:' && (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1')) {
|
||||
console.warn("Bypassing geolocation on local HTTP environment.");
|
||||
startApp();
|
||||
return;
|
||||
}
|
||||
|
||||
loadingScreen.classList.add("hidden");
|
||||
geoScreen.classList.remove("hidden");
|
||||
|
||||
if (!navigator.geolocation) {
|
||||
geoMsg.innerHTML = "Twoja przeglądarka nie wspiera geolokalizacji. Aplikacja wymaga nowszej przeglądarki.";
|
||||
return;
|
||||
}
|
||||
|
||||
geoMsg.innerHTML = "Pobieranie lokalizacji...";
|
||||
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(position) => {
|
||||
const dist = haversineDistance(
|
||||
RESTAURANT_LAT, RESTAURANT_LNG,
|
||||
position.coords.latitude, position.coords.longitude
|
||||
);
|
||||
|
||||
const accuracy = position.coords.accuracy;
|
||||
console.log(`[GEO] Lat: ${position.coords.latitude}, Lng: ${position.coords.longitude}, Dist: ${dist}m, Accuracy: ${accuracy}m`);
|
||||
|
||||
if (dist <= MAX_DISTANCE_METERS) {
|
||||
startApp();
|
||||
setTimeout(() => showToast(`Lokalizacja zweryfikowana (Dystans: ${Math.round(dist)}m, Dokładność: ${Math.round(accuracy)}m)`), 2000);
|
||||
} else {
|
||||
geoMsg.innerHTML = `Wydaje się, że jesteś poza restauracją (ok. ${Math.round(dist)}m od nas).<br>Nasza aplikacja działa tylko na miejscu.<br><br>
|
||||
<small style="color: #888;">Debug: Twoja odległość: ${Math.round(dist)}m, Dokładność sygnału: ${Math.round(accuracy)}m</small><br><br>
|
||||
Jeśli to błąd GPS lub słaby sygnał, spróbuj ponownie za chwilę.`;
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
if (error.code === error.PERMISSION_DENIED) {
|
||||
geoMsg.innerHTML = `<b style="color: #ff6b6b;">Nie mamy Twojej zgody na lokalizację.</b><br><br>
|
||||
Przeglądarka zapamiętała Twoją odmowę i nie możemy ponownie wyświetlić okienka z zapytaniem. Aby odblokować dostęp:<br><br>
|
||||
1. Kliknij ikonkę <b>kłódki / ustawień</b> 🔒 obok adresu strony na samej górze przeglądarki.<br>
|
||||
2. Znajdź <b>Uprawnienia</b> (Lokalizacja) i zmień z "Zablokuj" na "Zezwalaj".<br>
|
||||
3. Odśwież stronę.`;
|
||||
} else {
|
||||
geoMsg.innerHTML = "Nie udało się pobrać lokalizacji. Sprawdź zasięg lub włącz GPS i spróbuj ponownie.";
|
||||
}
|
||||
},
|
||||
{ enableHighAccuracy: true, timeout: 15000, maximumAge: 0 }
|
||||
);
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
initGeolocation();
|
||||
}, 600);
|
||||
@@ -23,6 +23,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="geoScreen" class="hidden">
|
||||
<div class="geo-icon">📍</div>
|
||||
<div class="geo-text">
|
||||
<h2>Prywatność i Lokalizacja</h2>
|
||||
<div class="geo-msg" id="geoMsg">
|
||||
Aby zapewnić bezpieczeństwo Twojego zamówienia, musimy upewnić się, że znajdujesz się na terenie restauracji.<br><br>Prosimy o udzielenie zgody na dostęp do lokalizacji w przeglądarce.
|
||||
</div>
|
||||
<button class="btn btn-primary" style="margin-top: 24px; max-width: 250px; margin-left: auto; margin-right: auto;" onclick="initGeolocation()">Udziel zgody / Sprawdź</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<header id="mainHeader">
|
||||
<h1 class="logo-text">Karczma Biesiada</h1>
|
||||
|
||||
Reference in New Issue
Block a user