{"id":240,"date":"2026-06-27T21:38:09","date_gmt":"2026-06-27T21:38:09","guid":{"rendered":"https:\/\/leclubleucate.fr\/accueil\/?page_id=240"},"modified":"2026-06-27T23:12:06","modified_gmt":"2026-06-27T23:12:06","slug":"reservation","status":"publish","type":"page","link":"https:\/\/leclubleucate.fr\/accueil\/reservation\/","title":{"rendered":"R\u00e9servation"},"content":{"rendered":"\n<!--\n  PAGE DE R\u00c9SERVATION \u2014 LE CLUB LEUCATE\n  ======================================\n  \u00c0 int\u00e9grer dans WordPress via un bloc \"HTML personnalis\u00e9\" (Custom HTML)\n  sur une nouvelle page (ex: leclubleucate.fr\/reservation).\n\n  Avant de publier : remplacez SUPABASE_URL et SUPABASE_ANON_KEY ci-dessous\n  par les m\u00eames valeurs que dans votre application de gestion.\n-->\n<div id=\"reservation-club-leucate\" style=\"max-width: 720px; margin: 0 auto; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; color: #0F2E3D;\">\n\n  <style>\n    #reservation-club-leucate * { box-sizing: border-box; }\n    #reservation-club-leucate input, #reservation-club-leucate select, #reservation-club-leucate textarea {\n      width: 100%; padding: 10px 12px; border-radius: 8px; border: 1px solid #D9D0BC;\n      font-size: 14px; font-family: inherit; margin-bottom: 14px;\n    }\n    #reservation-club-leucate label { font-size: 13px; font-weight: 600; color: #8A8275; display: block; margin-bottom: 4px; }\n    #reservation-club-leucate .rcl-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }\n    @media (max-width: 600px) { #reservation-club-leucate .rcl-row { grid-template-columns: 1fr; } }\n    #reservation-club-leucate .rcl-accordeon-item {\n      border: 1px solid #EAE3D3; border-radius: 10px; margin-bottom: 8px; overflow: hidden; background: #fff;\n    }\n    #reservation-club-leucate .rcl-accordeon-bouton {\n      width: 100%; display: flex; align-items: center; justify-content: space-between;\n      background: #FAF8F4; border: none; padding: 12px 14px; cursor: pointer; text-align: left;\n      font-weight: 700; color: #1B4965; font-size: 14px; font-family: inherit;\n    }\n    #reservation-club-leucate .rcl-accordeon-fleche { transition: transform 0.2s; font-size: 12px; color: #8A8275; }\n    #reservation-club-leucate .rcl-accordeon-item.rcl-ouvert .rcl-accordeon-fleche { transform: rotate(180deg); }\n    #reservation-club-leucate .rcl-accordeon-contenu {\n      max-height: 0; overflow: hidden; transition: max-height 0.25s ease;\n    }\n    #reservation-club-leucate .rcl-accordeon-item.rcl-ouvert .rcl-accordeon-contenu { max-height: 420px; }\n    #reservation-club-leucate .rcl-accordeon-desc { padding: 12px 14px; font-size: 13px; color: #5A5248; line-height: 1.5; }\n    #reservation-club-leucate .rcl-btn {\n      background: #1B4965; color: #fff; border: none; border-radius: 10px; padding: 13px 22px;\n      font-size: 15px; font-weight: 700; cursor: pointer; width: 100%;\n    }\n    #reservation-club-leucate .rcl-btn:disabled { background: #A8C0CC; cursor: default; }\n    #reservation-club-leucate .rcl-success {\n      background: #E1ECE6; color: #3A5C4F; padding: 16px; border-radius: 10px; text-align: center; font-weight: 600;\n    }\n    #reservation-club-leucate .rcl-error {\n      background: #FBE2DA; color: #A8432B; padding: 12px; border-radius: 8px; margin-bottom: 14px; font-size: 13px;\n    }\n    #reservation-club-leucate .rcl-dates-chip {\n      display: inline-flex; align-items: center; gap: 6px; background: #E3ECF1; color: #1B4965;\n      border-radius: 16px; padding: 5px 10px; font-size: 13px; font-weight: 600; margin: 3px;\n    }\n    #reservation-club-leucate .rcl-dates-chip button {\n      background: none; border: none; color: #1B4965; cursor: pointer; font-weight: 700; padding: 0;\n    }\n    #reservation-club-leucate .rcl-calendrier { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-bottom: 16px; }\n    @media (max-width: 600px) { #reservation-club-leucate .rcl-calendrier { grid-template-columns: 1fr; } }\n    #reservation-club-leucate .rcl-mois-titre { font-size: 13px; font-weight: 700; color: #0F2E3D; margin-bottom: 6px; text-align: center; }\n    #reservation-club-leucate .rcl-grille-jours { display: grid; grid-template-columns: repeat(6, 1fr); gap: 4px; font-size: 10px; color: #A8A096; text-align: center; font-weight: 600; margin-bottom: 4px; }\n    #reservation-club-leucate .rcl-grille { display: grid; grid-template-columns: repeat(6, 1fr); gap: 4px; }\n    #reservation-club-leucate .rcl-jour {\n      aspect-ratio: 1; border: none; border-radius: 6px; background: #F2EEE3; color: #8A8275;\n      font-size: 12px; font-weight: 600; cursor: pointer; display: flex; align-items: center; justify-content: center;\n    }\n    #reservation-club-leucate .rcl-jour.rcl-jour-vide { background: transparent; cursor: default; }\n    #reservation-club-leucate .rcl-jour.rcl-jour-selectionne { background: #1B4965; color: #fff; }\n  <\/style>\n\n  <h2 style=\"color: #1B4965; margin-bottom: 4px;\">R\u00e9server des cours de natation<\/h2>\n  <p style=\"color: #5A5248; font-size: 14px; margin-bottom: 24px;\">\n    Tous les matins de 9h30 \u00e0 13h30, \u00e0 Leucate. Remplissez ce formulaire, nous validons votre demande et revenons vers vous rapidement.\n  <\/p>\n\n  <h3 style=\"color: #1B4965; font-size: 16px; margin-bottom: 10px;\">Comment choisir le niveau de votre enfant ?<\/h3>\n  <div id=\"rcl-niveaux\">\n    <div class=\"rcl-accordeon-item\"><button type=\"button\" class=\"rcl-accordeon-bouton\">D\u00e9butant 1, 2 et 3 <span class=\"rcl-accordeon-fleche\">\u25bc<\/span><\/button><div class=\"rcl-accordeon-contenu\"><div class=\"rcl-accordeon-desc\"><strong>D\u00e9butant 1<\/strong> : votre enfant ne sait pas nager mais accepte d&rsquo;immerger sa t\u00eate sous l&rsquo;eau facilement. Objectif : propulsion de jambes et \u00e9toile de mer.<br><br><strong>D\u00e9butant 2<\/strong> : votre enfant accepte de mettre la t\u00eate sous l&rsquo;eau et sait se propulser sous l&rsquo;eau, mais ne nage pas encore seul. Objectif : encha\u00eenement de plusieurs brasses compl\u00e8tes.<br><br><strong>D\u00e9butant 3<\/strong> : votre enfant nage quelques brasses seul, sans technique, l\u00e0 o\u00f9 il a pied. Objectif : dipl\u00f4me du petit poisson (15m de brasse, t\u00eate hors de l&rsquo;eau, avec passage sous l&rsquo;eau).<\/div><\/div><\/div>\n    <div class=\"rcl-accordeon-item\"><button type=\"button\" class=\"rcl-accordeon-bouton\">Interm\u00e9diaire 1 et 2 <span class=\"rcl-accordeon-fleche\">\u25bc<\/span><\/button><div class=\"rcl-accordeon-contenu\"><div class=\"rcl-accordeon-desc\">Votre enfant nage 15 \u00e0 20m seul (technique \u00e0 affiner), et en Interm\u00e9diaire 2 il nage sans avoir pied, t\u00eate hors de l&rsquo;eau. Objectif : dipl\u00f4mes des 25m et 50m brasse.<\/div><\/div><\/div>\n    <div class=\"rcl-accordeon-item\"><button type=\"button\" class=\"rcl-accordeon-bouton\">Brasse coul\u00e9e 1 et 2 <span class=\"rcl-accordeon-fleche\">\u25bc<\/span><\/button><div class=\"rcl-accordeon-contenu\"><div class=\"rcl-accordeon-desc\">Votre enfant ma\u00eetrise la brasse et travaille la respiration et la coul\u00e9e. Objectif BC 1 : dipl\u00f4me des 50m. Objectif BC 2 : dipl\u00f4me des 100m.<\/div><\/div><\/div>\n    <div class=\"rcl-accordeon-item\"><button type=\"button\" class=\"rcl-accordeon-bouton\">Crawl 1, 2 et 3 <span class=\"rcl-accordeon-fleche\">\u25bc<\/span><\/button><div class=\"rcl-accordeon-contenu\"><div class=\"rcl-accordeon-desc\">Votre enfant apprend ou perfectionne le crawl.<br><br><strong>Crawl 1<\/strong> : objectif dipl\u00f4me des 50m.<br><strong>Crawl 2<\/strong> : objectif dipl\u00f4me des 100m.<br><strong>Crawl 3<\/strong> : objectif dipl\u00f4me des 400m.<\/div><\/div><\/div>\n    <div class=\"rcl-accordeon-item\"><button type=\"button\" class=\"rcl-accordeon-bouton\">Dos crawl\u00e9 1 et 2 <span class=\"rcl-accordeon-fleche\">\u25bc<\/span><\/button><div class=\"rcl-accordeon-contenu\"><div class=\"rcl-accordeon-desc\">Apprentissage du dos crawl\u00e9.<br><br><strong>DC 1<\/strong> : objectif dipl\u00f4me des 50m.<br><strong>DC 2<\/strong> : objectif dipl\u00f4me des 100m.<\/div><\/div><\/div>\n    <div class=\"rcl-accordeon-item\"><button type=\"button\" class=\"rcl-accordeon-bouton\">Papillon <span class=\"rcl-accordeon-fleche\">\u25bc<\/span><\/button><div class=\"rcl-accordeon-contenu\"><div class=\"rcl-accordeon-desc\">Nageur confirm\u00e9 qui apprend le papillon.<br><br>Objectifs dipl\u00f4mes des 50m, puis des 100m.<\/div><\/div><\/div>\n    <div class=\"rcl-accordeon-item\"><button type=\"button\" class=\"rcl-accordeon-bouton\">Perfectionnement triathlon \/ swimrun <span class=\"rcl-accordeon-fleche\">\u25bc<\/span><\/button><div class=\"rcl-accordeon-contenu\"><div class=\"rcl-accordeon-desc\">Pour les nageurs confirm\u00e9s qui souhaitent se perfectionner en eau libre : navigation vers la bou\u00e9e, gestion des vagues, gestion de la propulsion en groupe (drafting), et adaptation de la nage aux conditions r\u00e9elles de course.<\/div><\/div><\/div>\n    <div class=\"rcl-accordeon-item\"><button type=\"button\" class=\"rcl-accordeon-bouton\">Cours particulier <span class=\"rcl-accordeon-fleche\">\u25bc<\/span><\/button><div class=\"rcl-accordeon-contenu\"><div class=\"rcl-accordeon-desc\">Suivi individuel, tous niveaux. Id\u00e9al pour progresser plus rapidement ou pour un besoin sp\u00e9cifique.<\/div><\/div><\/div>\n  <\/div>\n\n  <h3 style=\"color: #1B4965; font-size: 16px; margin: 24px 0 14px;\">Vos informations<\/h3>\n\n  <div id=\"rcl-formulaire\">\n    <div class=\"rcl-error\" id=\"rcl-error\" style=\"display: none;\"><\/div>\n\n    <div class=\"rcl-row\">\n      <div><label>Nom de l&rsquo;enfant *<\/label><input type=\"text\" id=\"rcl-nom\" required><\/div>\n      <div>\n        <label>Pr\u00e9nom de l&rsquo;enfant *<\/label>\n        <input type=\"text\" id=\"rcl-prenom\" required placeholder=\"Pr\u00e9nom du nageur, pas le v\u00f4tre\">\n        <p style=\"font-size: 12px; color: #1B4965; margin: -10px 0 14px; font-weight: 600;\">\u26a0\ufe0f Merci d&rsquo;indiquer le pr\u00e9nom de l&rsquo;enfant qui nagera, pas le v\u00f4tre.<\/p>\n      <\/div>\n    <\/div>\n\n    <label>Date de naissance de l&rsquo;enfant *<\/label>\n    <input type=\"date\" id=\"rcl-naissance\" required>\n\n    <label>Niveau pressenti<\/label>\n    <select id=\"rcl-niveau\">\n      <option value=\"\">\u2014 Je ne sais pas, \u00e0 \u00e9valuer \u2014<\/option>\n      <option value=\"D\u00e9b 1\">D\u00e9butant 1<\/option>\n      <option value=\"D\u00e9b 2\">D\u00e9butant 2<\/option>\n      <option value=\"D\u00e9b 3\">D\u00e9butant 3<\/option>\n      <option value=\"Inter 1\">Interm\u00e9diaire 1<\/option>\n      <option value=\"Inter 2\">Interm\u00e9diaire 2<\/option>\n      <option value=\"BC 1\">Brasse coul\u00e9e 1<\/option>\n      <option value=\"BC 2\">Brasse coul\u00e9e 2<\/option>\n      <option value=\"Crawl 1\">Crawl 1<\/option>\n      <option value=\"Crawl 2\">Crawl 2<\/option>\n      <option value=\"Crawl 3\">Crawl 3<\/option>\n      <option value=\"DC 1\">Dos crawl\u00e9 1<\/option>\n      <option value=\"DC 2\">Dos crawl\u00e9 2<\/option>\n      <option value=\"Papillon\">Papillon<\/option>\n      <option value=\"Triathlon\/Swimrun\">Perfectionnement triathlon \/ swimrun<\/option>\n      <option value=\"Cours particulier\">Cours particulier<\/option>\n    <\/select>\n\n    <label>Dates de cours souhait\u00e9es<\/label>\n    <p style=\"font-size: 12.5px; color: #8A8275; margin: -8px 0 10px;\">Cliquez sur les jours souhait\u00e9s (le club est ferm\u00e9 le samedi).<\/p>\n    <div class=\"rcl-calendrier\" id=\"rcl-calendrier\"><\/div>\n    <div id=\"rcl-dates-liste\" style=\"margin-bottom: 14px;\"><\/div>\n\n    <div id=\"rcl-estimation\" style=\"display:none; background:#E3ECF1; border-radius:10px; padding:14px 16px; margin-bottom:18px;\">\n      <div style=\"font-size:13px; color:#1B4965; font-weight:700; margin-bottom:6px;\">Estimation tarifaire<\/div>\n      <div id=\"rcl-estimation-detail\" style=\"font-size:13px; color:#0F2E3D; line-height:1.6;\"><\/div>\n      <div style=\"display:flex; justify-content:space-between; align-items:center; margin-top:10px; padding-top:10px; border-top:1px solid #C9D6DE;\">\n        <span style=\"font-size:14px; font-weight:700; color:#1B4965;\">Total estim\u00e9<\/span>\n        <span id=\"rcl-estimation-total\" style=\"font-size:18px; font-weight:700; color:#1B4965;\"><\/span>\n      <\/div>\n      <p style=\"font-size:11.5px; color:#5A7384; margin:8px 0 0;\">Cette estimation est indicative ; le montant d\u00e9finitif sera confirm\u00e9 apr\u00e8s validation de votre demande.<\/p>\n    <\/div>\n\n    <div class=\"rcl-row\">\n      <div><label>Votre nom (contact) *<\/label><input type=\"text\" id=\"rcl-contact\" required><\/div>\n      <div><label>Votre t\u00e9l\u00e9phone *<\/label><input type=\"tel\" id=\"rcl-tel\" required><\/div>\n    <\/div>\n\n    <label>Votre e-mail *<\/label>\n    <input type=\"email\" id=\"rcl-mail\" required>\n\n    <label>Message (optionnel)<\/label>\n    <textarea id=\"rcl-message\" rows=\"3\"><\/textarea>\n\n    <button class=\"rcl-btn\" id=\"rcl-submit\">Envoyer ma demande de r\u00e9servation<\/button>\n  <\/div>\n\n  <div class=\"rcl-success\" id=\"rcl-success\" style=\"display: none;\">\n    Merci ! Votre demande a bien \u00e9t\u00e9 envoy\u00e9e. Nous revenons vers vous rapidement pour la confirmer.\n  <\/div>\n\n<\/div>\n\n<script>\n(function () {\n  const SUPABASE_URL = 'https:\/\/gtdpvgjedugdzgfbxtjq.supabase.co';\n  const SUPABASE_ANON_KEY = 'sb_publishable_i9R-9zK7n8e8GcU9oZINgA_e99Q5dR1';\n\n  let datesChoisies = [];\n  const anneeCourante = new Date().getFullYear();\n  const MOIS_CALENDRIER = [\n    { label: 'Juillet ' + anneeCourante, year: anneeCourante, month: 6, days: 31 },\n    { label: 'Ao\u00fbt ' + anneeCourante, year: anneeCourante, month: 7, days: 31 },\n  ];\n\n  function isoDate(year, month, day) {\n    const m = String(month + 1).padStart(2, '0');\n    const d = String(day).padStart(2, '0');\n    return year + '-' + m + '-' + d;\n  }\n\n  function rafraichirListeDates() {\n    const liste = document.getElementById('rcl-dates-liste');\n    liste.innerHTML = '';\n    datesChoisies.forEach((d, i) => {\n      const chip = document.createElement('span');\n      chip.className = 'rcl-dates-chip';\n      const [y, m, day] = d.split('-');\n      chip.innerHTML = day + '\/' + m + '\/' + y + ' <button type=\"button\" data-i=\"' + i + '\">\u2715<\/button>';\n      liste.appendChild(chip);\n    });\n    liste.querySelectorAll('button').forEach(btn => {\n      btn.addEventListener('click', () => {\n        datesChoisies.splice(parseInt(btn.dataset.i, 10), 1);\n        rafraichirListeDates();\n        genererCalendrier();\n      });\n    });\n  }\n\n  function toggleDate(iso) {\n    const idx = datesChoisies.indexOf(iso);\n    if (idx === -1) {\n      datesChoisies.push(iso);\n      datesChoisies.sort();\n    } else {\n      datesChoisies.splice(idx, 1);\n    }\n    rafraichirListeDates();\n    genererCalendrier();\n    calculerEstimation();\n  }\n\n  const TARIF_ENFANT = 20, TARIF_ENFANT_VIP = 17;\n  const TARIF_ADULTE = 30, TARIF_ADULTE_VIP = 25; \/\/ s'applique aussi \u00e0 \"Cours particulier\"\n  const TARIF_TRIATHLON = 35, TARIF_TRIATHLON_VIP = 30;\n  const TARIF_CARTE_VIP = 15;\n  const AGE_ADULTE = 16;\n\n  function calculerAge(dateNaissance) {\n    const naissance = new Date(dateNaissance);\n    const aujourdHui = new Date();\n    let age = aujourdHui.getFullYear() - naissance.getFullYear();\n    const moisPasse = aujourdHui.getMonth() - naissance.getMonth();\n    if (moisPasse < 0) {\n      age--;\n    } else if (moisPasse === 0) {\n      if (aujourdHui.getDate() < naissance.getDate()) age--;\n    }\n    return age;\n  }\n\n  function calculerEstimation() {\n    const bloc = document.getElementById('rcl-estimation');\n    const nbSeances = datesChoisies.length;\n    const dateNaissance = document.getElementById('rcl-naissance').value;\n    const niveau = document.getElementById('rcl-niveau').value;\n\n    if (nbSeances === 0 || !dateNaissance) {\n      bloc.style.display = 'none';\n      return;\n    }\n\n    const age = calculerAge(dateNaissance);\n\n    if (age < 4) {\n      bloc.style.display = 'block';\n      bloc.style.background = '#FBE2DA';\n      document.getElementById('rcl-estimation-detail').innerHTML =\n        '<span style=\"color:#A8432B; font-weight:600;\">Les cours de natation ne sont malheureusement pas accessibles aux enfants de moins de 4 ans.<\/span>';\n      document.getElementById('rcl-estimation-total').textContent = '';\n      return;\n    }\n    bloc.style.background = '#E3ECF1';\n\n    let tarifNormal, tarifVip;\n    if (niveau === 'Triathlon\/Swimrun') {\n      tarifNormal = TARIF_TRIATHLON;\n      tarifVip = TARIF_TRIATHLON_VIP;\n    } else if (niveau === 'Cours particulier' || age >= AGE_ADULTE) {\n      tarifNormal = TARIF_ADULTE;\n      tarifVip = TARIF_ADULTE_VIP;\n    } else {\n      tarifNormal = TARIF_ENFANT;\n      tarifVip = TARIF_ENFANT_VIP;\n    }\n\n    const totalSansVip = nbSeances * tarifNormal;\n    const totalAvecVip = nbSeances * tarifVip + TARIF_CARTE_VIP;\n    const vipAvantageuse = totalAvecVip < totalSansVip;\n\n    const detail = document.getElementById('rcl-estimation-detail');\n    const totalSpan = document.getElementById('rcl-estimation-total');\n\n    if (vipAvantageuse) {\n      const economie = totalSansVip - totalAvecVip;\n      const pluriel = nbSeances > 1 ? 's' : '';\n      detail.innerHTML =\n        nbSeances + ' s\u00e9ance' + pluriel + ' \u00d7 ' + tarifVip + '\u20ac (tarif carte VIP) = ' + (nbSeances * tarifVip).toFixed(0) + '\u20ac<br>' +\n        '+ Carte club VIP : ' + TARIF_CARTE_VIP + '\u20ac<br>' +\n        '<span style=\"color:#3A7D5C; font-weight:600;\">La carte VIP vous fait \u00e9conomiser ' + economie.toFixed(0) + '\u20ac sur ce nombre de s\u00e9ances \u2014 elle est automatiquement incluse dans cette estimation.<\/span>';\n      totalSpan.textContent = totalAvecVip.toFixed(0) + ' \u20ac';\n    } else {\n      const pluriel = nbSeances > 1 ? 's' : '';\n      detail.innerHTML = nbSeances + ' s\u00e9ance' + pluriel + ' \u00d7 ' + tarifNormal + '\u20ac = ' + totalSansVip.toFixed(0) + '\u20ac';\n      totalSpan.textContent = totalSansVip.toFixed(0) + ' \u20ac';\n    }\n\n    bloc.style.display = 'block';\n  }\n\n  function construireMessageAvecEstimation() {\n    const messageLibre = document.getElementById('rcl-message').value.trim();\n    const totalSpan = document.getElementById('rcl-estimation-total');\n    let estimationTexte = '';\n    if (totalSpan) {\n      if (totalSpan.textContent) {\n        estimationTexte = 'Estimation tarifaire indicative calcul\u00e9e par le formulaire : ' + totalSpan.textContent + '.';\n      }\n    }\n    const saut = String.fromCharCode(10) + String.fromCharCode(10);\n    return [messageLibre, estimationTexte].filter(Boolean).join(saut) || null;\n  }\n\n  document.getElementById('rcl-naissance').addEventListener('change', calculerEstimation);\n  document.getElementById('rcl-niveau').addEventListener('change', calculerEstimation);\n\n  function genererCalendrier() {\n    const conteneur = document.getElementById('rcl-calendrier');\n    conteneur.innerHTML = '';\n    MOIS_CALENDRIER.forEach(mois => {\n      const bloc = document.createElement('div');\n      const titre = document.createElement('div');\n      titre.className = 'rcl-mois-titre';\n      titre.textContent = mois.label;\n      bloc.appendChild(titre);\n\n      const enTetes = document.createElement('div');\n      enTetes.className = 'rcl-grille-jours';\n      ['L', 'M', 'M', 'J', 'V', 'D'].forEach(j => {\n        const span = document.createElement('span');\n        span.textContent = j;\n        enTetes.appendChild(span);\n      });\n      bloc.appendChild(enTetes);\n\n      const grille = document.createElement('div');\n      grille.className = 'rcl-grille';\n\n      \/\/ Grille \u00e0 6 colonnes : Lundi, Mardi, Mercredi, Jeudi, Vendredi, Dimanche (le samedi n'a pas de colonne).\n      \/\/ On calcule directement, pour chaque jour du mois, sa position dans cette grille \u00e0 6 colonnes,\n      \/\/ en ignorant simplement les samedis (aucune case g\u00e9n\u00e9r\u00e9e pour eux, comme demand\u00e9).\n      let colonne = null;\n      for (let jour = 1; jour <= mois.days; jour++) {\n        const dateObj = new Date(mois.year, mois.month, jour);\n        const jourSemaine = dateObj.getDay(); \/\/ 0=dimanche, 1=lundi, ..., 6=samedi\n        if (jourSemaine === 6) continue; \/\/ samedi : aucune case, on saute au jour suivant\n\n        \/\/ Position dans la grille \u00e0 6 colonnes : lundi=0, mardi=1, mercredi=2, jeudi=3, vendredi=4, dimanche=5\n        const positionColonne = jourSemaine === 0 ? 5 : jourSemaine - 1;\n\n        if (colonne === null) {\n          \/\/ Premi\u00e8re case r\u00e9elle du mois : on ajoute les cases vides n\u00e9cessaires avant elle\n          for (let i = 0; i < positionColonne; i++) {\n            const vide = document.createElement('div');\n            vide.className = 'rcl-jour rcl-jour-vide';\n            grille.appendChild(vide);\n          }\n        }\n        colonne = positionColonne;\n\n        const iso = isoDate(mois.year, mois.month, jour);\n        const btn = document.createElement('button');\n        btn.type = 'button';\n        btn.className = 'rcl-jour' + (datesChoisies.includes(iso) ? ' rcl-jour-selectionne' : '');\n        btn.textContent = jour;\n        btn.addEventListener('click', () => toggleDate(iso));\n        grille.appendChild(btn);\n      }\n\n      bloc.appendChild(grille);\n      conteneur.appendChild(bloc);\n    });\n  }\n\n  genererCalendrier();\n\n  \/\/ \u00c2ge minimum obligatoire de 4 ans : on limite directement la date s\u00e9lectionnable\n  \/\/ dans le calendrier du navigateur, pour qu'une date trop r\u00e9cente ne soit pas m\u00eame proposable.\n  (function limiterDateNaissance() {\n    const aujourdHui = new Date();\n    const limite = new Date(aujourdHui.getFullYear() - 4, aujourdHui.getMonth(), aujourdHui.getDate());\n    const annee = limite.getFullYear();\n    const mois = String(limite.getMonth() + 1).padStart(2, '0');\n    const jour = String(limite.getDate()).padStart(2, '0');\n    document.getElementById('rcl-naissance').setAttribute('max', annee + '-' + mois + '-' + jour);\n  })();\n\n  \/\/ Accord\u00e9on des niveaux : un seul niveau ouvert \u00e0 la fois, pour garder la page compacte.\n  document.querySelectorAll('#rcl-niveaux .rcl-accordeon-bouton').forEach(btn => {\n    btn.addEventListener('click', () => {\n      const item = btn.closest('.rcl-accordeon-item');\n      const etaitOuvert = item.classList.contains('rcl-ouvert');\n      document.querySelectorAll('#rcl-niveaux .rcl-accordeon-item').forEach(i => i.classList.remove('rcl-ouvert'));\n      if (!etaitOuvert) item.classList.add('rcl-ouvert');\n    });\n  });\n\n  document.getElementById('rcl-submit').addEventListener('click', async () => {\n    const nom = document.getElementById('rcl-nom').value.trim();\n    const prenom = document.getElementById('rcl-prenom').value.trim();\n    const dateNaissance = document.getElementById('rcl-naissance').value;\n    const contact = document.getElementById('rcl-contact').value.trim();\n    const tel = document.getElementById('rcl-tel').value.trim();\n    const mail = document.getElementById('rcl-mail').value.trim();\n    const errorBox = document.getElementById('rcl-error');\n\n    if (!nom || !prenom || !dateNaissance || !contact || !tel || !mail) {\n      errorBox.textContent = 'Merci de remplir tous les champs obligatoires (marqu\u00e9s *).';\n      errorBox.style.display = 'block';\n      return;\n    }\n\n    if (calculerAge(dateNaissance) < 4) {\n      errorBox.textContent = 'Les cours de natation ne sont malheureusement pas accessibles aux enfants de moins de 4 ans.';\n      errorBox.style.display = 'block';\n      return;\n    }\n\n    errorBox.style.display = 'none';\n\n    const submitBtn = document.getElementById('rcl-submit');\n    submitBtn.disabled = true;\n    submitBtn.textContent = 'Envoi en cours\u2026';\n\n    try {\n      const res = await fetch(SUPABASE_URL + '\/functions\/v1\/demande-reservation', {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application\/json',\n          Authorization: 'Bearer ' + SUPABASE_ANON_KEY,\n        },\n        body: JSON.stringify({\n          nom, prenom,\n          dateNaissance: dateNaissance,\n          contact, tel, mail,\n          datesSouhaitees: datesChoisies,\n          niveauPressenti: document.getElementById('rcl-niveau').value || null,\n          message: construireMessageAvecEstimation(),\n        }),\n      });\n      const data = await res.json();\n      if (!res.ok || data.error) {\n        errorBox.textContent = data.error || 'Une erreur est survenue, merci de r\u00e9essayer.';\n        errorBox.style.display = 'block';\n        submitBtn.disabled = false;\n        submitBtn.textContent = 'Envoyer ma demande de r\u00e9servation';\n        return;\n      }\n      document.getElementById('rcl-formulaire').style.display = 'none';\n      document.getElementById('rcl-success').style.display = 'block';\n    } catch (err) {\n      errorBox.textContent = 'Une erreur r\u00e9seau est survenue, merci de r\u00e9essayer.';\n      errorBox.style.display = 'block';\n      submitBtn.disabled = false;\n      submitBtn.textContent = 'Envoyer ma demande de r\u00e9servation';\n    }\n  });\n})();\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>R\u00e9server des cours de natation Tous les matins de 9h30 \u00e0 13h30, \u00e0 Leucate. Remplissez ce formulaire, nous validons votre<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-240","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.9 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>R\u00e9servation - Le Club Leucate<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/leclubleucate.fr\/accueil\/reservation\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"R\u00e9servation - Le Club Leucate\" \/>\n<meta property=\"og:description\" content=\"R\u00e9server des cours de natation Tous les matins de 9h30 \u00e0 13h30, \u00e0 Leucate. Remplissez ce formulaire, nous validons votre\" \/>\n<meta property=\"og:url\" content=\"https:\/\/leclubleucate.fr\/accueil\/reservation\/\" \/>\n<meta property=\"og:site_name\" content=\"Le Club Leucate\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/lesdauphinsdeleucate\/\" \/>\n<meta property=\"article:modified_time\" content=\"2026-06-27T23:12:06+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/leclubleucate.fr\/wp-content\/uploads\/2025\/05\/LE-CLUB.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1563\" \/>\n\t<meta property=\"og:image:height\" content=\"1563\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data1\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/reservation\\\/\",\"url\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/reservation\\\/\",\"name\":\"R\u00e9servation - Le Club Leucate\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/#website\"},\"datePublished\":\"2026-06-27T21:38:09+00:00\",\"dateModified\":\"2026-06-27T23:12:06+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/reservation\\\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/reservation\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/reservation\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"R\u00e9servation\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/#website\",\"url\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/\",\"name\":\"Le Club Leucate\",\"description\":\"Club de plage et de natation\",\"publisher\":{\"@id\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/#organization\",\"name\":\"Le Club Leucate\",\"url\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/leclubleucate.fr\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/LE-CLUB.png\",\"contentUrl\":\"https:\\\/\\\/leclubleucate.fr\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/LE-CLUB.png\",\"width\":1563,\"height\":1563,\"caption\":\"Le Club Leucate\"},\"image\":{\"@id\":\"https:\\\/\\\/leclubleucate.fr\\\/accueil\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/lesdauphinsdeleucate\\\/\",\"https:\\\/\\\/www.instagram.com\\\/le_club_leucate?igsh=bzRoeTVsbzY5cXlo\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"R\u00e9servation - Le Club Leucate","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/leclubleucate.fr\/accueil\/reservation\/","og_locale":"fr_FR","og_type":"article","og_title":"R\u00e9servation - Le Club Leucate","og_description":"R\u00e9server des cours de natation Tous les matins de 9h30 \u00e0 13h30, \u00e0 Leucate. Remplissez ce formulaire, nous validons votre","og_url":"https:\/\/leclubleucate.fr\/accueil\/reservation\/","og_site_name":"Le Club Leucate","article_publisher":"https:\/\/www.facebook.com\/lesdauphinsdeleucate\/","article_modified_time":"2026-06-27T23:12:06+00:00","og_image":[{"width":1563,"height":1563,"url":"https:\/\/leclubleucate.fr\/wp-content\/uploads\/2025\/05\/LE-CLUB.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_misc":{"Dur\u00e9e de lecture estim\u00e9e":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/leclubleucate.fr\/accueil\/reservation\/","url":"https:\/\/leclubleucate.fr\/accueil\/reservation\/","name":"R\u00e9servation - Le Club Leucate","isPartOf":{"@id":"https:\/\/leclubleucate.fr\/accueil\/#website"},"datePublished":"2026-06-27T21:38:09+00:00","dateModified":"2026-06-27T23:12:06+00:00","breadcrumb":{"@id":"https:\/\/leclubleucate.fr\/accueil\/reservation\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/leclubleucate.fr\/accueil\/reservation\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/leclubleucate.fr\/accueil\/reservation\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/leclubleucate.fr\/accueil\/"},{"@type":"ListItem","position":2,"name":"R\u00e9servation"}]},{"@type":"WebSite","@id":"https:\/\/leclubleucate.fr\/accueil\/#website","url":"https:\/\/leclubleucate.fr\/accueil\/","name":"Le Club Leucate","description":"Club de plage et de natation","publisher":{"@id":"https:\/\/leclubleucate.fr\/accueil\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/leclubleucate.fr\/accueil\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-FR"},{"@type":"Organization","@id":"https:\/\/leclubleucate.fr\/accueil\/#organization","name":"Le Club Leucate","url":"https:\/\/leclubleucate.fr\/accueil\/","logo":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/leclubleucate.fr\/accueil\/#\/schema\/logo\/image\/","url":"https:\/\/leclubleucate.fr\/wp-content\/uploads\/2025\/05\/LE-CLUB.png","contentUrl":"https:\/\/leclubleucate.fr\/wp-content\/uploads\/2025\/05\/LE-CLUB.png","width":1563,"height":1563,"caption":"Le Club Leucate"},"image":{"@id":"https:\/\/leclubleucate.fr\/accueil\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/lesdauphinsdeleucate\/","https:\/\/www.instagram.com\/le_club_leucate?igsh=bzRoeTVsbzY5cXlo"]}]}},"_links":{"self":[{"href":"https:\/\/leclubleucate.fr\/accueil\/wp-json\/wp\/v2\/pages\/240","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/leclubleucate.fr\/accueil\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/leclubleucate.fr\/accueil\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/leclubleucate.fr\/accueil\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/leclubleucate.fr\/accueil\/wp-json\/wp\/v2\/comments?post=240"}],"version-history":[{"count":5,"href":"https:\/\/leclubleucate.fr\/accueil\/wp-json\/wp\/v2\/pages\/240\/revisions"}],"predecessor-version":[{"id":274,"href":"https:\/\/leclubleucate.fr\/accueil\/wp-json\/wp\/v2\/pages\/240\/revisions\/274"}],"wp:attachment":[{"href":"https:\/\/leclubleucate.fr\/accueil\/wp-json\/wp\/v2\/media?parent=240"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}