const form = document.getElementById('rsvp-form'); const statusNode = document.getElementById('form-status'); const attendanceFields = document.getElementById('attendance-fields'); const attendanceInputs = Array.from(document.querySelectorAll('input[name="attendance"]')); const successModal = document.getElementById('success-modal'); const successOkButton = document.getElementById('success-ok'); const closeModalNodes = Array.from(document.querySelectorAll('[data-close-modal]')); const googleCalendarLink = document.getElementById('google-calendar-link'); const iCalDownloadButton = document.getElementById('ical-download'); const copyIbanButton = document.getElementById('copy-iban'); const ibanFeedback = document.getElementById('iban-feedback'); const giftHolder = document.getElementById('gift-holder'); const giftIban = document.getElementById('gift-iban'); const giftCausal = document.getElementById('gift-causal'); const giftNote = document.getElementById('gift-note'); // Modifica qui i dati del calendario evento. const EVENT_CALENDAR = { title: 'Il Gianquarantesimo', location: 'Lost Paradise Beach Club, Bacoli', description: 'Conferma la tua presenza per i 40 anni del Gianca.', date: '2026-04-25', startTime: '12:00', durationHours: 6, timezone: 'Europe/Rome' }; // Modifica qui i dati regalo / quota viaggio. const GIFT_DETAILS = { holder: 'Flygo S.r.l', iban: 'IT 34 O 02008 03450 000011029239', causal: 'Lista Compleanno Giancarlo Esposito da parte di ...', note: 'Nota facoltativa: un pensiero semplice e sempre gradito.' }; function updateAttendanceFields() { const selected = document.querySelector('input[name="attendance"]:checked'); const attending = selected?.value === 'si'; attendanceFields.classList.toggle('attendance-fields--hidden', !attending); attendanceFields.querySelectorAll('input, select, textarea').forEach((field) => { field.disabled = !attending; if (!attending && field.tagName === 'TEXTAREA') field.value = ''; if (!attending && field.tagName === 'SELECT') field.value = '0'; }); } function openSuccessModal() { if (!successModal) return; successModal.classList.add('success-modal--open'); successModal.setAttribute('aria-hidden', 'false'); document.body.classList.add('modal-open'); successOkButton?.focus(); } function closeSuccessModal() { if (!successModal) return; successModal.classList.remove('success-modal--open'); successModal.setAttribute('aria-hidden', 'true'); document.body.classList.remove('modal-open'); } function pad(value) { return String(value).padStart(2, '0'); } function createFloatingDateTime(date, time, plusHours = 0) { const [year, month, day] = date.split('-').map(Number); const [hours, minutes] = time.split(':').map(Number); const normalizedDate = new Date(Date.UTC(year, month - 1, day, hours, minutes, 0)); normalizedDate.setUTCHours(normalizedDate.getUTCHours() + plusHours); return `${normalizedDate.getUTCFullYear()}${pad(normalizedDate.getUTCMonth() + 1)}${pad(normalizedDate.getUTCDate())}T${pad(normalizedDate.getUTCHours())}${pad(normalizedDate.getUTCMinutes())}00`; } function buildGoogleCalendarUrl(eventData) { const start = createFloatingDateTime(eventData.date, eventData.startTime, 0); const end = createFloatingDateTime(eventData.date, eventData.startTime, eventData.durationHours); const params = new URLSearchParams({ action: 'TEMPLATE', text: eventData.title, details: eventData.description, location: eventData.location, ctz: eventData.timezone, dates: `${start}/${end}` }); return `https://calendar.google.com/calendar/render?${params.toString()}`; } function escapeIcsText(value) { return value .replace(/\\/g, '\\\\') .replace(/\n/g, '\\n') .replace(/,/g, '\\,') .replace(/;/g, '\\;'); } function buildIcsContent(eventData) { const start = createFloatingDateTime(eventData.date, eventData.startTime, 0); const end = createFloatingDateTime(eventData.date, eventData.startTime, eventData.durationHours); const stamp = `${createFloatingDateTime(eventData.date, eventData.startTime, 0)}Z`; const uid = `gianca-40-${start}@gianca-event`; return [ 'BEGIN:VCALENDAR', 'VERSION:2.0', 'PRODID:-//Gianca40//Event Landing//IT', 'CALSCALE:GREGORIAN', 'BEGIN:VEVENT', `UID:${uid}`, `DTSTAMP:${stamp}`, `DTSTART;TZID=${eventData.timezone}:${start}`, `DTEND;TZID=${eventData.timezone}:${end}`, `SUMMARY:${escapeIcsText(eventData.title)}`, `LOCATION:${escapeIcsText(eventData.location)}`, `DESCRIPTION:${escapeIcsText(eventData.description)}`, 'END:VEVENT', 'END:VCALENDAR' ].join('\r\n'); } function triggerIcsDownload() { const content = buildIcsContent(EVENT_CALENDAR); const blob = new Blob([content], { type: 'text/calendar;charset=utf-8' }); const downloadUrl = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = downloadUrl; link.download = 'i-40-anni-del-gianca.ics'; document.body.append(link); link.click(); link.remove(); URL.revokeObjectURL(downloadUrl); } function setIbanFeedback(message) { if (!ibanFeedback) return; ibanFeedback.textContent = message; } async function copyIbanToClipboard() { if (!copyIbanButton) return; const ibanNodeId = copyIbanButton.dataset.copyTarget; const ibanText = document.getElementById(ibanNodeId || '')?.textContent?.trim(); if (!ibanText) return; try { await navigator.clipboard.writeText(ibanText); setIbanFeedback('IBAN copiato negli appunti.'); } catch (error) { const fallbackField = document.createElement('input'); fallbackField.value = ibanText; document.body.append(fallbackField); fallbackField.select(); const copied = document.execCommand('copy'); fallbackField.remove(); setIbanFeedback(copied ? 'IBAN copiato negli appunti.' : 'Copia non riuscita. Riprova.'); } } attendanceInputs.forEach((input) => input.addEventListener('change', updateAttendanceFields)); closeModalNodes.forEach((node) => node.addEventListener('click', closeSuccessModal)); successOkButton?.addEventListener('click', closeSuccessModal); iCalDownloadButton?.addEventListener('click', triggerIcsDownload); copyIbanButton?.addEventListener('click', async () => { await copyIbanToClipboard(); window.clearTimeout(copyIbanButton.dataset.feedbackTimeoutId); const timeoutId = window.setTimeout(() => setIbanFeedback(''), 2500); copyIbanButton.dataset.feedbackTimeoutId = String(timeoutId); }); document.addEventListener('keydown', (event) => { if (event.key === 'Escape' && successModal?.classList.contains('success-modal--open')) { closeSuccessModal(); } }); updateAttendanceFields(); if (googleCalendarLink) { googleCalendarLink.href = buildGoogleCalendarUrl(EVENT_CALENDAR); } if (giftHolder) giftHolder.textContent = GIFT_DETAILS.holder; if (giftIban) giftIban.textContent = GIFT_DETAILS.iban; if (giftCausal) giftCausal.textContent = GIFT_DETAILS.causal; if (giftNote) giftNote.textContent = GIFT_DETAILS.note; function encode(data) { return new URLSearchParams(data).toString(); } form?.addEventListener('submit', async (event) => { event.preventDefault(); if (!form.reportValidity()) return; const submitButton = form.querySelector('button[type="submit"]'); const formData = new FormData(form); submitButton.disabled = true; statusNode.textContent = 'Invio in corso...'; try { const response = await fetch('/', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: encode(formData) }); if (!response.ok) { throw new Error('Submission failed'); } form.reset(); updateAttendanceFields(); statusNode.textContent = ''; openSuccessModal(); } catch (error) { statusNode.textContent = 'C’è stato un problema nell’invio. Riprova tra poco.'; } finally { submitButton.disabled = false; } });