164 lines
6.2 KiB
PHP
164 lines
6.2 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/includes/bootstrap.php';
|
|
|
|
$projectName = $_SERVER['PROJECT_NAME'] ?? 'CineReserve';
|
|
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
|
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
|
|
|
$showId = isset($_GET['show_id']) ? (int)$_GET['show_id'] : 0;
|
|
$show = $showId ? fetch_show($showId) : null;
|
|
|
|
$rows = ['A', 'B', 'C', 'D', 'E'];
|
|
$seatsPerRow = 8;
|
|
$allSeats = [];
|
|
foreach ($rows as $row) {
|
|
for ($i = 1; $i <= $seatsPerRow; $i++) {
|
|
$allSeats[] = $row . $i;
|
|
}
|
|
}
|
|
$bookedSeats = $show ? fetch_booked_seats($showId) : [];
|
|
|
|
$errors = [];
|
|
$success = '';
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $show) {
|
|
$name = trim($_POST['customer_name'] ?? '');
|
|
$email = trim($_POST['customer_email'] ?? '');
|
|
$seats = trim($_POST['seats'] ?? '');
|
|
|
|
if ($name === '') {
|
|
$errors[] = 'Customer name is required.';
|
|
}
|
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
$errors[] = 'A valid email is required.';
|
|
}
|
|
$seatList = array_filter(array_map('trim', explode(',', $seats)));
|
|
if (!$seatList) {
|
|
$errors[] = 'Select at least one seat.';
|
|
}
|
|
|
|
$invalidSeats = array_diff($seatList, $allSeats);
|
|
$takenSeats = array_intersect($seatList, $bookedSeats);
|
|
if ($invalidSeats) {
|
|
$errors[] = 'One or more seats are invalid.';
|
|
}
|
|
if ($takenSeats) {
|
|
$errors[] = 'Some selected seats are already booked: ' . implode(', ', $takenSeats) . '.';
|
|
}
|
|
|
|
if (!$errors) {
|
|
$pdo = db();
|
|
$bookingCode = generate_booking_code($pdo);
|
|
$total = count($seatList) * (float)$show['price'];
|
|
|
|
$stmt = $pdo->prepare(
|
|
"INSERT INTO bookings (show_id, customer_name, customer_email, seats, total_price, booking_code)
|
|
VALUES (?, ?, ?, ?, ?, ?)"
|
|
);
|
|
$stmt->execute([$showId, $name, $email, implode(', ', $seatList), $total, $bookingCode]);
|
|
|
|
header('Location: confirmation.php?code=' . urlencode($bookingCode));
|
|
exit;
|
|
}
|
|
}
|
|
?>
|
|
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title><?= h($projectName) ?> — Select seats</title>
|
|
<?php if ($projectDescription): ?>
|
|
<meta name="description" content="<?= h($projectDescription) ?>" />
|
|
<meta property="og:description" content="<?= h($projectDescription) ?>" />
|
|
<meta property="twitter:description" content="<?= h($projectDescription) ?>" />
|
|
<?php endif; ?>
|
|
<?php if ($projectImageUrl): ?>
|
|
<meta property="og:image" content="<?= h($projectImageUrl) ?>" />
|
|
<meta property="twitter:image" content="<?= h($projectImageUrl) ?>" />
|
|
<?php endif; ?>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?= time(); ?>">
|
|
</head>
|
|
<body data-price="<?= h($show ? (string)$show['price'] : '0') ?>">
|
|
<div class="app-shell">
|
|
<nav class="navbar navbar-light">
|
|
<div class="container">
|
|
<a class="navbar-brand fw-semibold" href="/"> <?= h($projectName) ?></a>
|
|
<a class="btn btn-outline-dark btn-sm" href="/">Back to movies</a>
|
|
</div>
|
|
</nav>
|
|
|
|
<main class="container my-4">
|
|
<?php if (!$show): ?>
|
|
<div class="alert alert-light border">Select a showtime to continue booking.</div>
|
|
<?php else: ?>
|
|
<div class="row g-4">
|
|
<div class="col-lg-7">
|
|
<div class="surface">
|
|
<h1 class="h4 mb-2">Choose your seats</h1>
|
|
<p class="text-muted small mb-4"><?= h($show['title']) ?> · <?= h(date('M d, H:i', strtotime($show['show_time']))) ?> · <?= h($show['format_label']) ?></p>
|
|
<div class="mb-3">
|
|
<div class="text-muted small mb-2">Screen</div>
|
|
<div class="badge-soft"><?= h($show['screen']) ?></div>
|
|
</div>
|
|
<div class="seat-grid mb-3" data-seat-grid>
|
|
<?php foreach ($allSeats as $seat): ?>
|
|
<?php $taken = in_array($seat, $bookedSeats, true); ?>
|
|
<div class="seat <?= $taken ? 'taken' : '' ?>" data-seat="<?= h($seat) ?>">
|
|
<?= h($seat) ?>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<div class="d-flex justify-content-between small text-muted">
|
|
<span>Selected: <span data-seat-output>None yet</span></span>
|
|
<span>Total: $<span data-total>0.00</span></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-5">
|
|
<div class="surface">
|
|
<h2 class="h5">Booking details</h2>
|
|
<?php if ($errors): ?>
|
|
<div class="alert alert-danger">
|
|
<?php foreach ($errors as $error): ?>
|
|
<div><?= h($error) ?></div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
<form method="post">
|
|
<div class="mb-3">
|
|
<label class="form-label">Full name</label>
|
|
<input class="form-control" name="customer_name" value="<?= h($_POST['customer_name'] ?? '') ?>" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Email</label>
|
|
<input class="form-control" name="customer_email" type="email" value="<?= h($_POST['customer_email'] ?? '') ?>" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Selected seats</label>
|
|
<input class="form-control" name="seats" data-seat-input readonly>
|
|
</div>
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<span class="text-muted small">Price per seat</span>
|
|
<span class="fw-semibold">$<?= h(number_format((float)$show['price'], 2)) ?></span>
|
|
</div>
|
|
<button class="btn btn-primary w-100" type="submit">Confirm booking</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
</main>
|
|
<footer class="footer py-3">
|
|
<div class="container">
|
|
<span class="text-muted small">Secure checkout placeholder · Pay at cinema supported.</span>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
<script src="assets/js/main.js?v=<?= time(); ?>"></script>
|
|
</body>
|
|
</html>
|