Files
2026-09-18 09:52:51 +02:00

1031 lines
35 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require_once('include/headscript.php');
/**
* Anteprima "scheda evento" pubblica (prototipo del widget WordPress).
* Versione COMPATTA + espandibile:
* - stato compatto: data, titolo, capacità/luogo/orario, prezzo, prenotazione
* - "Dettagli": espande la scheda completa (cover, descrizione, gallery, mappa,
* per chi è adatto / cosa portare / istruzioni)
* Prenotazione a passo unico: qty + "Prenota" rivela Nome/Cognome/Email + consensi
* nella stessa card. In anteprima "Conferma" non invia: mostra un riepilogo.
*/
$pdo = DBHandlerSelect::getInstance()->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));
}
?>
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8" />
<title><?php echo e($ev['title']); ?> — Anteprima</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<style>
:root {
--accent: <?php echo $color; ?>;
--ink: #2b2622;
--muted: #8c837c;
--line: #ece7e2;
--paper: #faf8f6;
--card: #ffffff;
--accent-soft: color-mix(in srgb, var(--accent) 10%, white);
--accent-tint: color-mix(in srgb, var(--accent) 16%, white);
--accent-ink: color-mix(in srgb, var(--accent) 62%, black);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background: var(--paper);
color: var(--ink);
font-family: 'Inter', system-ui, -apple-system, sans-serif;
line-height: 1.55;
-webkit-font-smoothing: antialiased;
}
.preview-bar {
background: var(--ink);
color: #f4efe9;
font-size: 13px;
text-align: center;
padding: 8px 16px;
}
.wrap {
max-width: 720px;
margin: 0 auto;
padding: 26px 18px 60px;
}
.card {
background: var(--card);
border-radius: 18px;
overflow: hidden;
box-shadow: 0 14px 40px rgba(43, 38, 34, 0.10);
}
/* ---------- HEADER COMPATTO ---------- */
.chead {
display: flex;
gap: 16px;
padding: 18px 22px;
align-items: flex-start;
}
.date-chip {
flex-shrink: 0;
border: 1px solid var(--line);
border-radius: 12px;
padding: 7px 11px 5px;
text-align: center;
min-width: 54px;
}
.date-chip .m {
font-size: 10.5px;
font-weight: 600;
letter-spacing: .12em;
color: var(--accent-ink);
}
.date-chip .d {
font-family: 'Fraunces', serif;
font-size: 23px;
font-weight: 600;
color: var(--ink);
line-height: 1;
}
.chead-thumb {
width: 76px;
height: 76px;
border-radius: 12px;
object-fit: cover;
flex-shrink: 0;
}
.chead .main {
flex: 1;
min-width: 0;
}
.title-row {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.title-row h1 {
font-family: 'Fraunces', serif;
font-weight: 500;
font-size: 21px;
margin: 0;
color: var(--ink);
}
.toggle {
background: none;
border: none;
color: var(--accent-ink);
font-weight: 600;
font-size: 13px;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 4px;
padding: 2px 2px;
}
.toggle svg {
width: 15px;
height: 15px;
transition: transform .2s;
}
.toggle.open svg {
transform: rotate(180deg);
}
.cmeta {
display: flex;
flex-wrap: wrap;
gap: 6px 20px;
margin-top: 9px;
}
.cmeta .item {
display: flex;
align-items: center;
gap: 7px;
color: var(--muted);
font-size: 13.5px;
}
.cmeta .item svg {
width: 16px;
height: 16px;
color: var(--accent-ink);
flex-shrink: 0;
}
.cmeta .item strong {
color: var(--ink);
font-weight: 600;
}
.price-badge {
flex-shrink: 0;
align-self: flex-start;
background: var(--accent);
color: #fff;
font-weight: 600;
font-size: 14px;
padding: 7px 13px;
border-radius: 999px;
}
/* ---------- DETTAGLI ESPANDIBILI ---------- */
.details {
display: none;
border-top: 1px solid var(--line);
}
.details.open {
display: block;
}
.hero {
position: relative;
height: 260px;
background: linear-gradient(135deg, var(--accent-ink), var(--accent));
}
.hero img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.hero .emblem {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
color: rgba(255, 255, 255, .35);
}
.hero .emblem svg {
width: 72px;
height: 72px;
}
.body {
padding: 22px;
}
.section+.section {
margin-top: 24px;
}
.section h3 {
font-family: 'Fraunces', serif;
font-weight: 600;
font-size: 18px;
color: var(--ink);
margin: 0 0 10px;
display: flex;
align-items: center;
gap: 9px;
}
.section h3 svg {
width: 19px;
height: 19px;
color: var(--accent-ink);
}
.desc {
font-size: 15px;
color: #4a433d;
}
.desc :where(p) {
margin: 0 0 10px;
}
.desc :where(img) {
max-width: 100%;
border-radius: 10px;
}
.detail-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
gap: 12px;
}
.detail {
background: var(--accent-soft);
border: 1px solid color-mix(in srgb, var(--accent) 18%, white);
border-radius: 13px;
padding: 14px 15px;
}
.detail .h {
display: flex;
align-items: center;
gap: 8px;
font-weight: 600;
color: var(--accent-ink);
margin-bottom: 6px;
font-size: 13.5px;
}
.detail .h svg {
width: 16px;
height: 16px;
}
.detail .t {
font-size: 13.5px;
color: #4a433d;
}
.gallery {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.gallery img {
width: 100px;
height: 100px;
object-fit: cover;
border-radius: 11px;
cursor: pointer;
transition: transform .15s, box-shadow .15s;
}
.gallery img:hover {
transform: translateY(-2px);
box-shadow: 0 8px 18px rgba(0, 0, 0, .15);
}
.map {
border: 0;
width: 100%;
height: 210px;
border-radius: 13px;
display: block;
}
/* ---------- BOOKING ---------- */
.booking {
padding: 18px 22px;
border-top: 1px solid var(--line);
}
.booking-compact {
display: flex;
align-items: flex-end;
gap: 18px;
flex-wrap: wrap;
}
.bc-block .lbl {
font-size: 12px;
color: var(--muted);
text-transform: uppercase;
letter-spacing: .05em;
margin-bottom: 5px;
}
.bc-title {
font-family: 'Fraunces', serif;
font-weight: 600;
font-size: 18px;
color: var(--ink);
margin-right: auto;
align-self: center;
}
.stepper {
display: flex;
align-items: center;
border: 1px solid var(--line);
border-radius: 11px;
overflow: hidden;
background: #fff;
}
.stepper button {
border: none;
background: #fff;
width: 42px;
height: 44px;
font-size: 21px;
color: var(--accent-ink);
cursor: pointer;
}
.stepper button:disabled {
color: #cfc8c2;
cursor: not-allowed;
}
.stepper .n {
width: 50px;
text-align: center;
font-size: 16px;
font-weight: 600;
}
.total-box .val {
font-family: 'Fraunces', serif;
font-size: 24px;
font-weight: 600;
color: var(--accent-ink);
}
.cta {
border: none;
border-radius: 11px;
background: var(--accent);
color: #fff;
font-size: 15px;
font-weight: 600;
font-family: inherit;
cursor: pointer;
transition: filter .15s;
}
.cta:hover {
filter: brightness(.94);
}
.cta:disabled {
background: #cfc8c2;
cursor: not-allowed;
}
.cta.compact {
padding: 13px 24px;
}
.cta.full {
width: 100%;
padding: 14px;
margin-top: 6px;
}
.booking-form {
display: none;
margin-top: 18px;
padding-top: 18px;
border-top: 1px dashed var(--line);
}
.booking-form.open {
display: block;
}
.field-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
}
.field {
margin-bottom: 12px;
}
.field label {
display: block;
font-size: 13px;
font-weight: 600;
color: var(--ink);
margin-bottom: 5px;
}
.field label .req {
color: #c0392b;
}
.field input {
width: 100%;
border: 1px solid var(--line);
border-radius: 10px;
padding: 11px 13px;
font-size: 15px;
font-family: inherit;
background: #fff;
color: var(--ink);
}
.field input:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, white);
}
.consent {
font-size: 13px;
color: #4a433d;
display: flex;
gap: 9px;
align-items: flex-start;
margin-bottom: 9px;
}
.consent input {
margin-top: 3px;
}
.consent a {
color: var(--accent-ink);
}
.soldout-note {
text-align: center;
font-weight: 600;
color: #c0392b;
}
.waitlist-banner {
background: color-mix(in srgb, var(--accent) 12%, white);
color: var(--accent-ink);
border-radius: 12px;
padding: 12px 14px;
font-size: 13.5px;
margin-bottom: 14px;
}
.form-error {
color: #c0392b;
font-size: 13px;
margin-top: 8px;
min-height: 18px;
}
.booking-done {
text-align: center;
padding: 6px 4px;
}
.booking-done .ok {
width: 52px;
height: 52px;
border-radius: 50%;
background: var(--accent);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 10px;
}
.booking-done h3 {
margin: 0 0 6px;
font-family: 'Fraunces', serif;
}
.booking-done p {
color: #4a433d;
font-size: 14px;
margin: 2px 0;
}
.booking-done .hintline {
color: var(--muted);
font-size: 12.5px;
margin-top: 10px;
}
.lightbox {
position: fixed;
inset: 0;
background: rgba(24, 19, 16, .9);
display: none;
align-items: center;
justify-content: center;
z-index: 50;
padding: 24px;
}
.lightbox.open {
display: flex;
}
.lightbox img {
max-width: 92vw;
max-height: 86vh;
border-radius: 12px;
}
.lightbox .close {
position: absolute;
top: 18px;
right: 22px;
color: #fff;
font-size: 34px;
cursor: pointer;
background: none;
border: none;
line-height: 1;
}
@media (max-width: 560px) {
.hero {
height: 200px;
}
.title-row h1 {
font-size: 19px;
}
.field-row {
grid-template-columns: 1fr;
}
.booking-compact {
gap: 14px;
}
.bc-title {
width: 100%;
margin-bottom: 4px;
}
}
@media (prefers-reduced-motion: reduce) {
* {
transition: none !important;
}
}
</style>
</head>
<body>
<div class="preview-bar">Anteprima — la card parte compatta; “Dettagli” apre la scheda completa. Il pulsante non invia nulla.</div>
<div class="wrap">
<div class="card">
<!-- HEADER COMPATTO -->
<div class="chead">
<div class="date-chip">
<div class="m"><?php echo e($monAbbr); ?></div>
<div class="d"><?php echo $dayNum; ?></div>
</div>
<?php if (!empty($ev['cover_image'])) : ?>
<img class="chead-thumb" src="<?php echo e($ev['cover_image']); ?>" alt="<?php echo e($ev['title']); ?>">
<?php endif; ?>
<div class="main">
<div class="title-row">
<h1><?php echo e($ev['title']); ?></h1>
<?php if ($hasDetails) : ?>
<button type="button" class="toggle" id="details-toggle" aria-expanded="false">
<span id="toggle-label">Dettagli</span>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="m6 9 6 6 6-6" />
</svg>
</button>
<?php endif; ?>
</div>
<div class="cmeta">
<div class="item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
<circle cx="12" cy="7" r="4" />
</svg>
<span>Capacità <strong><?php echo $booked; ?>/<?php echo $maxSeats; ?></strong></span>
</div>
<?php if (trim((string) $ev['address']) !== '') : ?>
<div class="item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7">
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" />
<circle cx="12" cy="10" r="3" />
</svg>
<span><?php echo e($ev['address']); ?></span>
</div>
<?php endif; ?>
<div class="item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7">
<circle cx="12" cy="12" r="9" />
<path d="M12 7v5l3 2" />
</svg>
<span><?php echo e($dateLong); ?> · <?php echo e($timeLabel); ?></span>
</div>
</div>
</div>
<div class="price-badge"><?php echo e($priceLabel); ?></div>
</div>
<!-- DETTAGLI ESPANDIBILI -->
<?php if ($hasDetails) : ?>
<div class="details" id="details">
<div class="hero">
<?php if (!empty($ev['cover_image'])) : ?>
<img src="<?php echo e($ev['cover_image']); ?>" alt="<?php echo e($ev['title']); ?>">
<?php else : ?>
<div class="emblem"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4">
<rect x="3" y="3" width="18" height="18" rx="2" />
<circle cx="9" cy="9" r="2" />
<path d="m21 15-5-5L5 21" />
</svg></div>
<?php endif; ?>
</div>
<div class="body">
<?php if (trim((string) $ev['description']) !== '') : ?>
<div class="section">
<div class="desc"><?php echo $ev['description']; ?></div>
</div>
<?php endif; ?>
<?php if (trim((string) $ev['suitable_for']) !== '' || trim((string) $ev['what_to_bring']) !== '' || trim((string) $ev['instructions']) !== '') : ?>
<div class="section">
<div class="detail-grid">
<?php if (trim((string) $ev['suitable_for']) !== '') : ?>
<div class="detail">
<div class="h"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7">
<path d="M20.8 5.6a5 5 0 0 0-7-.1L12 7l-1.8-1.5a5 5 0 1 0-6.6 7.5L12 21l8.4-8a5 5 0 0 0 .4-7.4z" />
</svg> Per chi è adatto</div>
<div class="t"><?php echo textBlock($ev['suitable_for']); ?></div>
</div>
<?php endif; ?>
<?php if (trim((string) $ev['what_to_bring']) !== '') : ?>
<div class="detail">
<div class="h"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7">
<path d="M6 7h12l1 13H5L6 7z" />
<path d="M9 7a3 3 0 0 1 6 0" />
</svg> Cosa portare</div>
<div class="t"><?php echo textBlock($ev['what_to_bring']); ?></div>
</div>
<?php endif; ?>
<?php if (trim((string) $ev['instructions']) !== '') : ?>
<div class="detail">
<div class="h"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7">
<circle cx="12" cy="12" r="9" />
<path d="M12 11v5" />
<path d="M12 8h.01" />
</svg> Istruzioni</div>
<div class="t"><?php echo textBlock($ev['instructions']); ?></div>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php if (!empty($gallery)) : ?>
<div class="section">
<h3><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7">
<rect x="3" y="3" width="18" height="18" rx="2" />
<circle cx="9" cy="9" r="2" />
<path d="m21 15-5-5L5 21" />
</svg> Galleria</h3>
<div class="gallery">
<?php foreach ($gallery as $g) : ?>
<img src="<?php echo e($g); ?>" alt="" data-full="<?php echo e($g); ?>">
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<?php if ($mapQuery !== '') : ?>
<div class="section">
<h3><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7">
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" />
<circle cx="12" cy="10" r="3" />
</svg> Dove</h3>
<iframe class="map" loading="lazy" src="https://www.google.com/maps?q=<?php echo urlencode($mapQuery); ?>&output=embed"></iframe>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<!-- BOOKING (compatto, passo unico) -->
<div class="booking" id="booking">
<?php if ($hardFull) : ?>
<div class="soldout-note">Evento esaurito — non ci sono più posti disponibili.</div>
<?php else : ?>
<?php if ($waitMode) : ?>
<div class="waitlist-banner">Posti esauriti — puoi iscriverti alla <strong>lista d'attesa</strong>: ti avviseremo se si libera un posto.</div>
<?php endif; ?>
<div class="booking-compact">
<div class="bc-title"><?php echo $waitMode ? "Lista d'attesa" : 'Prenota questo evento'; ?></div>
<div class="bc-block">
<div class="lbl">Persone</div>
<div class="stepper">
<button type="button" id="q-minus">−</button>
<span class="n" id="q-num">1</span>
<button type="button" id="q-plus">+</button>
</div>
</div>
<div class="bc-block total-box">
<div class="lbl">Totale</div>
<div class="val" id="q-total"><?php echo e($priceLabel); ?></div>
</div>
<button type="button" class="cta compact" id="b-open"><?php echo $waitMode ? "Lista d'attesa" : 'Prenota'; ?></button>
</div>
<div class="booking-form" id="booking-form">
<div class="field-row">
<div class="field">
<label>Nome <span class="req">*</span></label>
<input type="text" id="b-name" placeholder="Il tuo nome">
</div>
<div class="field">
<label>Cognome <span class="req">*</span></label>
<input type="text" id="b-surname" placeholder="Il tuo cognome">
</div>
</div>
<div class="field">
<label>Email <span class="req">*</span></label>
<input type="email" id="b-email" placeholder="latua@email.it">
</div>
<label class="consent">
<input type="checkbox" id="b-consent">
<span>Ho letto e accetto l'<a href="#" target="_blank">informativa privacy</a>. <span class="req">*</span></span>
</label>
<label class="consent">
<input type="checkbox" id="b-marketing">
<span>Desidero ricevere aggiornamenti e novità via email.</span>
</label>
<button type="button" class="cta full" id="b-submit"><?php echo $waitMode ? "Iscriviti alla lista d'attesa" : 'Conferma prenotazione'; ?></button>
<div class="form-error" id="b-error"></div>
</div>
<?php endif; ?>
</div>
</div>
<script>
var WAIT_MODE = <?php echo $waitMode ? 'true' : 'false'; ?>;
</script>
</div>
<div class="lightbox" id="lightbox">
<button class="close" id="lb-close">&times;</button>
<img src="" alt="" id="lb-img">
</div>
<script>
var COST = <?php echo json_encode($cost); ?>;
var SYM = <?php echo json_encode($sym); ?>;
var MAXQTY = <?php echo (int) $maxQty; ?>;
function fmtMoney(v) {
if (v <= 0) return 'Gratuito';
return SYM + v.toLocaleString('it-IT', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
}
// Toggle dettagli
var dt = document.getElementById('details-toggle');
if (dt) {
dt.addEventListener('click', function() {
var box = document.getElementById('details');
var open = box.classList.toggle('open');
dt.classList.toggle('open', open);
dt.setAttribute('aria-expanded', open ? 'true' : 'false');
document.getElementById('toggle-label').textContent = open ? 'Chiudi' : 'Dettagli';
});
}
(function() {
var qty = 1;
var numEl = document.getElementById('q-num');
if (!numEl) return;
var totEl = document.getElementById('q-total');
var minus = document.getElementById('q-minus');
var plus = document.getElementById('q-plus');
var submitBtn = document.getElementById('b-submit');
function refresh() {
numEl.textContent = qty;
totEl.textContent = fmtMoney(qty * COST);
minus.disabled = qty <= 1;
plus.disabled = qty >= MAXQTY;
if (submitBtn) {
if (typeof WAIT_MODE !== 'undefined' && WAIT_MODE) {
submitBtn.textContent = "Iscriviti alla lista d'attesa";
} else {
submitBtn.textContent = 'Conferma prenotazione' + (COST > 0 ? ' · ' + fmtMoney(qty * COST) : '');
}
}
}
minus.addEventListener('click', function() {
if (qty > 1) {
qty--;
refresh();
}
});
plus.addEventListener('click', function() {
if (qty < MAXQTY) {
qty++;
refresh();
}
});
refresh();
// "Prenota" rivela i campi (stessa card, passo unico)
document.getElementById('b-open').addEventListener('click', function() {
document.getElementById('booking-form').classList.add('open');
this.style.display = 'none';
document.getElementById('b-name').focus();
});
submitBtn.addEventListener('click', function() {
var name = document.getElementById('b-name').value.trim();
var surname = document.getElementById('b-surname').value.trim();
var email = document.getElementById('b-email').value.trim();
var consent = document.getElementById('b-consent').checked;
var err = document.getElementById('b-error');
if (!name || !surname) {
err.textContent = 'Inserisci nome e cognome.';
return;
}
if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) {
err.textContent = 'Inserisci un\'email valida.';
return;
}
if (!consent) {
err.textContent = 'Devi accettare l\'informativa privacy.';
return;
}
err.textContent = '';
var marketing = document.getElementById('b-marketing').checked;
var wm = (typeof WAIT_MODE !== 'undefined' && WAIT_MODE);
document.getElementById('booking').innerHTML =
'<div class="booking-done">' +
' <div class="ok"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" width="24" height="24"><path d="M20 6 9 17l-5-5"/></svg></div>' +
' <h3>' + (wm ? "Anteprima lista d'attesa" : 'Anteprima prenotazione') + '</h3>' +
' <p><strong>' + name + ' ' + surname + '</strong> · ' + email + '</p>' +
' <p>' + qty + ' ' + (qty === 1 ? 'persona' : 'persone') + (wm ? " · in lista d'attesa" : ' · Totale <strong>' + fmtMoney(qty * COST) + '</strong>') + '</p>' +
' <p>Marketing: ' + (marketing ? 'sì' : 'no') + '</p>' +
' <p class="hintline">' + (wm ? "Nel widget pubblico, qui parte l'iscrizione alla lista d'attesa." : 'Nel widget pubblico, qui parte la prenotazione reale (POST all\'endpoint).') + '</p>' +
'</div>';
});
})();
// Lightbox galleria
var lb = document.getElementById('lightbox');
var lbImg = document.getElementById('lb-img');
document.querySelectorAll('.gallery img').forEach(function(img) {
img.addEventListener('click', function() {
lbImg.src = img.getAttribute('data-full');
lb.classList.add('open');
});
});
function closeLb() {
lb.classList.remove('open');
lbImg.src = '';
}
document.getElementById('lb-close').addEventListener('click', closeLb);
lb.addEventListener('click', function(e) {
if (e.target === lb) closeLb();
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') closeLb();
});
</script>
</body>
</html>