// ===================================================================== // Art&Suites — Liste d'attente · logique du formulaire (React) // ===================================================================== // // WEBHOOK MAKE — module « Custom webhook » du scénario. // Le formulaire POSTe le payload JSON ci-dessous à cette adresse. // const WEBHOOK_URL = "https://hook.eu2.make.com/3ordu80g2n0dth071bhpkttkez6qqlkt"; // --------------------------------------------------------------------- // Suites // --------------------------------------------------------------------- const SUITES = [ { id: "sarah", caption: { fr: "Belle Époque Narbonne", en: "Belle Époque Narbonne", es: "Belle Époque Narbonne" }, name: "Sarah Bernhardt", meta: { fr: "80 m² · 1 à 6 pers.", en: "80 m² · 1–6 guests", es: "80 m² · 1 a 6 huésp." }, price: 80, swatch: "linear-gradient(150deg, #E2B791 0%, #C99873 55%, #8C6240 100%)", image: "assets/suite-sarah.webp", }, { id: "frida", caption: { fr: "Casa Azul Narbonne", en: "Casa Azul Narbonne", es: "Casa Azul Narbonne" }, name: "Frida Kahlo", meta: { fr: "42 m² · 1 à 4 pers.", en: "42 m² · 1–4 guests", es: "42 m² · 1 a 4 huésp." }, price: 75, swatch: "linear-gradient(150deg, #F5BFB4 0%, #F51549 60%, #8E0A29 100%)", image: "assets/suite-frida.webp", }, { id: "boheme", caption: { fr: "Portanelle Millénaire Gaillac", en: "Portanelle Millénaire Gaillac", es: "Portanelle Millénaire Gaillac" }, name: "La Bohème Saint Michel", meta: { fr: "75 m² · 1 à 5 pers.", en: "75 m² · 1–5 guests", es: "75 m² · 1 a 5 huésp." }, price: 70, swatch: "linear-gradient(150deg, #FCF2E6 0%, #E2B791 65%, #886040 100%)", image: "assets/suite-boheme.webp", }, ]; // --------------------------------------------------------------------- // i18n // --------------------------------------------------------------------- const T = { fr: { nav: "Les suites", eyebrow: "Liste d'attente", title: "Si une suite se libère, vous le saurez avant tout le monde !", lead: "Vos dates sont déjà complètes ?\nDès qu'une suite correspondant à vos attentes se libère, nous vous écrivons, souvent avant qu'elle ne reparaisse en ligne.", suiteQ: "La suite qui vous fait rêver", suiteHelp: "", perNight: "/ nuit", name: "Nom complet", namePh: "Camille Laurent", email: "Adresse e-mail", emailPh: "camille@exemple.fr", mobile: "Téléphone mobile", mobilePh: "06 12 34 56 78", mobileHelp: "Pour vous joindre vite si la suite se libère.", periodQ: "Période souhaitée", checkin: "Arrivée", checkout: "Départ", guests: "Nombre de personnes", guestUnit: ["personne", "personnes"], guestPlus: "6 personnes ou plus", rgpd: "J'accepte qu'Art\u0026Suites conserve mes coordonnées afin de me prévenir d'une disponibilité. Elles ne seront ni revendues, ni utilisées à d'autres fins.", submit: "Rejoindre la liste", sending: "Envoi…", reassure: "Sans engagement · Vous pouvez nous demander de vous retirer de la liste à tout moment.", errReq: "Ce champ est requis.", errEmail: "Cette adresse e-mail semble incomplète.", errSuite: "Choisissez une suite.", errConsent: "Merci de cocher cette case pour continuer.", errDates: "Le départ doit être après l'arrivée.", }, en: { nav: "The suites", eyebrow: "Waitlist", title: "When a suite opens up, you'll be the first to know.", lead: "Are your dates already booked? Leave us a few words. The moment a suite matching your stay frees up, we write to you — often before it reappears online.", suiteQ: "The suite you're dreaming of", suiteHelp: "", perNight: "/ night", name: "Full name", namePh: "Camille Laurent", email: "Email address", emailPh: "camille@example.com", mobile: "Mobile phone", mobilePh: "+33 6 12 34 56 78", mobileHelp: "So we can reach you quickly if it opens up.", periodQ: "Preferred dates", checkin: "Check-in", checkout: "Check-out", guests: "Number of guests", guestUnit: ["guest", "guests"], guestPlus: "6 guests or more", rgpd: "I agree that Art\u0026Suites may keep my details to notify me of availability. They will never be sold or used for any other purpose.", submit: "Join the list", sending: "Sending…", reassure: "No commitment · You can ask to be removed from the list at any time.", errReq: "This field is required.", errEmail: "This email address looks incomplete.", errSuite: "Please choose a suite.", errConsent: "Please tick this box to continue.", errDates: "Check-out must be after check-in.", }, es: { nav: "Las suites", eyebrow: "Lista de espera", title: "Cuando una suite se libere, será el primero en saberlo.", lead: "¿Sus fechas ya están completas? Déjenos unas palabras. En cuanto se libere una suite para su estancia, le escribimos — a menudo antes de que vuelva a aparecer en línea.", suiteQ: "La suite que le seduce", suiteHelp: "", perNight: "/ noche", name: "Nombre completo", namePh: "Camille Laurent", email: "Correo electrónico", emailPh: "camille@ejemplo.com", mobile: "Teléfono móvil", mobilePh: "+34 612 34 56 78", mobileHelp: "Para localizarle rápido si se libera.", periodQ: "Fechas deseadas", checkin: "Llegada", checkout: "Salida", guests: "Número de personas", guestUnit: ["persona", "personas"], guestPlus: "6 personas o más", rgpd: "Acepto que Art\u0026Suites conserve mis datos para avisarme de la disponibilidad. No serán vendidos ni usados para otros fines.", submit: "Unirse a la lista", sending: "Enviando…", reassure: "Sin compromiso · Puede pedir que le retiremos de la lista en cualquier momento.", errReq: "Este campo es obligatorio.", errEmail: "Este correo parece incompleto.", errSuite: "Elija una suite.", errConsent: "Marque esta casilla para continuar.", errDates: "La salida debe ser posterior a la llegada.", }, }; const LANGS = [["fr", "FR"], ["en", "EN"], ["es", "ES"]]; // --------------------------------------------------------------------- // Small pieces // --------------------------------------------------------------------- function CheckIcon({ stroke }) { return ( ); } function Field({ label, help, error, children, htmlFor }) { return (