Files

339 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reservierungssystem</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--primary: #3b82f6;
--primary-dark: #2563eb;
--bg: #f8fafc;
--card: #ffffff;
--text: #1e293b;
--text-light: #64748b;
--border: #e2e8f0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg);
color: var(--text);
min-height: 100vh;
}
.header {
background: var(--card);
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border);
}
.logo { font-size: 1.5rem; font-weight: 600; color: var(--primary); }
.nav { display: flex; gap: 1rem; align-items: center; }
.btn {
padding: 0.5rem 1.25rem;
border-radius: 6px;
border: none;
cursor: pointer;
font-size: 0.9rem;
transition: all 0.2s;
}
.btn-primary { background: var(--primary); color: white; }
.btn-primary:hover { background: var(--primary-dark); }
.btn-secondary { background: transparent; border: 1px solid var(--border); color: var(--text); }
.container { max-width: 1200px; margin: 0 auto; padding: 2rem; }
.page-title { font-size: 2rem; font-weight: 700; margin-bottom: 0.5rem; }
.page-subtitle { color: var(--text-light); margin-bottom: 2rem; }
.rooms-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.room-card {
background: var(--card);
border-radius: 12px;
padding: 1.5rem;
border: 1px solid var(--border);
cursor: pointer;
transition: all 0.2s;
}
.room-card:hover {
box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1);
}
.form-group { margin-bottom: 1rem; }
.form-group label { display: block; margin-bottom: 0.5rem; font-size: 0.875rem; color: var(--text-light); }
.form-group input {
width: 100%;
padding: 0.75rem;
border: 1px solid var(--border);
border-radius: 6px;
font-size: 1rem;
}
.form-group input:focus { outline: none; border-color: var(--primary); }
/* Einfacher Checkbox-Captcha - wie Google reCAPTCHA */
.captcha-box {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem 1.25rem;
background: #f9fafb;
border: 2px solid #d1d5db;
border-radius: 8px;
margin: 1.5rem 0;
width: fit-content;
}
.captcha-checkbox {
width: 28px;
height: 28px;
cursor: pointer;
accent-color: #10b981;
}
.captcha-label {
font-size: 1rem;
color: var(--text);
cursor: pointer;
user-select: none;
}
.modal {
display: none;
position: fixed;
top: 0; left: 0; width: 100%; height: 100%;
background: rgba(0,0,0,0.5);
z-index: 1000;
align-items: center;
justify-content: center;
}
.modal.active { display: flex; }
.modal-content {
background: var(--card);
padding: 2rem;
border-radius: 12px;
width: 90%;
max-width: 400px;
}
.modal-title { font-size: 1.25rem; font-weight: 600; margin-bottom: 1.5rem; }
.admin-only { display: none; }
.admin-visible .admin-only { display: block; }
.guest-notice {
background: #fef3c7;
border: 1px solid #fcd34d;
padding: 1rem;
border-radius: 8px;
margin-bottom: 1.5rem;
color: #92400e;
}
</style>
</head>
<body>
<header class="header">
<div class="logo">🍽️ Reservierung</div>
<nav class="nav">
<span id="userStatus"></span>
<button class="btn btn-secondary" id="loginBtn" onclick="showLogin()">Admin Login</button>
<button class="btn btn-primary admin-only" onclick="showNewBooking()">+ Buchung</button>
</nav>
</header>
<div class="modal" id="loginModal">
<div class="modal-content">
<h2 class="modal-title">Admin Login</h2>
<form id="loginForm" onsubmit="handleLogin(event)">
<div class="form-group">
<label>Passwort</label>
<input type="password" id="loginPassword" required placeholder="••••••••">
</div>
<button type="submit" class="btn btn-primary" style="width: 100%">Anmelden</button>
<button type="button" class="btn btn-secondary" style="width: 100%; margin-top: 0.5rem" onclick="hideLogin()">Abbrechen</button>
</form>
</div>
</div>
<main class="container">
<div class="guest-notice" id="guestNotice">
👋 Willkommen! Als Gast können Sie Tische reservieren.
</div>
<h1 class="page-title">Unsere Räume</h1>
<p class="page-subtitle">Wählen Sie einen Raum für Ihre Reservierung</p>
<div class="loading" id="loading">Lade Räume...</div>
<div class="rooms-grid" id="roomsGrid" style="display: none;"></div>
<div id="bookingSection" style="display: none;">
<h2 style="margin: 2rem 0 1rem;">Tisch reservieren</h2>
<!-- Einfacher Checkbox-Captcha -->
<div class="captcha-box">
<input type="checkbox" id="captchaCheckbox" class="captcha-checkbox">
<label for="captchaCheckbox" class="captcha-label">Ich bin kein Roboter</label>
</div>
<form id="bookingForm" onsubmit="handleBooking(event)">
<div class="form-group">
<label>Name *</label>
<input type="text" id="bookingName" required placeholder="Max Mustermann">
</div>
<div class="form-group">
<label>E-Mail *</label>
<input type="email" id="bookingEmail" required placeholder="max@beispiel.de">
</div>
<div class="form-group">
<label>Telefon</label>
<input type="tel" id="bookingPhone" placeholder="+49 123 456789">
</div>
<div class="form-group">
<label>Datum *</label>
<input type="date" id="bookingDate" required>
</div>
<div class="form-group">
<label>Zeit *</label>
<input type="time" id="bookingTime" required>
</div>
<div class="form-group">
<label>Personen *</label>
<input type="number" id="bookingGuests" min="1" max="20" value="2" required>
</div>
<button type="submit" class="btn btn-primary" style="width: 100%">Reservierung anfragen</button>
</form>
</div>
</main>
<script>
let currentUser = null;
async function checkSession() {
try {
const res = await fetch('/api/session');
const data = await res.json();
if (data.logged_in) {
currentUser = data;
document.body.classList.add('admin-visible');
document.getElementById('loginBtn').textContent = 'Abmelden';
document.getElementById('loginBtn').onclick = logout;
document.getElementById('guestNotice').style.display = 'none';
}
} catch (e) {}
loadRooms();
}
async function loadRooms() {
try {
const res = await fetch('/api/rooms');
const rooms = await res.json();
displayRooms(rooms);
} catch (e) {
document.getElementById('loading').textContent = 'Fehler beim Laden';
}
}
function displayRooms(rooms) {
const grid = document.getElementById('roomsGrid');
document.getElementById('loading').style.display = 'none';
grid.style.display = 'grid';
grid.innerHTML = rooms.map(room => `
<div class="room-card" onclick="selectRoom(${room.id}, '${room.name}')" style="border-left: 4px solid ${room.color}">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:1rem">
<span style="font-size:1.25rem; font-weight:600">${room.name}</span>
<span style="padding:0.25rem 0.75rem; border-radius:20px; font-size:0.75rem; background:${room.color}20; color:${room.color}">${room.capacity} Plätze</span>
</div>
<div style="color:var(--text-light); font-size:0.9rem">${room.areas ? room.areas.length : 0} Bereiche</div>
</div>
`).join('');
}
function selectRoom(roomId, roomName) {
document.getElementById('bookingSection').style.display = 'block';
document.getElementById('bookingSection').scrollIntoView({ behavior: 'smooth' });
}
function showLogin() { document.getElementById('loginModal').classList.add('active'); }
function hideLogin() { document.getElementById('loginModal').classList.remove('active'); }
async function handleLogin(e) {
e.preventDefault();
const password = document.getElementById('loginPassword').value;
try {
const res = await fetch('/api/admin/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ password })
});
if (res.ok) { hideLogin(); location.reload(); }
else { alert('Falsches Passwort'); }
} catch (e) { alert('Fehler beim Login'); }
}
async function logout() {
await fetch('/api/admin/logout', { method: 'POST' });
location.reload();
}
async function handleBooking(e) {
e.preventDefault();
// Einfacher Checkbox-Captcha-Check
if (!document.getElementById('captchaCheckbox').checked) {
alert('Bitte bestätigen Sie "Ich bin kein Roboter"');
return;
}
const data = {
name: document.getElementById('bookingName').value,
email: document.getElementById('bookingEmail').value,
phone: document.getElementById('bookingPhone').value,
date: document.getElementById('bookingDate').value,
time: document.getElementById('bookingTime').value,
guests: parseInt(document.getElementById('bookingGuests').value),
captcha_verified: true
};
try {
const res = await fetch('/api/reservations', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (res.ok) {
alert('Reservierung erfolgreich! Wir melden uns bei Ihnen.');
document.getElementById('bookingForm').reset();
document.getElementById('captchaCheckbox').checked = false;
} else {
const err = await res.json();
alert(err.error || 'Fehler bei der Reservierung');
}
} catch (e) { alert('Netzwerkfehler'); }
}
document.getElementById('bookingDate').valueAsDate = new Date();
checkSession();
</script>
</body>
</html>