getConnection(); function e($value): string { return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8'); } $id = isset($_GET['id']) ? (int) $_GET['id'] : 0; if ($id <= 0) { http_response_code(404); echo 'Evento non trovato'; exit(); } $st = $pdo->prepare("SELECT e.*, u.first_name AS cf, u.last_name AS cl FROM events e LEFT JOIN auth_users u ON u.id = e.user_id WHERE e.id = ?"); $st->execute([$id]); $ev = $st->fetch(PDO::FETCH_ASSOC); if (!$ev) { http_response_code(404); echo 'Evento non trovato'; exit(); } $bs = $pdo->prepare("SELECT COALESCE(SUM(seats),0) FROM event_bookings WHERE event_id = ? AND status IN ('confirmed','pending','offered')"); $bs->execute([$id]); $booked = (int) $bs->fetchColumn(); $maxSeats = (int) $ev['max_seats']; $remaining = max(0, $maxSeats - $booked); $soldOut = $remaining <= 0; $maxPer = max(1, (int) $ev['max_per_booking']); $waitlistOn = ($ev['waitlist_enabled'] ?? 'N') === 'Y'; $waitMode = $soldOut && $waitlistOn; // pieno ma con lista d'attesa $hardFull = $soldOut && !$waitlistOn; // pieno senza lista d'attesa $maxQty = $soldOut ? ($waitMode ? $maxPer : 0) : max(1, min($maxPer, $remaining)); $cost = (float) $ev['cost']; $curr = $ev['currency'] ?: 'EUR'; $symbols = ['EUR' => '€', 'USD' => '$', 'GBP' => '£', 'CHF' => 'CHF']; $sym = $symbols[$curr] ?? $curr; $priceLabel = $cost > 0 ? $sym . number_format($cost, 2, ',', '.') : 'Gratuito'; $color = (isset($ev['color']) && preg_match('/^#[0-9a-fA-F]{6}$/', $ev['color'])) ? $ev['color'] : '#4CAF50'; $gallery = []; if (!empty($ev['gallery'])) { $g = json_decode($ev['gallery'], true); if (is_array($g)) { $gallery = $g; } } $mesiAbbr = [1 => 'GEN', 2 => 'FEB', 3 => 'MAR', 4 => 'APR', 5 => 'MAG', 6 => 'GIU', 7 => 'LUG', 8 => 'AGO', 9 => 'SET', 10 => 'OTT', 11 => 'NOV', 12 => 'DIC']; $mesi = [1 => 'gennaio', 2 => 'febbraio', 3 => 'marzo', 4 => 'aprile', 5 => 'maggio', 6 => 'giugno', 7 => 'luglio', 8 => 'agosto', 9 => 'settembre', 10 => 'ottobre', 11 => 'novembre', 12 => 'dicembre']; $startTs = strtotime($ev['starts_at']); $dayNum = (int) date('j', $startTs); $monAbbr = $mesiAbbr[(int) date('n', $startTs)]; $dateLong = $dayNum . ' ' . $mesi[(int) date('n', $startTs)] . ' ' . date('Y', $startTs); $timeLabel = date('H:i', $startTs); if (!empty($ev['ends_at'])) { $timeLabel .= '–' . date('H:i', strtotime($ev['ends_at'])); } $organizer = trim((string) $ev['organizer_name']) !== '' ? $ev['organizer_name'] : trim(($ev['cf'] ?? '') . ' ' . ($ev['cl'] ?? '')); $mapQuery = trim((string) $ev['address']) !== '' ? $ev['address'] : (($ev['lat'] !== null && $ev['lng'] !== null) ? ($ev['lat'] . ',' . $ev['lng']) : ''); $hasDetails = trim((string) $ev['description']) !== '' || trim((string) $ev['suitable_for']) !== '' || trim((string) $ev['what_to_bring']) !== '' || trim((string) $ev['instructions']) !== '' || !empty($ev['cover_image']) || !empty($gallery) || $mapQuery !== ''; function textBlock(?string $t): string { return nl2br(e((string) $t)); } ?>