templates/Parent/DetailsSejour.html.twig line 1

Open in your IDE?
  1. {% extends "Parent/LayoutParent.html.twig" %} {% block LinksCss %}
  2. {{ parent() }}
  3. <script src="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.js"></script>
  4. <link rel="stylesheet" href="{{ '/css/Parent/css/premiercnx.css' }}" />
  5. <link href="{{ asset('css/Parent/css/detailsejour.css') }}" type="text/css" rel="stylesheet" />
  6. <link rel="stylesheet" href="{{ '/css/Accompagnateur/imgzoom.css' }}" />
  7. <link rel="stylesheet" href="{{ asset('Plugins/css/dropzone.css') }}" />
  8. <link rel="stylesheet" href="{{ asset('css/splide.min.css') }}" />
  9. <link rel="stylesheet" href="{{ asset('css/favorites-sidebar.css') }}" />
  10. {% set destination = "detailsejour" %}
  11. <style>
  12. .btn-cmdFav {
  13.   background-color: #F56040;
  14.   color: white;
  15.   padding: 10px 20px;
  16.   border-radius: 6px;
  17.   font-size: 1rem;
  18.   box-shadow: 0 4px 8px rgba(0,0,0,0.15);
  19.   transition: all 0.3s ease;
  20. }
  21. .btn-cmdFav:hover {
  22.   background-color: #e64a30;
  23.   transform: scale(1.05);
  24.   box-shadow: 0 6px 12px rgba(0,0,0,0.2);
  25. }
  26. .filter-badge {
  27.   background-color: #ccc;
  28.   color: white;
  29.   font-size: 12px;
  30.   padding: 2px 10px;
  31.   border-radius: 20px;
  32.   display: flex;
  33.   align-items: center;
  34.   cursor: pointer;
  35.   transition: all 0.3s ease;
  36. }
  37. .filter-badge:hover {
  38.   background-color: #aaa;
  39. }
  40. /* Quand le filtre est actif */
  41. .filter-badge.active {
  42.   background-color: #3BA39B; /* Vert plus vif */
  43.   box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
  44.   font-weight: bold;
  45.   color: white;
  46. }
  47.   .close-btn-purchase {
  48.     position: absolute;
  49.     padding: 2px;
  50.     top: 10px;
  51.     right: 10px;
  52.     background: none;
  53.     border: none;
  54.     font-size: 35px;
  55.     cursor: pointer;
  56.   }
  57.   .close-btn-purchase :hover {
  58.     color: red;
  59.   }
  60.   .rowimag.no-margin {
  61.     display: grid;
  62.     grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  63.     /* auto-fill + minmax ensures they fill the row and wrap automatically */
  64.     gap: 8px; /* spacing between items, optional */
  65.     margin: 0; /* override default margin if you want */
  66.     padding: 0;
  67.   }
  68.   /* Each cell is 200px tall (or pick your own dimension). */
  69.   .photo-item {
  70.     width: 100%;
  71.     height: 250px; /* fixed height: 200px */
  72.     position: relative;
  73.     overflow: hidden; /* hide any overflow if the image is bigger */
  74.     border-radius: 4px; /* optional rounding corners */
  75.     background: #f0f0f0; /* fallback background color while image loads */
  76.     margin-bottom: 20px;
  77.   }
  78.   /* For images, we want them to fill the box and maintain a cover aspect. */
  79.   .photo-item img,
  80.   .photo-item video {
  81.     width: 100%;
  82.     height: 100%;
  83.     object-fit: cover; /* ensures image or video is cropped rather than distorted */
  84.     display: block;
  85.   }
  86.   .fav-button {
  87.     pointer-events: none; /* Makes the entire button unclickable */
  88.   }
  89.   
  90.   /* Enable hover effects only */
  91.   .fav-button * {
  92.     pointer-events: auto; /* Re-enable events for children */
  93.     pointer-events: hover; /* Only allow hover events, not clicks */
  94.   }
  95.   
  96.   /* Add this class to the purchase alert to ensure it remains interactive */
  97.   #purchase-alert {
  98.     pointer-events: auto;
  99.   
  100.   }
  101.   /* Réduit l'espace autour du header */
  102.   .header {
  103.     padding: 15px 15px 5px 15px;
  104.     background: #f9f9f9;
  105.   }
  106.   /* Réduit l'espace sous le titre et le sous-titre */
  107.   .titreDetailSej {
  108.     margin-bottom: 8px;
  109.   }
  110.   .media-counts {
  111.     margin-bottom: 8px;
  112.   }
  113.   /* Centre la navigation des dates */
  114.   .date-navigation {
  115.     display: flex;
  116.     align-items: center;
  117.     justify-content: center;
  118.     gap: 8px;
  119.     width: 100%;
  120.     margin-top: 0;
  121.   }
  122.   /* Centre le conteneur des cartes */
  123.   .date-container {
  124.     display: flex;
  125.     justify-content: center;
  126.     width: 100%;
  127.   }
  128.   .media-list-horizontal {
  129.     gap: 4px;
  130.     font-size: 11px;
  131.     margin-top: 2px;
  132.     display: flex;
  133.     justify-content: center;
  134.     list-style: none;
  135.     margin-bottom: 0;
  136.     padding-left: 0;
  137.   }
  138.   .sejour-title h1 {
  139.     font-size: 1.5rem;
  140.     font-weight: bold;
  141.     color: #3BA39B;
  142.     display: flex;
  143.     align-items: center;
  144.     gap: 10px;
  145.   }
  146.   .sejour-dates {
  147.     font-size: 14px;
  148.     color: #777;
  149.     margin-top: 5px;
  150.   }
  151.   .sejour-medias {
  152.     display: flex;
  153.     gap: 20px;
  154.     align-items: center;
  155.     font-size: 14px;
  156.     color: #555;
  157.   }
  158.   .media-info {
  159.     display: flex;
  160.     align-items: center;
  161.     gap: 5px;
  162.   }
  163.   /* Responsive Mobile */
  164.   @media (max-width: 768px) {
  165.     .sejour-header {
  166.       flex-direction: column;
  167.       align-items: center;
  168.       text-align: center;
  169.     }
  170.     .sejour-medias {
  171.       margin-top: 10px;
  172.       gap: 10px;
  173.     }
  174.   }
  175. </style>
  176. {% endblock %} {% set pageMenu = app.session.get('pageMenu') %} {% block Content
  177. %}
  178. <!-- Alerte pour inciter à acheter -->
  179. <div id="purchase-alert" class="purchase-alert hidden" style="display: none;">
  180.   <button class="close-btn" onclick="closePurchaseAlert()">&times;</button>
  181.   <div id="purchase-alert-content">
  182.     <!-- Le contenu de l'alerte sera mis à jour dynamiquement en fonction du nombre de favoris -->
  183.   </div>
  184. </div>
  185. <div
  186.   id="verifImg"
  187.   class="modal fade"
  188.   role="dialog"
  189.   style="background-color: rgba(112, 112, 112, 0.56); z-index: 1000000"
  190. >
  191.   <div class="modal-dialog dialogUploadImg">
  192.     <div class="row modal-content no-margin contentdialogNoImg">
  193.       <div class="headerdialogUploadImg">
  194.         <h1 class="titledialogUploadImg"></h1>
  195.         <img
  196.           src="{{ '/images/Accompagnateur/CroixFermeture.svg' }}"
  197.           class="closeNOUploadImg"
  198.           data-dismiss="modal"
  199.         />
  200.       </div>
  201.       <div class="ContenudetailsSejour">
  202.         <div class="row no-margin detailsSejour">
  203.           <div class="ContentUpload">
  204.             <h1 class="titleTelechargement">
  205.               Oulala, patience, avant tout sélectionnez vos photos préférées à
  206.               l'aide de ce bouton
  207.               <i
  208.                 class="bi bi-heart"
  209.                 style="font-size: 1.3rem"
  210.                 title="Ajouter à  ma sélection"
  211.               ></i>
  212.               sous les photos  <br /><br /><a style="color: #f09e7a"
  213.                 >Pensez à commander des tirages... pour leurs offrir un beau
  214.                 souvenir !
  215.               </a>
  216.             </h1>
  217.           </div>
  218.         </div>
  219.       </div>
  220.       <div class="BottomNoUploadImg">
  221.         <button class="BtnUploadImg btnAnnulerUpload" data-dismiss="modal">
  222.           OK
  223.         </button>
  224.       </div>
  225.     </div>
  226.   </div>
  227. </div>
  228. <div class="main-content">
  229.   <div class="row no-margin">
  230.     <!-- Chat button -->
  231.     <div
  232.       class="fav-button"
  233.       onmouseover="showSelection()"
  234.       onmouseout="hideSelection()"
  235.     >
  236.       <i id="favoris-icon-Accueilpayment" class="bi bi-heart-fill CoeurEclat"></i
  237.       ><label
  238.         id="likeCount"
  239.         class="labelFavCount"
  240.         style="background-color: #f56040"
  241.       >
  242.         {{ likes | length }}</label
  243.       >
  244.     </div>
  245.     <div class="selection-popover" id="selectionPopover">
  246.       <h4>Votre sélection</h4>
  247.       <p>Tirages : {{ likes | length }} / 12</p>
  248.       <p>Numériques : {{ likes | length }} / 15</p>
  249.       <p>Album : {{ likes | length }} / 20</p>
  250.       <button class="finalize-button">Finaliser ma commande</button>
  251.     </div>
  252.   </div>
  253.   <div class="divSliderModern">
  254.     <input type="hidden" id="nbFavCurrent" value="{{ nblikes }}" />
  255.     <div
  256.       class="splide no-padding no-margin"
  257.       id="imageSlider"
  258.       style="max-height: 200px"
  259.     >
  260.       <div class="splide__track">
  261.         <ul class="splide__list">
  262.           <!-- Slide 1 -->
  263.           <li class="splide__slide">
  264.             <div class="slider-content" style="background: white">
  265.               <div class="namePRD" style="display: block">
  266.                 <h4
  267.                   class="titleProdbienvenu titleProdbienvenu1"
  268.                   style="color: #41a2aa"
  269.                 >
  270.                   Ajoutez vos favoris dès maintenant
  271.                 </h4>
  272.                 <h4
  273.                   class="titleProdbienvenu titleProdbienvenu2"
  274.                   style="color: #f09e7a"
  275.                 >
  276.                   et profitez de nos produits souvenirs personnalisés !
  277.                 </h4>
  278.               </div>
  279.               <img
  280.                 src="{{ asset('/images/imgSliderEmpty2.png') }}"
  281.                 class="imgslider"
  282.                 alt="Image 1"
  283.               />
  284.             </div>
  285.           </li>
  286.           <!-- Slide 2 -->
  287.           <li class="splide__slide">
  288.             <div class="slider-content" style="background: white">
  289.               <div class="namePRD" style="display: block">
  290.                 <h4
  291.                   class="titleProdbienvenu titleProdbienvenu1"
  292.                   style="color: #f09e7a"
  293.                 >
  294.                   Pensez à commander le livre du séjour
  295.                 </h4>
  296.                 <h4
  297.                   class="titleProdbienvenu titleProdbienvenu2"
  298.                   style="color: #41a2aa"
  299.                 >
  300.                   et offrez lui le plus beau des cadeaux !
  301.                 </h4>
  302.               </div>
  303.               <img
  304.                 src="{{ asset('/images/imgSliderEmpty1.png') }}"
  305.                 class="imgslider"
  306.                 alt="Image 2"
  307.               />
  308.             </div>
  309.           </li>
  310.         </ul>
  311.       </div>
  312.     </div>
  313.   </div>
  314.   <!-- Section de contenu à atteindre après le scroll -->
  315.   <div
  316.     class="no-margin"
  317.     id="scrollTarget"
  318.     style="width: 100%; background: #f9f9f9; padding-top: 30px"
  319.   >
  320.     <div class="no-margin" id="scrollTarget" style="width: 100%">
  321.       <!-- Conteneur principal en ligne -->
  322.       <div
  323.         class="header d-flex align-items-center justify-content-between"
  324.         style="padding: 15px;"
  325.       >
  326.         <!-- Bloc titre -->
  327.         <div class="box divInfosSejour" style="width: 95%;">
  328.           <img
  329.             class="imageTitreSej"
  330.             src="/Accueil/imagesAccueil/sejour.png"
  331.             alt="Icône séjour"
  332.             style="width: 40px; height: auto"
  333.           />
  334.           <h1 class="titreDetailSej">
  335.             Séjour {{sejour.codeSejour}} {{ sejour.themSejour }}
  336.             <span class="spnTitleSej">
  337.               du
  338.               {{ sejour.dateDebutSejour|date("d M Y")|replace({"Jan": "janv.", "Feb": "fév.", "Mar": "mars", "Apr": "avr.", "May": "mai", "Jun": "juin", "Jul": "juil.", "Aug": "août", "Sep": "sept.", "Oct.": "oct.", "Nov.": "nov.", "Dec.": "déc."}) }}
  339.               au
  340.               {{ sejour.dateFinSejour|date("d M Y")|replace({"Jan": "janv.", "Feb": "fév.", "Mar": "mars", "Apr": "avr.", "May": "mai", "Jun": "juin", "Jul": "juil.", "Aug": "août", "Sep": "sept.", "Oct.": "oct.", "Nov.": "nov.", "Dec.": "déc."}) }}
  341.             </span>
  342.           </h1>
  343.           <span class="spnTitleSej" style="color:black">
  344.         
  345.             (📷 {{ attachementsCount }} Photos/Vidéos | 🎵 {{ nbmessages }} Audios  ❤️  <label
  346.         id="mesFavCount" style="color:black;margin-right:5px"
  347.       
  348.     >
  349.     {{ nblikes }}   </label> Favoris )
  350.   
  351.           </span>
  352.           <div class="date-navigation">
  353.           
  354.      
  355.             <div class="date-container">
  356.               {% for x, groupAttach in listeattach %}
  357.                 {% set xDate = date(x) %}
  358.                 {% set finDate = date(sejour.dateFinSejour) %}
  359.                 {% if xDate <= finDate %}
  360.                   <div
  361.                     class="date-card modern-card {% if loop.last and xDate <= finDate %} active {% endif %}"
  362.                     data-aos="fade-up"
  363.                     data-bs-toggle="collapse"
  364.                     data-bs-target="#demP{{ loop.index }}"
  365.                     id="iconedemoP{{ loop.index }}"
  366.                   >
  367.                     <div class="card-content text-center">
  368.                       <span class="day">
  369.                         {% if groupAttach.isFirstDay == "yes" %} Premier jour
  370.                         {% elseif groupAttach.isLastDay == "yes" %} Dernier jour
  371.                         {% else %}
  372.                           {{ xDate|date("D")|replace({
  373.                             "Mon": "lun.",
  374.                             "Tue": "mar.",
  375.                             "Wed": "mer.",
  376.                             "Thu": "jeu.",
  377.                             "Fri": "ven.",
  378.                             "Sat": "sam.",
  379.                             "Sun": "dim."
  380.                           }) }}
  381.                         {% endif %}
  382.                       </span>
  383.                       <span class="full-date">
  384.                         {{ xDate|date("d M Y")|replace({
  385.                           "Jan": "janv.",
  386.                           "Feb": "fév.",
  387.                           "Mar": "mars",
  388.                           "Apr": "avr.",
  389.                           "May": "mai",
  390.                           "Jun": "juin",
  391.                           "Jul": "juil.",
  392.                           "Aug": "août",
  393.                           "Sep": "sept.",
  394.                           "Oct.": "oct.",
  395.                           "Nov.": "nov.",
  396.                           "Dec.": "déc."
  397.                         }) }}
  398.                       </span>
  399.                       <ul class="media-list-horizontal">
  400.                         {% if groupAttach.countPhotos > 0 %}
  401.                         <li>
  402.                           <i class="bi bi-images" style="color: #f56040; font-size: 0.7rem; margin-right: 3px"></i>
  403.                           {{ groupAttach.countPhotos }}
  404.                         </li>
  405.                         {% endif %}
  406.                         {% if groupAttach.countAudio > 0 %}
  407.                         <li>
  408.                           <i class="bi bi-mic-fill" style="color: #ffa500; font-size: 0.7rem; margin-right: 5px"></i>
  409.                           {{ groupAttach.countAudio }}
  410.                         </li>
  411.                         {% endif %}
  412.                         {% if groupAttach.countVideos > 0 %}
  413.                         <li>
  414.                           <i class="bi bi-camera-video-fill" style="color: #41a2aa; font-size: 0.7rem; margin-right: 5px"></i>
  415.                           {{ groupAttach.countVideos }}
  416.                         </li>
  417.                         {% endif %}
  418.                       </ul>
  419.                     </div>
  420.                   </div>
  421.                 {% endif %}
  422.               {% endfor %} <div id="dynamic-card" class="dynamic-card">
  423.       <div id="dynamic-card-content" class="dynamic-card-content">
  424.         <!-- Le contenu dynamique (album, pochette, montage vidéo) sera injecté ici -->
  425.       </div>
  426.     </div>
  427.             </div>
  428.           </div>
  429.         </div>
  430.       </div>
  431.     </div>
  432.     <!-- Descriptions and Attachments -->
  433.     <div class="container--gallery modern">
  434.       {% set lastValidIndex = 0 %}
  435.       {% set hasAttachments = false %}
  436.       {% for x, groupAttach in listeattach %}
  437.       {% set xDate = date(x) %}
  438.       {% set finDate = date(sejour.dateFinSejour) %}
  439.       {% if xDate <= finDate %}
  440.       {% set lastValidIndex = loop.index %}
  441.       {% set hasAttachments = true %}
  442.       <div
  443.         id="demP{{ loop.index }}"
  444.         class="collapse {% if loop.last and xDate <= finDate %}show{% endif %}"
  445.         style="padding: 2%; padding-top: 0%"
  446.       >
  447.         <div class="journal-entry">
  448.         <div class="entry-header" style="
  449.     display: flex;
  450.     align-items: center;
  451.     justify-content: space-between;
  452.     background: #ffffff;
  453.     padding: 8px 15px;
  454.     border-radius: 10px;
  455.     margin-bottom: 20px;
  456.     box-shadow: 0 2px 8px rgba(0,0,0,0.05);
  457.     border-bottom: 1px solid #eee;
  458.     flex-wrap: wrap;
  459. ">
  460.   <!-- Bouton Jour Précédent -->
  461.   {% if not loop.first %}
  462.   <button class="btn-prev-day" data-target="{{ loop.index0 - 1 }}" style="
  463.       background-color: #3BA39B;
  464.       border: none;
  465.       padding: 5px 10px;
  466.       border-radius: 8px;
  467.       font-weight: bold;
  468.       font-size: 14px;
  469.       height: 36px;
  470.       display: flex;
  471.       align-items: center;
  472.       color: white;
  473.       cursor: pointer;
  474.       transition: all 0.3s ease;
  475.   ">
  476.     <i class="bi bi-chevron-left" style="font-size: 18px;"></i>
  477.   </button>
  478.   {% else %}
  479.   <div style="width: 36px;"></div>
  480.   {% endif %}
  481.   <!-- Centre : Date + Médias -->
  482.   <div style="
  483.       flex-grow: 1;
  484.       display: flex;
  485.       align-items: center;
  486.       justify-content: center;
  487.       flex-wrap: wrap;
  488.       gap: 12px;
  489.   ">
  490.     <!-- Date -->
  491.     <div style="font-weight: bold; font-size: 16px; color: #333;">
  492.       {{ x|date("l d F Y")|replace({
  493.           "Monday": "Lundi", "Tuesday": "Mardi", "Wednesday": "Mercredi",
  494.           "Thursday": "Jeudi", "Friday": "Vendredi", "Saturday": "Samedi",
  495.           "Sunday": "Dimanche",
  496.           "January": "Janvier", "February": "Février", "March": "Mars",
  497.           "April": "Avril", "May": "Mai", "June": "Juin",
  498.           "July": "Juillet", "August": "Août", "September": "Septembre",
  499.           "October": "Octobre", "November": "Novembre", "December": "Décembre"
  500.       }) }}
  501.     </div>
  502.   <!-- Filtres Médias -->
  503. <div class="filter-icons" style="display: flex; gap: 8px; flex-wrap: wrap;">
  504.     <span class="filter-badge active" data-filter="all" title="Afficher tout">
  505.         <i class="bi bi-grid-3x3-gap-fill" style="margin-right: 5px; font-size: 14px;"></i> Tout
  506.     </span>
  507.     {% if groupAttach.countPhotos > 0 %}
  508.     <span class="filter-badge" data-filter="photo" title="Filtrer les photos">
  509.         <i class="bi bi-image" style="margin-right: 5px; font-size: 14px;"></i> {{ groupAttach.countPhotos }}
  510.     </span>
  511.     {% endif %}
  512.     {% if groupAttach.countVideos > 0 %}
  513.     <span class="filter-badge" data-filter="video" title="Filtrer les vidéos">
  514.         <i class="bi bi-camera-video-fill" style="margin-right: 5px; font-size: 14px;"></i> {{ groupAttach.countVideos }}
  515.     </span>
  516.     {% endif %}
  517.     {% if groupAttach.countAudio > 0 %}
  518.     <span class="filter-badge" data-filter="audio" title="Filtrer les messages audio">
  519.         <i class="bi bi-mic-fill" style="margin-right: 5px; font-size: 14px;"></i> {{ groupAttach.countAudio }}
  520.     </span>
  521.     {% endif %}
  522. </div>
  523.   </div>
  524.   <!-- Bouton Jour Suivant -->
  525.   {% if not loop.last %}
  526.   <button class="btn-next-day" data-target="{{ loop.index0 + 1 }}" style="
  527.       background-color: #3BA39B;
  528.       border: none;
  529.       padding: 5px 10px;
  530.       border-radius: 8px;
  531.       font-weight: bold;
  532.       font-size: 14px;
  533.       height: 36px;
  534.       display: flex;
  535.       align-items: center;
  536.       color: white;
  537.       cursor: pointer;
  538.       transition: all 0.3s ease;
  539.   ">
  540.     <i class="bi bi-chevron-right" style="font-size: 18px;"></i>
  541.   </button>
  542.   {% else %}
  543.   <div style="width: 36px;"></div>
  544.   {% endif %}
  545.    
  546.    
  547.         </div>
  548.         <!-- Contenu -->
  549.         <div class="entry-content" id="TourContent">
  550.       
  551.           <p class="description" style="margin-left:2%;width:95%;margin-top:1%;margin-bottom:1%;text-align:left">
  552.             {% for description in sejour.jourdescripdate %} {% if
  553.             description.datejourphoto|date("m/d/Y") == x|date("m/d/Y") %}
  554.             {{ description.description | nl2br }}
  555.             {% endif %} {% endfor %}
  556.           </p>
  557.  
  558.           <!-- Conteneur des photos et vidéos -->
  559.           <div
  560.             class="rowimag no-margin"
  561.             style="
  562.               width: 100%;
  563.               display: flex;
  564.               flex-wrap: wrap;
  565.               margin: 0;
  566.               box-sizing: border-box;
  567.             "
  568.           >
  569.             <!-- Afficher les Photos et Vidéos -->
  570.             {% for attach in groupAttach.attachments %}
  571.               {% if attach.libiller == 'photo' %}
  572.            
  573.             <div class="column" data-type="{{ attach.libiller }}">
  574.             
  575.               <div class="photo-zoom photo-item">
  576.          
  577.                 <a href="{{ attach.path }}">
  578.                   <img src="{{ attach.path }}" alt="{{ attach.descreption }}" />
  579.                 </a>
  580.                 <!-- Icône du cœur avec logique existante -->
  581.                 <div
  582.                   class="heart-icon"
  583.                   id="coeur{{ attach.id_attchment }}"
  584.                   data-id="{{ attach.id_attchment }}"
  585.                   data-sejour-id="{{ sejour.id }}"
  586.                   data-path="{{ attach.path }}"
  587.                   data-description="{{ attach.descreption }}"
  588.                 >
  589.                   {% if app.user %} {% if attach.is_favorite %}
  590.                   <i
  591.                     class="bi bi-heart-fill"
  592.                     title="Sélectionnée"
  593.                     style="color: #f56040"
  594.                   ></i>
  595.                   {% else %}
  596.                   <i class="bi bi-heart" title="Ajouter à ma sélection"></i>
  597.                   {% endif %} {% endif %}
  598.                 </div>
  599.                 <div class="photo-actions" style="display: none">
  600.                   <button class="menu-btn">⋮</button>
  601.                   <div class="menu-options">
  602.                     <button onclick="addToPack('tirage')">
  603.                       🖨️ Ajouter au tirage
  604.                     </button>
  605.                     <button onclick="addToPack('numerique')">
  606.                       💾 Ajouter au numérique
  607.                     </button>
  608.                   </div>
  609.                 </div>
  610.               
  611.               </div>
  612.               {% if attach.descreption != "" %}
  613.               <h4 class="description">{{ attach.descreption }}</h4>
  614.               {% endif %}
  615.             </div>
  616.             {% endif %} 
  617.              {% if attach.libiller == 'video' %}
  618.            
  619.             <div class="column" data-type="{{ attach.libiller }}">
  620.                  
  621.             
  622.                  <div class="video-container" style="position: relative; display: inline-block; width: 100%; border-radius: 8px; overflow: hidden;">
  623.                         <video class="photo-zoom" controls controlslist="nodownload noplaybackrate" style="width: 100%;">
  624.                           <source src="{{ attach.path }}" type="video/mp4" />
  625.                           Votre navigateur ne supporte pas la lecture vidéo.
  626.                         </video>
  627.                       
  628.                       </div>
  629.               {% if attach.descreption != "" %}
  630.               <h4 class="description">{{ attach.descreption }}</h4>
  631.               {% endif %}
  632.             </div>
  633.             {% endif %} 
  634.             
  635.             {% endfor %}
  636.           </div>
  637.           <!-- Section séparée pour les messages audio -->
  638.           {% if groupAttach.countAudio > 0 %}
  639.           <div class="audio-messages-section" style="margin-top:15px; border-top: 1px solid #eee; padding: 30px;">
  640.             <h4 style="margin-bottom: 15px; color: #555">
  641.               <i class="bi bi-mic-fill" style="margin-right: 8px; color: #ffa500"></i>
  642.               Messages vocaux ({{ groupAttach.countAudio }})
  643.             </h4>
  644.             
  645.             {% if sejour.codeSejour|slice(0, 2) == 'PF' %}
  646.               {# Les séjours commençant par PF ont toujours accès #}
  647.               <div class="audio-messages-container" style="display: flex; flex-wrap: wrap; gap: 15px">
  648.                 {% for attach in groupAttach.attachments %}
  649.                   {% if attach.libiller == 'message' %}
  650.                     <div class="audio-message-item" style="background: #f9f9f9; border-radius: 8px; padding: 12px; display: flex; flex-direction: column; width: calc(33.33% - 10px); min-width: 250px; flex-grow: 1;">
  651.                       <div class="audio-player-container" style="display: flex; align-items: center; margin-bottom: 10px;">
  652.                         <i class="bi bi-mic-fill" style="font-size: 20px; margin-right: 10px; color: #ffa500"></i>
  653.                         <audio controls controlslist="nodownload noplaybackrate" style="flex: 1">
  654.                           <source src="{{ attach.path }}" type="audio/mp3" />
  655.                           Votre navigateur ne supporte pas la lecture audio.
  656.                         </audio>
  657.                       </div>
  658.                       {% if attach.descreption != "" %}
  659.                         <div class="audio-description" style="padding-left: 30px">
  660.                           <p style="margin: 0; font-size: 14px; color: #555; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;">
  661.                             {{ attach.descreption }}
  662.                           </p>
  663.                         </div>
  664.                       {% endif %}
  665.                     </div>
  666.                   {% endif %}
  667.                 {% endfor %}
  668.               </div>
  669.             
  670.             {% elseif sejour.codeSejour|slice(0, 2) == 'PP' and parentsejour.payment  == 1 or sejour.codeSejour|slice(0, 2) == 'EF' and parentsejour.payment  == 1 %}
  671.               {# PP ou EF avec paiement effectué #}
  672.               <div class="audio-messages-container" style="display: flex; flex-wrap: wrap; gap: 15px">
  673.                 {% for attach in groupAttach.attachments %}
  674.                   {% if attach.libiller == 'message' %}
  675.                     <div class="audio-message-item" style="background: #f9f9f9; border-radius: 8px; padding: 12px; display: flex; flex-direction: column; width: calc(33.33% - 10px); min-width: 250px; flex-grow: 1;">
  676.                       <div class="audio-player-container" style="display: flex; align-items: center; margin-bottom: 10px;">
  677.                         <i class="bi bi-mic-fill" style="font-size: 20px; margin-right: 10px; color: #ffa500"></i>
  678.                         <audio controls controlslist="nodownload noplaybackrate" style="flex: 1">
  679.                           <source src="{{ attach.path }}" type="audio/mp3" />
  680.                           Votre navigateur ne supporte pas la lecture audio.
  681.                         </audio>
  682.                       </div>
  683.                       {% if attach.descreption != "" %}
  684.                         <div class="audio-description" style="padding-left: 30px">
  685.                           <p style="margin: 0; font-size: 14px; color: #555; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;">
  686.                             {{ attach.descreption }}
  687.                           </p>
  688.                         </div>
  689.                       {% endif %}
  690.                     </div>
  691.                   {% endif %}
  692.                 {% endfor %}
  693.               </div>
  694.             
  695.             {% elseif sejour.codeSejour|slice(0, 2) == 'PP' and parentsejour.payment == 0 or sejour.codeSejour|slice(0, 2) == 'EF' and parentsejour.payment == 0 %}
  696.               {# PP ou EF sans paiement - message d'accès limité et audio désactivés #}
  697.               <div class="audio-messages-container" style="display: flex; flex-wrap: wrap; gap: 15px; opacity: 0.5; pointer-events: none; filter: grayscale(100%);">
  698.                 <div class="audio-messages-restricted" style="padding: 20px; background: #f0f0f0; border-radius: 8px; text-align: center; margin-bottom: 15px; width: 100%;">
  699.                   <i class="bi bi-lock-fill" style="font-size: 24px; color: #808080; margin-bottom: 10px;"></i>
  700.                   <p style="margin: 0; color: #555;">Pour accéder aux messages vocaux, veuillez effectuer le paiement de votre séjour.</p>
  701.                 </div>
  702.                 {% for attach in groupAttach.attachments %}
  703.                   {% if attach.libiller == 'message' %}
  704.                     <div class="audio-message-item" style="background: #f9f9f9; border-radius: 8px; padding: 12px; display: flex; flex-direction: column; width: calc(33.33% - 10px); min-width: 250px; flex-grow: 1;">
  705.                       <div class="audio-player-container" style="display: flex; align-items: center; margin-bottom: 10px;">
  706.                         <i class="bi bi-mic-fill" style="font-size: 20px; margin-right: 10px; color: #ffa500"></i>
  707.                         <audio controls controlslist="nodownload noplaybackrate" style="flex: 1" disabled>
  708.                           <source src="{{ attach.path }}" type="audio/mp3" />
  709.                           Votre navigateur ne supporte pas la lecture audio.
  710.                         </audio>
  711.                       </div>
  712.                       {% if attach.descreption != "" %}
  713.                         <div class="audio-description" style="padding-left: 30px">
  714.                           <p style="margin: 0; font-size: 14px; color: #555; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;">
  715.                             {{ attach.descreption }}
  716.                           </p>
  717.                         </div>
  718.                       {% endif %}
  719.                     </div>
  720.                   {% endif %}
  721.                 {% endfor %}
  722.               </div>
  723.             {% endif %}
  724.           </div>
  725.         {% endif %}
  726.         </div>
  727.       </div>
  728.     </div>
  729.     {% endif %}
  730.     {% endfor %}
  731.     {% if not hasAttachments %}
  732.     <div class="welcome-message" style="padding: 50px 20px; text-align: center; background: #f9f9f9; border-radius: 15px; margin: 30px auto; max-width: 800px; box-shadow: 0 5px 15px rgba(0,0,0,0.05);">
  733.       <img src="/images/welcome-icon.svg" alt="Bienvenue" style="width: 80px; margin-bottom: 20px;" onerror="this.src='/images/Accompagnateur/Picto5sur5.svg'; this.style.width='120px';">
  734.       
  735.       <h2 style="color: #41a2aa; margin-bottom: 20px; font-size: 24px;">Bienvenue sur votre espace séjour !</h2>
  736.       
  737.       <p style="font-size: 18px; color: #555; margin-bottom: 15px;">
  738.         Aucun contenu n'a encore été partagé pour ce séjour.
  739.       </p>
  740.       
  741.       <p style="font-size: 16px; color: #666; margin-bottom: 25px;">
  742.         L'accompagnateur partagera bientôt des photos, vidéos et messages vocaux.
  743.         <br>Revenez consulter cette page régulièrement pour suivre les aventures du séjour !
  744.       </p>
  745.       
  746.       <div style="display: flex; justify-content: center; gap: 15px; flex-wrap: wrap;">
  747.         <div style="display: flex; align-items: center; background: #fff; padding: 15px; border-radius: 10px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);">
  748.           <i class="bi bi-images" style="font-size: 24px; color: #f56040; margin-right: 10px;"></i>
  749.           <span>Photos du séjour</span>
  750.         </div>
  751.         
  752.         <div style="display: flex; align-items: center; background: #fff; padding: 15px; border-radius: 10px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);">
  753.           <i class="bi bi-camera-video-fill" style="font-size: 24px; color: #41a2aa; margin-right: 10px;"></i>
  754.           <span>Vidéos des activités</span>
  755.         </div>
  756.         
  757.         <div style="display: flex; align-items: center; background: #fff; padding: 15px; border-radius: 10px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);">
  758.           <i class="bi bi-mic-fill" style="font-size: 24px; color: #ffa500; margin-right: 10px;"></i>
  759.           <span>Messages vocaux</span>
  760.         </div>
  761.       </div>
  762.     </div>
  763.     
  764.     <!-- Espace supplémentaire pour déplacer le footer vers le bas -->
  765.     <div style="height: 300px;"></div>
  766.     {% endif %}
  767.     
  768.     <!-- Make sure we're showing the right content by default if no valid content is marked 'show' -->
  769.     {% if lastValidIndex > 0 %}
  770.     <script>
  771.       document.addEventListener('DOMContentLoaded', function() {
  772.         // Check if no content is showing
  773.         if (document.querySelectorAll('.container--gallery .collapse.show').length === 0) {
  774.           // Show the content for the last valid date
  775.           var lastValidContent = document.getElementById('demP{{ lastValidIndex }}');
  776.           if (lastValidContent) {
  777.             lastValidContent.classList.add('show');
  778.             
  779.             // Also mark the corresponding date card as active
  780.             var dateCards = document.querySelectorAll('.date-card');
  781.             if (dateCards.length >= {{ lastValidIndex }}) {
  782.               dateCards.forEach(card => card.classList.remove('active'));
  783.               dateCards[{{ lastValidIndex - 1 }}].classList.add('active');
  784.             }
  785.           }
  786.         }
  787.       });
  788.     </script>
  789.     {% endif %}
  790.   </div>
  791. </div>
  792.   {% endblock %} {% block Javascript %}
  793.   {{ parent() }}
  794.   <script>// Gestion de la sidebar des favoris
  795. document.addEventListener('DOMContentLoaded', function() {
  796.     const sidebar = document.getElementById('favorites-sidebar');
  797.     const openBtn = document.getElementById('openFavoritesSidebar');
  798.     const closeBtn = document.querySelector('.favorites-close');
  799.     const favButton = document.querySelector('.fav-button');
  800.     function openSidebar() {
  801.         sidebar.classList.add('active');
  802.         updateFavoritesSidebar();
  803.     }
  804.     function closeSidebar() {
  805.         sidebar.classList.remove('active');
  806.     }
  807.     function updateFavoritesSidebar() {
  808.         const grid = document.getElementById('favorites-grid');
  809.         const counter = document.getElementById('favorites-counter');
  810.         const emptyState = document.getElementById('favorites-empty-state');
  811.         const progress = document.getElementById('favorites-progress');
  812.         
  813.         const count = parseInt(document.getElementById('likeCount').textContent);
  814.         counter.textContent = count +1;
  815.         
  816.         if (count === 0) {
  817.             emptyState.style.display = 'flex';
  818.             grid.style.display = 'none';
  819.         } else {
  820.             emptyState.style.display = 'none';
  821.             grid.style.display = 'grid';
  822.             const percentage = (count / 20) * 100;
  823.             progress.style.width = `${percentage}%`;
  824.         }
  825.     }
  826.     if (openBtn) {
  827.         openBtn.addEventListener('click', openSidebar);
  828.     }
  829.     if (favButton) {
  830.         favButton.addEventListener('click', openSidebar);
  831.     }
  832.     if (closeBtn) {
  833.         closeBtn.addEventListener('click', closeSidebar);
  834.     }
  835.     document.addEventListener('click', (e) => {
  836.         if (sidebar.classList.contains('active') && 
  837.             !sidebar.contains(e.target) && 
  838.             !favButton.contains(e.target) && 
  839.             !openBtn.contains(e.target)) {
  840.             closeSidebar();
  841.         }
  842.     });
  843. });
  844. // Modification des fonctions existantes
  845. const originalAddFavoris = window.AddFavoris;
  846. window.AddFavoris = function($id, $idSejour, $urlimg, $description) {
  847.     if (originalAddFavoris) {
  848.         originalAddFavoris($id, $idSejour, $urlimg, $description);
  849.     }
  850.     
  851.     // Vérifier si la sidebar est ouverte - noter que nous vérifions la valeur CSS right: 0
  852.     if ($("#favorites-sidebar").css("right") === "0px") {
  853.         // Recharger les favoris
  854.         loadFavorites();
  855.     }
  856. };
  857. const originalSupprimerFavoris = window.supprimerFavoris;
  858. window.supprimerFavoris = function($id, $idSejour) {
  859.     if (originalSupprimerFavoris) {
  860.         originalSupprimerFavoris($id, $idSejour);
  861.     }
  862.     
  863.     // Vérifier si la sidebar est ouverte
  864.     if ($("#favorites-sidebar").css("right") === "0px") {
  865.         // Recharger les favoris
  866.         loadFavorites();
  867.     }
  868. };
  869. // Variables globales
  870. let selectedFavorites = [];
  871. let allFavorites = [];
  872. // Fonction pour mettre à jour la sidebar
  873. function loadFavorites() {
  874.     $("#favorites-grid").html("<div style='text-align:center;padding:20px;'>Chargement...</div>");
  875.     
  876.     $.ajax({
  877.         url: "/Parent/mes-favoris",
  878.         type: "GET",
  879.         dataType: "json",
  880.         success: function(data) {
  881.             $("#favorites-grid").empty();
  882.             allFavorites = data.data || [];
  883.             
  884.             if (allFavorites.length > 0) {
  885.                 $("#favorites-empty-state").hide();
  886.                 
  887.                 $.each(allFavorites, function(i, fav) {
  888.                     var isSelected = selectedFavorites.includes(fav.id);
  889.                     
  890.                     var item = $("<div class='favorite-item' style='position:relative;border-radius:8px;overflow:hidden;aspect-ratio:1;cursor:pointer;'></div>");
  891.                     var img = $("<img style='width:100%;height:100%;object-fit:cover;transition:transform 0.3s ease;'>").attr("src", fav.path).attr("alt", fav.descreption || "Photo favorite");
  892.                     
  893.                     // Overlay de sélection
  894.                     var selectionOverlay = $("<div class='selection-overlay' style='position:absolute;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.3);display:flex;align-items:center;justify-content:center;'></div>");
  895.                     
  896.                     // Icône de sélection
  897.                     var checkIcon = $("<div style='width:25px;height:25px;border-radius:50%;border:2px solid white;display:flex;align-items:center;justify-content:center;background:" + (isSelected ? "#F56040" : "transparent") + ";transition:background 0.2s;'></div>");
  898.                     if (isSelected) {
  899.                         checkIcon.append("<i class='bi bi-check' style='color:white;font-size:16px;'></i>");
  900.                     }
  901.                     
  902.                     selectionOverlay.append(checkIcon);
  903.                     
  904.                     // Overlay d'action (bouton supprimer)
  905.                     var actionOverlay = $("<div class='action-overlay' style='position:absolute;top:5px;right:5px;opacity:0;transition:opacity 0.2s;'></div>");
  906.                   
  907.                     actionOverlay.append(deleteBtn);
  908.                     
  909.                     // Ajouter les événements
  910.                     item.hover(
  911.                         function() { $(this).find(".action-overlay").css("opacity", "1"); },
  912.                         function() { $(this).find(".action-overlay").css("opacity", "0"); }
  913.                     );
  914.                     
  915.                     item.click(function() {
  916.                         toggleSelection(fav.id, $(this).find(".selection-overlay > div"));
  917.                     });
  918.                     
  919.                     item.append(img).append(selectionOverlay).append(actionOverlay);
  920.                     $("#favorites-grid").append(item);
  921.                 });
  922.                 
  923.                 $("#favorites-counter").text(allFavorites.length);
  924.                 
  925.                 // Mettre à jour le compteur sur le bouton également
  926.                 $("#openFavoritesSidebar span").text(allFavorites.length);
  927.                 
  928.                 // Mettre à jour l'interface produits
  929.                 updateProductsView();
  930.                 
  931.             } else {
  932.                 $("#favorites-empty-state").show();
  933.                 $("#favorites-counter").text("0");
  934.                 $("#openFavoritesSidebar span").text("0");
  935.                 $("#selection-count").text("0");
  936.                 updateProductsView();
  937.             }
  938.         },
  939.         error: function() {
  940.             $("#favorites-grid").html("<div style='color:red;text-align:center;padding:20px;'>Erreur de chargement</div>");
  941.         }
  942.     });
  943. }
  944. // Fonction pour supprimer un favori
  945. function removeFavorite(id) {
  946.     $.ajax({
  947.         url: "/Parent/remove-favorite/" + id,
  948.         type: "POST",
  949.         success: function() {
  950.             // Retirer de la sélection si présent
  951.             selectedFavorites = selectedFavorites.filter(favId => favId != id);
  952.             
  953.             // Mettre à jour le compteur de sélection
  954.             $("#selection-count").text(selectedFavorites.length);
  955.             
  956.             // Recharger les favoris
  957.             loadFavorites();
  958.             
  959.             // Mettre à jour les compteurs globaux
  960.             var count = parseInt($("#likeCount").text());
  961.             if (!isNaN(count)) {
  962.                 $("#likeCount").text(count - 1);
  963.             }
  964.             
  965.             var countFav = parseInt($("#mesFavCount").text());
  966.             if (!isNaN(countFav)) {
  967.                 $("#mesFavCount").text(countFav - 1);
  968.             }
  969.             
  970.             // Mettre à jour l'interface produits
  971.             updateProductsView();
  972.         },
  973.         error: function() {
  974.             alert("Erreur lors de la suppression du favori");
  975.         }
  976.     });
  977. }
  978. // Fonction pour basculer la sélection d'une photo
  979. function toggleSelection(id, checkElement) {
  980.     const index = selectedFavorites.indexOf(id);
  981.     
  982.     if (index === -1) {
  983.         // Ajouter à la sélection
  984.         selectedFavorites.push(id);
  985.         checkElement.css("background", "#F56040");
  986.         checkElement.html("<i class='bi bi-check' style='color:white;font-size:16px;'></i>");
  987.     } else {
  988.         // Retirer de la sélection
  989.         selectedFavorites.splice(index, 1);
  990.         checkElement.css("background", "transparent");
  991.         checkElement.html("");
  992.     }
  993.     
  994.     // Mettre à jour le compteur
  995.     $("#selection-count").text(selectedFavorites.length);
  996.     
  997.     // Mettre à jour l'interface produits
  998.     updateProductsView();
  999. }
  1000. // Fonction pour mettre à jour la vue des produits
  1001. function updateProductsView() {
  1002.     const current = selectedFavorites.length;
  1003.     $("#product-photo-count").text(current);
  1004.     
  1005.     let remainingForAlbum = Math.max(0, 20 - current);
  1006.     let remainingForPochette = Math.max(0, 12 - current);
  1007.     let remainingForPack = Math.max(0, 12 - current);
  1008.     const progressBar = (count, total, color) => `
  1009.         <div style="margin: 5px 0;">
  1010.             <div style="background-color: #e9ecef; border-radius: 5px; overflow: hidden; height: 8px;">
  1011.                 <div style="width: ${(count / total) * 100}%; background-color: ${color}; height: 100%;"></div>
  1012.             </div>
  1013.             <small style="font-size: 12px;">${count}/${total} photos</small>
  1014.         </div>
  1015.     `;
  1016.     // Liste des produits
  1017.     const products = [
  1018.         {
  1019.             name: "Pack numérique (20 photos)",
  1020.             required: 20,
  1021.             remaining: Math.max(0, 20 - current),
  1022.             image: "/images/produit/photoNumerique.jpg",
  1023.             color: "#4caf50",
  1024.             link: "{{ path('PackPhotosNumerique_Favoris', {'nbr':20}) }}",
  1025.         },
  1026.        +
  1027.         {
  1028.             name: "Pochette photo (12 photos)",
  1029.             required: 12,
  1030.             remaining: Math.max(0, 12 - current),
  1031.             image: "/images/produit/PochettePhoto5sur5-2.jpg",
  1032.             color: "#2196f3",
  1033.             link: "{{ path('AjoutPochettePhotos_Favoris', {'nbr': 12}) }}",
  1034.         },
  1035.     ].sort((a, b) => a.remaining - b.remaining);
  1036.     const productList = products
  1037.         .map((product) => {
  1038.             const count = current;
  1039.             const total = product.required;
  1040.             const remaining = product.remaining;
  1041.             return `
  1042.                 <li style="margin-bottom: 20px;">
  1043.                     <div style="display: flex; align-items: center; gap: 10px;">
  1044.                         <img src="${product.image}" alt="${product.name}" style="width: 70px; height: 70px; border-radius: 5px; object-fit: cover;" />
  1045.                         <div style="flex: 1;">
  1046.                             <strong style="font-size: 14px;">${product.name}</strong>
  1047.                             ${progressBar(count, total, product.color)}
  1048.                             ${
  1049.                                 `<small style="color: ${product.color}; font-size: 12px;">
  1050.                                     Encore ${remaining} photos pour compléter ${product.name.toLowerCase()}
  1051.                                 </small>
  1052.                                 <button
  1053.                                     style="
  1054.                                         margin-top: 5px;
  1055.                                         padding: 6px 12px;
  1056.                                         background-color: ${product.color};
  1057.                                         color: white;
  1058.                                         border: none;
  1059.                                         border-radius: 5px;
  1060.                                         font-size: 13px;
  1061.                                         cursor: pointer;
  1062.                                     "
  1063.                                     onclick="window.location.href='${product.link}'"
  1064.                                 >
  1065.                                     Commander
  1066.                                 </button>`
  1067.                             }
  1068.                         </div>
  1069.                     </div>
  1070.                 </li>
  1071.             `;
  1072.         })
  1073.         .join("");
  1074.     const boutiqueButton = `
  1075.         <li style="margin-top: 25px; text-align: center;">
  1076.             <button
  1077.                 style="
  1078.                     padding: 8px 15px;
  1079.                     background-color: #F56040;
  1080.                     color: white;
  1081.                     border: none;
  1082.                     border-radius: 5px;
  1083.                     font-size: 14px;
  1084.                     width: 170px;
  1085.                     height: 40px;
  1086.                     cursor: pointer;
  1087.                 "
  1088.                 onclick="window.location.href='{{ path('boutique5sur5') }}'"
  1089.             >
  1090.                 Voir toute la boutique
  1091.             </button>
  1092.         </li>
  1093.     `;
  1094.     $("#product-list").html(productList + boutiqueButton);
  1095. }
  1096. // Modifications au script existant
  1097. $(document).ready(function() {
  1098.     // Fonctions pour ouvrir/fermer la sidebar
  1099.     $("#openFavoritesSidebar").click(function() {
  1100.         $("#favorites-sidebar").css("right", "0");
  1101.         loadFavorites();
  1102.     });
  1103.     
  1104.     $("#close-favorites-btn").click(function() {
  1105.         closeFavoritesSidebar();
  1106.     });
  1107.     
  1108.     // Fonction pour fermer la sidebar
  1109.     window.closeFavoritesSidebar = function() {
  1110.         $("#favorites-sidebar").css("right", "-500px");
  1111.     };
  1112.     
  1113.     // Tout sélectionner / Tout désélectionner
  1114.     $("#select-all-btn").click(function() {
  1115.         if (selectedFavorites.length === allFavorites.length) {
  1116.             // Tout désélectionner
  1117.             selectedFavorites = [];
  1118.             $(".selection-overlay > div").css("background", "transparent").html("");
  1119.             $(this).text("Tout sélectionner");
  1120.         } else {
  1121.             // Tout sélectionner
  1122.             selectedFavorites = allFavorites.map(fav => fav.id);
  1123.             $(".selection-overlay > div").css("background", "#F56040").html("<i class='bi bi-check' style='color:white;font-size:16px;'></i>");
  1124.             $(this).text("Tout désélectionner");
  1125.         }
  1126.         
  1127.         // Mettre à jour le compteur
  1128.         $("#selection-count").text(selectedFavorites.length);
  1129.         
  1130.         // Mettre à jour l'interface produits
  1131.         updateProductsView();
  1132.     });
  1133.     
  1134.     // Gestion des onglets
  1135.     $(".sidebar-tab").click(function() {
  1136.         $(".sidebar-tab").removeClass("active").css({
  1137.             "color": "#666",
  1138.             "border-bottom": "none"
  1139.         });
  1140.         $(this).addClass("active").css({
  1141.             "color": "#F56040",
  1142.             "border-bottom": "2px solid #F56040"
  1143.         });
  1144.         
  1145.         const tabId = $(this).attr("id");
  1146.         $(".tab-content").hide();
  1147.         
  1148.         if (tabId === "tab-photos") {
  1149.             $("#photos-content").show();
  1150.         } else if (tabId === "tab-products") {
  1151.             $("#products-content").show();
  1152.         }
  1153.     });
  1154.     
  1155.     // Modifier les fonctions existantes pour intercepter l'ajout/suppression de favoris
  1156.     const originalAddFavoris = window.AddFavoris;
  1157.     window.AddFavoris = function($id, $idSejour, $urlimg, $description) {
  1158.         if (originalAddFavoris) {
  1159.             originalAddFavoris($id, $idSejour, $urlimg, $description);
  1160.         }
  1161.         
  1162.         // Recharger les favoris si la sidebar est ouverte
  1163.         if ($("#favorites-sidebar").css("right") === "0px") {
  1164.             loadFavorites();
  1165.         }
  1166.     };
  1167.     const originalSupprimerFavoris = window.supprimerFavoris;
  1168.     window.supprimerFavoris = function($id, $idSejour) {
  1169.         if (originalSupprimerFavoris) {
  1170.             originalSupprimerFavoris($id, $idSejour);
  1171.         }
  1172.         
  1173.         // Recharger les favoris si la sidebar est ouverte
  1174.         if ($("#favorites-sidebar").css("right") === "0px") {
  1175.             // Retirer de la sélection si présent
  1176.             selectedFavorites = selectedFavorites.filter(favId => favId != $id);
  1177.             loadFavorites();
  1178.         }
  1179.     };
  1180.     
  1181.     // Fermer en cliquant en dehors
  1182.     $(document).click(function(event) {
  1183.         if (!$(event.target).closest("#favorites-sidebar").length && 
  1184.             !$(event.target).closest("#openFavoritesSidebar").length && 
  1185.             $("#favorites-sidebar").css("right") === "0px") {
  1186.             closeFavoritesSidebar();
  1187.         }
  1188.     });
  1189. });
  1190. // Initialisation de la sidebar
  1191. $(document).ready(function() {
  1192.     // Fonctions pour ouvrir/fermer la sidebar
  1193.     $("#openFavoritesSidebar").click(function() {
  1194.         $("#favorites-sidebar").css("right", "0");
  1195.         loadFavorites();
  1196.     });
  1197.     
  1198.     $("#close-favorites-btn").click(function() {
  1199.         $("#favorites-sidebar").css("right", "-500px");
  1200.     });
  1201.     
  1202.     // Fermer en cliquant en dehors
  1203.     $(document).click(function(event) {
  1204.         if (!$(event.target).closest("#favorites-sidebar").length && 
  1205.             !$(event.target).closest("#openFavoritesSidebar").length && 
  1206.             $("#favorites-sidebar").css("right") === "0px") {
  1207.             $("#favorites-sidebar").css("right", "-500px");
  1208.         }
  1209.     });
  1210. });
  1211.   </script>
  1212.   <script src="{{ asset('js/splide.min.js') }}"></script>
  1213.    
  1214. <script>
  1215.   document.addEventListener('DOMContentLoaded', function () {
  1216.     const openBtn = document.getElementById('openFavoritesSidebar');
  1217.     const sidebar = document.getElementById('favorites-sidebar');
  1218.     const closeBtn = document.getElementById('favorites-close');
  1219.     if (openBtn && sidebar) {
  1220.       openBtn.addEventListener('click', () => sidebar.classList.add('active'));
  1221.     }
  1222.     if (closeBtn && sidebar) {
  1223.       closeBtn.addEventListener('click', () => sidebar.classList.remove('active'));
  1224.     }
  1225.   });
  1226. </script>
  1227.  
  1228. <script>
  1229. document.addEventListener('DOMContentLoaded', function() {
  1230.   const filterBadges = document.querySelectorAll('.filter-badge');
  1231.   filterBadges.forEach(badge => {
  1232.     badge.addEventListener('click', function() {
  1233.       // Désactiver tous les badges
  1234.       filterBadges.forEach(b => b.classList.remove('active'));
  1235.       // Activer le badge cliqué
  1236.       this.classList.add('active');
  1237.     });
  1238.   });
  1239. });
  1240. </script>
  1241.   <script
  1242.     type="text/javascript"
  1243.     src="{{ asset('Accueil/js/jquery.magnific-popup.min.js') }}"
  1244.   ></script>
  1245.   <script>
  1246. document.addEventListener('DOMContentLoaded', function () {
  1247.   const prevButtons = document.querySelectorAll('.btn-prev-day');
  1248.   const nextButtons = document.querySelectorAll('.btn-next-day');
  1249.   const dateCards = document.querySelectorAll('.date-card.modern-card');
  1250.   const collapseSections = document.querySelectorAll('.collapse');
  1251.   function navigateToDay(index) {
  1252.     if (index >= 0 && index < collapseSections.length) {
  1253.       // Fermer tous les jours
  1254.       collapseSections.forEach(s => s.classList.remove('show'));
  1255.       dateCards.forEach(c => c.classList.remove('active'));
  1256.       // Ouvrir le bon jour
  1257.       const targetCollapse = collapseSections[index];
  1258.       const targetCard = dateCards[index];
  1259.       if (targetCollapse && targetCard) {
  1260.         targetCollapse.classList.add('show');
  1261.         targetCard.classList.add('active');
  1262.       }
  1263.     }
  1264.   }
  1265.   prevButtons.forEach(button => {
  1266.     button.addEventListener('click', function () {
  1267.       const targetIndex = parseInt(this.dataset.target, 10);
  1268.       navigateToDay(targetIndex);
  1269.     });
  1270.   });
  1271.   nextButtons.forEach(button => {
  1272.     button.addEventListener('click', function () {
  1273.       const targetIndex = parseInt(this.dataset.target, 10);
  1274.       navigateToDay(targetIndex);
  1275.     });
  1276.   });
  1277. });
  1278. </script>
  1279.   <script>
  1280.     document.addEventListener('DOMContentLoaded', function() {
  1281.   const style = document.createElement('style');
  1282.   style.textContent = `
  1283.     .hidden {
  1284.       display: none !important;
  1285.     }
  1286.   `;
  1287.   document.head.appendChild(style);
  1288. });
  1289.     document.addEventListener('DOMContentLoaded', function() {
  1290.     // Get the favorite button
  1291.     const favoriteButton = document.querySelector('.fav-button');
  1292.     if (favoriteButton) {
  1293.       // Make it unclickable with JS too (belt and suspenders approach)
  1294.       favoriteButton.style.pointerEvents = 'none';
  1295.       
  1296.       // Override any existing click handlers
  1297.       favoriteButton.onclick = function(e) {
  1298.         e.preventDefault();
  1299.         e.stopPropagation();
  1300.         return false;
  1301.       };
  1302.       
  1303.       // Make sure hover still works
  1304.       favoriteButton.addEventListener('mouseover', function() {
  1305.         document.getElementById('purchase-alert').style.display = 'block';
  1306.       });
  1307.       
  1308.       // Keep any existing hover functionality
  1309.       if (typeof showSelection === 'function') {
  1310.         favoriteButton.onmouseover = showSelection;
  1311.       }
  1312.     }
  1313.     
  1314.     // Make sure the purchase alert remains interactive
  1315.     const purchaseAlert = document.getElementById('purchase-alert');
  1316.     if (purchaseAlert) {
  1317.       purchaseAlert.style.pointerEvents = 'auto';
  1318.     }
  1319.   });
  1320.     // Sélection des éléments
  1321.     const purchaseAlert = document.getElementById("purchase-alert");
  1322.     const alertContent = document.getElementById("purchase-alert-content");
  1323.     const likeCountLabel = document.getElementById("likeCount");
  1324.     const favoriteCount = parseInt(likeCountLabel.textContent.trim(), 10); // Convertir en nombre
  1325.     // Fonction pour mettre à jour le contenu de l'alerte
  1326.     function updatePurchaseAlert(current) {
  1327.   let remainingForAlbum = Math.max(0, 20 - current);
  1328.   let remainingForPochette = Math.max(0, 12 - current);
  1329.   let remainingForPack = Math.max(0, 12 - current);
  1330.   const progressBar = (count, total, color) => `
  1331.   <div style="margin: 5px 0;">
  1332.     <div style="background-color: #e9ecef; border-radius: 5px; overflow: hidden; height: 8px;">
  1333.       <div style="width: ${
  1334.         (count / total) * 100
  1335.       }%; background-color: ${color}; height: 100%;"></div>
  1336.     </div>
  1337.     <small style="font-size: 12px;">${count}/${total} photos</small>
  1338.   </div>
  1339. `;
  1340.   // Use Twig paths here:
  1341.   const products = [
  1342.       {
  1343.       name: "Pochette photo (12 photos)",
  1344.       required: 12,
  1345.       remaining: remainingForPochette,
  1346.       image: "/images/produit/PochettePhoto5sur5-2.jpg",
  1347.       color: "#2196f3",
  1348.       link: "{{ path('AjoutPochettePhotos_Favoris', {'nbr': 12}) }}",
  1349.     },
  1350.        {
  1351.       name: "Pack numérique (20 photos)",
  1352.       required: 20,
  1353.       remaining: remainingForAlbum,
  1354.       image: "/images/produit/photoNumerique.jpg",
  1355.       color: "#4caf50",
  1356.       link: "{{ path('PackPhotosNumerique_Favoris', {'nbr': 20}) }}",
  1357.     }
  1358.   
  1359.   
  1360.     
  1361.   ].sort((a, b) => a.remaining - b.remaining);
  1362.   const productList = products
  1363.     .map((product) => {
  1364.       const count = current;
  1365.       const total = product.required;
  1366.       const remaining = product.remaining;
  1367.       return `
  1368.     <li style="margin-bottom: 15px;">
  1369.       <div style="display: flex; align-items: center; gap: 10px;">
  1370.         <img
  1371.           src="${product.image}"
  1372.           alt="${product.name}"
  1373.           style="width: 65px; height: 65px; border-radius: 5px; margin-top:-19px"
  1374.         />
  1375.         <div style="flex: 1;">
  1376.           <strong style="font-size: 14px;">${product.name}</strong>
  1377.           ${progressBar(count, total, product.color)}
  1378.           ${
  1379.             remaining > 0
  1380.               ? `<small style="color: ${product.color}; font-size: 12px;">
  1381.                    Encore ${remaining} photos ❤️ pour compléter ${product.name.toLowerCase()}
  1382.                  </small>`
  1383.               : `<button
  1384.                   style="
  1385.                     margin-top: 5px;
  1386.                     padding: 5px 8px;
  1387.                     background-color: ${product.color};
  1388.                     color: white;
  1389.                     border: none;
  1390.                     border-radius: 5px;
  1391.                     font-size: 12px;
  1392.                     cursor: pointer;
  1393.                   "
  1394.                   onclick="window.location.href='${product.link}'"
  1395.                 >
  1396.                   Commander
  1397.                 </button>`
  1398.           }
  1399.         </div>
  1400.       </div>
  1401.     </li>
  1402.   `;
  1403.     })
  1404.     .join("");
  1405.   const plusButton = `
  1406.     <li style="margin-bottom: 15px; text-align: center;">
  1407.       <button
  1408.         style="
  1409.           padding: 5px 8px;
  1410.           background-color: #F56040;
  1411.           color: white;
  1412.           border: none;
  1413.           border-radius: 5px;
  1414.           font-size: 14px;
  1415.           line-height: 1;
  1416.           width: 150px;
  1417.           height: 40px;
  1418.           cursor: pointer;
  1419.         "
  1420.         onclick="window.location.href='{{ path('boutique5sur5') }}'"
  1421.       >
  1422.         Aller à la boutique
  1423.       </button>
  1424.     </li>
  1425.   `;
  1426.   if (current === 0) {
  1427.     alertContent.innerHTML = `
  1428.     <p style="font-size: 16px; font-weight: bold; color: #333;">
  1429.       Vous n'avez pas encore de photos favorites !
  1430.     </p>
  1431.     <p style="margin-bottom: 20px; color: #555;">
  1432.       Commencez à ajouter vos moments préférés pour profiter de nos offres.
  1433.     </p>
  1434.     <ul style="list-style-type: none; padding: 0;">${productList}${plusButton}</ul>
  1435.   `;
  1436.   } else {
  1437.     alertContent.innerHTML = `
  1438.     <p style="font-size: 16px; font-weight: bold; color: #333;">
  1439.       Vous avez atteint ${current} photos favorites !
  1440.     </p>
  1441.     <p style="margin-bottom: 20px; color: #555;">
  1442.       Profitez de nos offres spéciales :
  1443.     </p>
  1444.     <ul style="list-style-type: none; padding: 0;">${productList}${plusButton}</ul>
  1445.   `;
  1446.   }
  1447.   purchaseAlert.classList.remove("hidden");
  1448.   clearTimeout(purchaseAlertTimeout);
  1449.   purchaseAlertTimeout = setTimeout(() => {
  1450.     if (!purchaseAlert.matches(":hover")) {
  1451.       closePurchaseAlert();
  1452.     }
  1453.   }, 5000);
  1454. }
  1455.     // Fonction pour fermer l'alerte
  1456.     function closePurchaseAlert() {
  1457.       purchaseAlert.classList.add("hidden");
  1458.     }
  1459.     // Événement pour mettre à jour le contenu et afficher la popover dynamiquement au hover
  1460.     document.querySelector(".fav-button").addEventListener("mouseover", () => {
  1461.       updatePurchaseAlert(favoriteCount);
  1462.       purchaseAlert.classList.remove("cachee"); // Réaffiche la popover
  1463.     });
  1464.     function showSelection() {
  1465.       document.getElementById("purchase-alert").style.display = "block";
  1466.     }
  1467.     function hideSelection() {
  1468.       document.getElementById("selectionPopover").style.display = "none";
  1469.     }
  1470.     document.addEventListener("DOMContentLoaded", function () {
  1471.       const container = document.querySelector(".date-container");
  1472.       // Vérifie si le conteneur existe pour éviter les erreurs
  1473.       if (container) {
  1474.         container.scrollTo({
  1475.           left: container.scrollWidth, // Scroll directement à la position maximale
  1476.           behavior: "smooth", // Défilement fluide
  1477.         });
  1478.       }
  1479.     });
  1480.     document.addEventListener("DOMContentLoaded", function () {
  1481.       const container = document.querySelector(".date-container");
  1482.       const leftArrow = document.querySelector(".scroll-btn.left");
  1483.       const rightArrow = document.querySelector(".scroll-btn.right");
  1484.       // Fonction pour vérifier le débordement et activer/désactiver les flèches
  1485.       function updateArrowsVisibility() {
  1486.         const isOverflowing = container.scrollWidth > container.clientWidth; // Vérifie si débordement
  1487.         leftArrow.style.display = isOverflowing ? "flex" : "none";
  1488.         rightArrow.style.display = isOverflowing ? "flex" : "none";
  1489.       }
  1490.       // Fonction pour défiler
  1491.       function scrollContainer(direction) {
  1492.         container.scrollBy({
  1493.           left: direction === "left" ? -200 : 200, // Défiler à gauche ou à droite
  1494.           behavior: "smooth",
  1495.         });
  1496.       }
  1497.       // Ajout des événements de clic pour les flèches
  1498.       leftArrow.addEventListener("click", () => scrollContainer("left"));
  1499.       rightArrow.addEventListener("click", () => scrollContainer("right"));
  1500.       // Vérification initiale et sur redimensionnement de la fenêtre
  1501.       updateArrowsVisibility();
  1502.       window.addEventListener("resize", updateArrowsVisibility);
  1503.     });
  1504.     document.addEventListener("DOMContentLoaded", function () {
  1505.       const container = document.querySelector(".date-container");
  1506.       const leftBtn = document.querySelector(".scroll-btn.left");
  1507.       const rightBtn = document.querySelector(".scroll-btn.right");
  1508.       leftBtn.addEventListener("click", () => {
  1509.         container.scrollBy({
  1510.           left: -200, // Défile vers la gauche
  1511.           behavior: "smooth",
  1512.         });
  1513.       });
  1514.       rightBtn.addEventListener("click", () => {
  1515.         container.scrollBy({
  1516.           left: 200, // Défile vers la droite
  1517.           behavior: "smooth",
  1518.         });
  1519.       });
  1520.     });
  1521.  document.addEventListener("DOMContentLoaded", function () {
  1522.     // Sélectionnez tous les badges de filtre
  1523.     const filterBadges = document.querySelectorAll(".filter-badge");
  1524.     // Sélectionnez tous les éléments de la galerie
  1525.     const galleryItems = document.querySelectorAll(".column");
  1526.     // Sélectionnez tous les jours
  1527.     const days = document.querySelectorAll(".collapse");
  1528.     // Fonction pour réinitialiser les filtres
  1529.     function resetFilters() {
  1530.         // Réinitialisez tous les éléments de la galerie
  1531.         galleryItems.forEach((item) => {
  1532.             item.style.display = "block";
  1533.         });
  1534.         // Réinitialisez les états des badges
  1535.         filterBadges.forEach((badge) => badge.classList.remove("active"));
  1536.     }
  1537.     // Ajoutez un gestionnaire d'événements pour chaque badge
  1538.     filterBadges.forEach((badge) => {
  1539.         badge.addEventListener("click", function () {
  1540.             const filter = this.getAttribute("data-filter");
  1541.             // Réinitialisez l'état actif pour tous les badges
  1542.             filterBadges.forEach((btn) => btn.classList.remove("active"));
  1543.             // Ajoutez l'état actif au badge cliqué
  1544.             this.classList.add("active");
  1545.             // Affichez ou masquez les éléments de la galerie
  1546.             galleryItems.forEach((item) => {
  1547.                 if (filter === "all") {
  1548.                     item.style.display = "block";
  1549.                 } else if (filter === "photo" && item.querySelector("img")) {
  1550.                     item.style.display = "block";
  1551.                 } else if (filter === "video" && item.querySelector("video")) {
  1552.                     item.style.display = "block";
  1553.                 } else if (filter === "audio" && item.classList.contains("audio-message-item")) {
  1554.                     item.style.display = "block";
  1555.                 } else {
  1556.                     item.style.display = "none";
  1557.                 }
  1558.             });
  1559.         });
  1560.     });
  1561.     // Réinitialiser les filtres lors du changement de jour
  1562.     days.forEach((day) => {
  1563.         day.addEventListener("show.bs.collapse", function () {
  1564.             resetFilters();
  1565.         });
  1566.     });
  1567. });
  1568.     $(document).ready(function () {
  1569.       let zoomCounter = 0; // Initialize zoom counter
  1570.       let currentImageSrc = ""; // Track current image source
  1571.       let lastClickPosition = { x: 50, y: 50 }; // Default to center of image
  1572.       $(".container--gallery").magnificPopup({
  1573.         delegate: "a",
  1574.         type: "image",
  1575.         mainClass: "mfp-with-zoom mfp-img-mobile",
  1576.         image: {
  1577.           verticalFit: true,
  1578.         },
  1579.         gallery: {
  1580.           enabled: true,
  1581.           tPrev: "Previous (Left arrow key)", // Alt text on left arrow
  1582.           tNext: "Next (Right arrow key)", // Alt text on right arrow
  1583.           tCounter: "%curr% of %total%", // Markup for "1 of 7" counter
  1584.         },
  1585.         zoom: {
  1586.           enabled: true,
  1587.           duration: 300,
  1588.           opener: function (element) {
  1589.             return element.find("img");
  1590.           },
  1591.         },
  1592.         callbacks: {
  1593.           open: function () {
  1594.             // Get current image data from the link that was clicked
  1595.             const currentLink = this.currItem.el;
  1596.             const imageId =
  1597.               currentLink
  1598.                 .closest(".photo-zoom")
  1599.                 .find(".heart-icon")
  1600.                 .data("id") || "";
  1601.             const sejourId =
  1602.               currentLink
  1603.                 .closest(".photo-zoom")
  1604.                 .find(".heart-icon")
  1605.                 .data("sejour-id") || "";
  1606.             const imagePath =
  1607.               currentLink
  1608.                 .closest(".photo-zoom")
  1609.                 .find(".heart-icon")
  1610.                 .data("path") || "";
  1611.             const imageDesc =
  1612.               currentLink
  1613.                 .closest(".photo-zoom")
  1614.                 .find(".heart-icon")
  1615.                 .data("description") || "";
  1616.             const isFavorite = currentLink
  1617.               .closest(".photo-zoom")
  1618.               .find(".heart-icon i")
  1619.               .hasClass("bi-heart-fill");
  1620.             const favoriteIconClass = isFavorite ? "bi-heart-fill" : "bi-heart";
  1621.             const favoriteIconColor = isFavorite ? "#f56040" : "white";
  1622.             const favoriteTooltip = isFavorite
  1623.               ? "Retirer des favoris"
  1624.               : "Ajouter aux favoris";
  1625.             const zoomControls = `
  1626.           <div class="mfp-zoom-controls">
  1627.             <button class="zoom-btn zoom-out" title="Zoom Out"><i class="fa fa-search-minus"></i></button>
  1628.             <button class="zoom-btn zoom-in" title="Zoom In"><i class="fa fa-search-plus"></i></button>
  1629.           </div>
  1630.           <div class="mfp-favorite">
  1631.             <button class="favorite-btn" 
  1632.                     data-id="${imageId}" 
  1633.                     data-sejour-id="${sejourId}" 
  1634.                     data-path="${imagePath}" 
  1635.                     data-description="${imageDesc}"
  1636.                     title="${favoriteTooltip}">
  1637.               <i class="bi ${favoriteIconClass}" style="color: ${favoriteIconColor}; text-shadow: 0px 0px 3px rgba(0,0,0,0.5);"></i>
  1638.             </button>
  1639.           </div>
  1640.           <div class="mfp-counter"></div>
  1641.         `;
  1642.             $(".mfp-content").append(zoomControls);
  1643.             initializeZoomControls();
  1644.             initializeFavoriteButton();
  1645.             const intervalId = setInterval(() => {
  1646.               const newImageSrc = $(".mfp-img").attr("src");
  1647.               if (newImageSrc !== currentImageSrc) {
  1648.                 currentImageSrc = newImageSrc;
  1649.                 zoomCounter = 0;
  1650.                 lastClickPosition = { x: 50, y: 50 }; // Reset to center
  1651.                 attachZoomHandler(); // Reattach zoom handler to new image
  1652.                 $(".mfp-img").css({
  1653.                   "transform-origin": `${lastClickPosition.x}% ${lastClickPosition.y}%`,
  1654.                   transform: `scale(1)`,
  1655.                 });
  1656.                 // Update favorite button for the new image
  1657.                 updateFavoriteButton();
  1658.                 initializeZoomControls();
  1659.                 updateCounter();
  1660.               }
  1661.             }, 100);
  1662.             this.content.on("mfpClose", function () {
  1663.               clearInterval(intervalId);
  1664.             });
  1665.             attachZoomHandler();
  1666.           },
  1667.           close: function () {
  1668.             $(".mfp-zoom-controls").remove();
  1669.             $(".mfp-favorite").remove();
  1670.             $(".mfp-counter").remove();
  1671.             zoomCounter = 0;
  1672.           },
  1673.         },
  1674.       });
  1675.       function attachZoomHandler() {
  1676.         $(".mfp-img")
  1677.           .off("click")
  1678.           .on("click", function (event) {
  1679.             event.stopPropagation(); // Prevent default navigation behavior
  1680.             // Calculate click coordinates relative to the image
  1681.             const imgOffset = $(this).offset();
  1682.             const clickX = event.pageX - imgOffset.left;
  1683.             const clickY = event.pageY - imgOffset.top;
  1684.             const imgWidth = $(this).width();
  1685.             const imgHeight = $(this).height();
  1686.             // Calculate transform-origin based on click position
  1687.             lastClickPosition = {
  1688.               x: (clickX / imgWidth) * 100,
  1689.               y: (clickY / imgHeight) * 100,
  1690.             };
  1691.             // Cycle through zoom levels: 1x, 1.5x, 2x
  1692.             zoomCounter = (zoomCounter + 1) % 3;
  1693.             const zoomLevels = [1, 1.5, 2];
  1694.             const zoomLevel = zoomLevels[zoomCounter];
  1695.             $(this).css({
  1696.               "transform-origin": `${lastClickPosition.x}% ${lastClickPosition.y}%`,
  1697.               transform: `scale(${zoomLevel})`,
  1698.             });
  1699.             updateZoomButtonState();
  1700.           });
  1701.       }
  1702.       function initializeZoomControls() {
  1703.         $(".mfp-zoom-controls .zoom-in")
  1704.           .off("click")
  1705.           .on("click", function (event) {
  1706.             event.stopPropagation();
  1707.             zoomCounter = (zoomCounter + 1) % 3;
  1708.             const zoomLevels = [1, 1.5, 2];
  1709.             const zoomLevel = zoomLevels[zoomCounter];
  1710.             $(".mfp-img").css({
  1711.               "transform-origin": `${lastClickPosition.x}% ${lastClickPosition.y}%`,
  1712.               transform: `scale(${zoomLevel})`,
  1713.             });
  1714.             updateZoomButtonState();
  1715.           });
  1716.         $(".mfp-zoom-controls .zoom-out")
  1717.           .off("click")
  1718.           .on("click", function (event) {
  1719.             event.stopPropagation();
  1720.             if (zoomCounter > 0) {
  1721.               zoomCounter -= 1;
  1722.               const zoomLevels = [1, 1.5, 2];
  1723.               const zoomLevel = zoomLevels[zoomCounter];
  1724.               $(".mfp-img").css({
  1725.                 "transform-origin": `${lastClickPosition.x}% ${lastClickPosition.y}%`,
  1726.                 transform: `scale(${zoomLevel})`,
  1727.               });
  1728.               updateZoomButtonState();
  1729.             } else {
  1730.               $.magnificPopup.close();
  1731.             }
  1732.           });
  1733.       }
  1734.       function initializeFavoriteButton() {
  1735.         $(".mfp-favorite .favorite-btn")
  1736.           .off("click")
  1737.           .on("click", function (event) {
  1738.             event.stopPropagation();
  1739.             const $this = $(this);
  1740.             const imageId = $this.data("id");
  1741.             const sejourId = $this.data("sejour-id");
  1742.             // Toggle favorite status
  1743.             const isFavorite = $this.find("i").hasClass("bi-heart-fill");
  1744.             // Update the button appearance
  1745.             if (isFavorite) {
  1746.               $this
  1747.                 .find("i")
  1748.                 .removeClass("bi-heart-fill")
  1749.                 .addClass("bi-heart")
  1750.                 .css("color", "white");
  1751.               $this.attr("title", "Ajouter aux favoris");
  1752.             } else {
  1753.               $this
  1754.                 .find("i")
  1755.                 .removeClass("bi-heart")
  1756.                 .addClass("bi-heart-fill")
  1757.                 .css("color", "#f56040");
  1758.               $this.attr("title", "Retirer des favoris");
  1759.             }
  1760.             // Update the original heart icon in the gallery
  1761.             const originalHeartIcon = $(
  1762.               `.heart-icon[data-id="${imageId}"]`
  1763.             ).find("i");
  1764.             if (isFavorite) {
  1765.               originalHeartIcon
  1766.                 .removeClass("bi-heart-fill")
  1767.                 .addClass("bi-heart")
  1768.                 .css("color", "");
  1769.             } else {
  1770.               originalHeartIcon
  1771.                 .removeClass("bi-heart")
  1772.                 .addClass("bi-heart-fill")
  1773.                 .css("color", "#f56040");
  1774.             }
  1775.             // Make AJAX call to update favorite status in the backend using Parent routes
  1776.             $.ajax({
  1777.               url: isFavorite ? "/Parent/aSupprimerFav" : "/Parent/ajouterFav",
  1778.               type: "POST",
  1779.               data: {
  1780.                 id: imageId,
  1781.                 idSejour: sejourId,
  1782.               },
  1783.               success: function (response) {
  1784.                 // Optional: Show a success message or handle response
  1785.                 console.log("Favorite status updated", response);
  1786.               },
  1787.               error: function (error) {
  1788.                 console.error("Error updating favorite status", error);
  1789.                 // Revert the icon change on error
  1790.                 if (isFavorite) {
  1791.                   $this
  1792.                     .find("i")
  1793.                     .removeClass("bi-heart")
  1794.                     .addClass("bi-heart-fill")
  1795.                     .css("color", "#f56040");
  1796.                   originalHeartIcon
  1797.                     .removeClass("bi-heart")
  1798.                     .addClass("bi-heart-fill")
  1799.                     .css("color", "#f56040");
  1800.                 } else {
  1801.                   $this
  1802.                     .find("i")
  1803.                     .removeClass("bi-heart-fill")
  1804.                     .addClass("bi-heart")
  1805.                     .css("color", "white");
  1806.                   originalHeartIcon
  1807.                     .removeClass("bi-heart-fill")
  1808.                     .addClass("bi-heart")
  1809.                     .css("color", "");
  1810.                 }
  1811.               },
  1812.             });
  1813.           });
  1814.       }
  1815.       function updateFavoriteButton() {
  1816.         // Get current image data from the current slide
  1817.         const currentSlide = $.magnificPopup.instance.currItem.el;
  1818.         const photoZoom = currentSlide.closest(".photo-zoom");
  1819.         if (photoZoom.length) {
  1820.           const heartIcon = photoZoom.find(".heart-icon");
  1821.           const imageId = heartIcon.data("id") || "";
  1822.           const sejourId = heartIcon.data("sejour-id") || "";
  1823.           const imagePath = heartIcon.data("path") || "";
  1824.           const imageDesc = heartIcon.data("description") || "";
  1825.           const isFavorite = heartIcon.find("i").hasClass("bi-heart-fill");
  1826.           const favoriteIconClass = isFavorite ? "bi-heart-fill" : "bi-heart";
  1827.           const favoriteIconColor = isFavorite ? "#f56040" : "white";
  1828.           const favoriteTooltip = isFavorite
  1829.             ? "Retirer des favoris"
  1830.             : "Ajouter aux favoris";
  1831.           // Update the favorite button
  1832.           const $favoriteBtn = $(".mfp-favorite .favorite-btn");
  1833.           $favoriteBtn.data("id", imageId);
  1834.           $favoriteBtn.data("sejour-id", sejourId);
  1835.           $favoriteBtn.data("path", imagePath);
  1836.           $favoriteBtn.data("description", imageDesc);
  1837.           $favoriteBtn.attr("title", favoriteTooltip);
  1838.           $favoriteBtn
  1839.             .find("i")
  1840.             .removeClass("bi-heart bi-heart-fill")
  1841.             .addClass(favoriteIconClass)
  1842.             .css("color", favoriteIconColor);
  1843.         }
  1844.       }
  1845.       function updateZoomButtonState() {
  1846.         const zoomLevels = [1, 1.5, 2];
  1847.         const currentZoom = zoomLevels[zoomCounter];
  1848.         $(".zoom-in").prop("disabled", currentZoom === 2);
  1849.         $(".zoom-out").prop("disabled", currentZoom === 1);
  1850.       }
  1851.       function updateCounter() {
  1852.         const counterText = $(".mfp-counter")
  1853.           .closest(".mfp-content")
  1854.           .find(".mfp-counter")
  1855.           .text();
  1856.         const matches = counterText.match(/(\d+) of (\d+)/);
  1857.         if (matches) {
  1858.           const currentIndex = matches[1];
  1859.           const totalImages = matches[2];
  1860.           $(".mfp-counter").text(`${currentIndex} of ${totalImages}`);
  1861.         }
  1862.       }
  1863.       // Add CSS for the favorite button and rounded image corners
  1864.       $("<style>")
  1865.         .prop("type", "text/css")
  1866.         .html(
  1867.           `
  1868.       .mfp-favorite {
  1869.         position: absolute;
  1870.         top: 15px;
  1871.         left: 15px;
  1872.         z-index: 1046;
  1873.       }
  1874.       .favorite-btn {
  1875.         background: transparent;
  1876.         border: none;
  1877.         font-size: 24px;
  1878.         padding: 5px;
  1879.         cursor: pointer;
  1880.         outline: none;
  1881.       }
  1882.       .favorite-btn i {
  1883.         transition: all 0.3s ease;
  1884.       }
  1885.       .favorite-btn:hover i {
  1886.         transform: scale(1.2);
  1887.       }
  1888.       /* Rounded corners for zoomed images */
  1889.       .mfp-img {
  1890.         border-radius: 8px;
  1891.       }
  1892.       /* Make sure the container doesn't clip the rounded corners */
  1893.       .mfp-figure:after {
  1894.         border-radius: 8px;
  1895.       }
  1896.     `
  1897.         )
  1898.         .appendTo("head");
  1899.     });
  1900.   </script>
  1901. <script>
  1902. document.addEventListener('DOMContentLoaded', function () {
  1903.   const openBtn = document.getElementById('openFavoritesBtn');
  1904.   const closeBtn = document.getElementById('closeSidebarBtn');
  1905.   const sidebar = document.getElementById('favoritesSidebar');
  1906.   const tbody = document.querySelector('#favoritesTable tbody');
  1907.   openBtn.addEventListener('click', async () => {
  1908.     try {
  1909.       const response = await fetch('/Parent/mes-favoris', {
  1910.         headers: {
  1911.           'Accept': 'application/json'
  1912.         }
  1913.       });
  1914.       const result = await response.json();
  1915.       if (!result.success || !Array.isArray(result.data)) {
  1916.         alert('Erreur lors du chargement des favoris.');
  1917.         return;
  1918.       }
  1919.       tbody.innerHTML = '';
  1920.       result.data.forEach((fav, index) => {
  1921.         const row = document.createElement('tr');
  1922.         row.innerHTML = `
  1923.           <td>${index + 1}</td>
  1924.           <td><img src="${fav.path}" alt="favori"></td>
  1925.           <td>${fav.descreption || '—'}</td>
  1926.           <td>${fav.created_at}</td>
  1927.         `;
  1928.         tbody.appendChild(row);
  1929.       });
  1930.       sidebar.classList.add('active');
  1931.     } catch (e) {
  1932.       console.error('Erreur réseau:', e);
  1933.       alert('Impossible de charger les favoris.');
  1934.     }
  1935.   });
  1936.   closeBtn.addEventListener('click', () => {
  1937.     sidebar.classList.remove('active');
  1938.   });
  1939. });
  1940. </script>
  1941.   <script>
  1942.         // Fonction pour vérifier et afficher l'alerte
  1943.         function checkFavorites() {
  1944.             if (favoriteCount >= 10) {
  1945.                 purchaseAlert.style.display = 'block'; // Affiche l'alerte
  1946.             } else {
  1947.                 purchaseAlert.style.display = 'none'; // Cache l'alerte si le nombre est réduit
  1948.             }
  1949.         }
  1950.         // Ajout d'un favori
  1951.         function addFavorite() {
  1952.             favoriteCount++;
  1953.             likeCountLabel.textContent = favoriteCount;
  1954.             checkFavorites();
  1955.         }
  1956.         // Suppression d'un favori
  1957.         function removeFavorite() {
  1958.             if (favoriteCount > 0) {
  1959.                 favoriteCount--;
  1960.                 likeCountLabel.textContent = favoriteCount;
  1961.                 checkFavorites();
  1962.             }
  1963.         }document.addEventListener('DOMContentLoaded', () => {
  1964.     const favoriteCount = {{ nblikes }};
  1965.     updateCardContent(favoriteCount);
  1966. });
  1967. function updateCardContent(favoriteCount) {
  1968.     const card = document.getElementById('dynamic-card');
  1969.     const cardContent = document.getElementById('dynamic-card-content');
  1970.     let produits = [];
  1971.     if (favoriteCount >= 20) {
  1972.         produits.push({
  1973.             titre: "Album débloqué !",
  1974.             bouton: "Commander",
  1975.             image: "/images/produit/Album5sur5-3.jpg",
  1976.             lien: "{{ path('EditionAlbum') }}"
  1977.         });
  1978.     }
  1979.     if (favoriteCount >= 12) {
  1980.         produits.push({
  1981.             titre: "Pochette débloquée !",
  1982.             bouton: "Commander",
  1983.             image: "/images/produit/PochettePhoto5sur5-2.jpg",
  1984.             lien: "{{ path('AjoutPochettePhotos_Favoris', {'nbr': 12}) }}"
  1985.         });
  1986.     }
  1987.     if (favoriteCount >= 5) {
  1988.         produits.push({
  1989.             titre: "Pack numérique débloqué !",
  1990.             bouton: "Commander",
  1991.             image: "/images/produit/photoNumerique.jpg",
  1992.             lien: "{{ path('PackPhotosNumerique_Favoris', {'nbr': 15}) }}"
  1993.         });
  1994.     }
  1995.     if (produits.length === 0) {
  1996.         cardContent.innerHTML = `
  1997.             <div style="text-align: center; padding: 10px;">
  1998.                 Ajoutez des favoris pour débloquer des surprises ✨
  1999.             </div>
  2000.         `;
  2001.         return;
  2002.     }
  2003.     cardContent.innerHTML = `
  2004.     <div class="splide" id="dynamicSplide">
  2005.       <div class="splide__track">
  2006.         <ul class="splide__list">
  2007.           ${produits.map(produit => `
  2008.             <li class="splide__slide" style="position: relative;">
  2009.               <img src="${produit.image}" alt="${produit.titre}" style="width: 100%; height: 150px; object-fit: cover; border-radius: 8px;">
  2010.               <div style="position: absolute; bottom: 0; left: 0; right: 0; background: rgba(0,0,0,0.1); color: white; padding: 10px; text-align: center; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;">
  2011.                 <div style="font-weight: bold; font-size: 14px;">${produit.titre}</div>
  2012.                 <button style="margin-top: 5px; padding: 5px 8px; background-color: #F56040; color: white; border: none; border-radius: 4px; font-size: 12px; cursor: pointer;" onclick="window.location.href='${produit.lien}'">
  2013.                   ${produit.bouton}
  2014.                 </button>
  2015.               </div>
  2016.             </li>
  2017.           `).join('')}
  2018.         </ul>
  2019.       </div>
  2020.     </div>
  2021.     `;
  2022.     // Monte le carrousel
  2023.     new Splide('#dynamicSplide', {
  2024.         type: 'loop',
  2025.         arrows: true,
  2026.         pagination: false,
  2027.         autoplay: true,
  2028.         interval: 4000,
  2029.         speed: 800,
  2030.     }).mount();
  2031. }
  2032.         function supprimerFavoris($id, $idSejour) {
  2033.             // Vider l'élément coeur pour ce favori
  2034.             const coeurElement = $('#coeur' + $id);
  2035.             coeurElement.empty();
  2036.             // Ajout d'une animation sur le bouton favori
  2037.             const favoriteButton = document.querySelector('.fav-button');
  2038.             if (favoriteButton) {
  2039.                 favoriteButton.classList.add('active');
  2040.                 // Retirer l'animation après qu'elle soit jouée
  2041.                 setTimeout(() => {
  2042.                     favoriteButton.classList.remove('active');
  2043.                 }, 600); // La durée doit correspondre à celle de l'animation
  2044.             }
  2045.             // Mise à jour de l'icône coeur
  2046.             const clas = $('.IconImag6').hasClass('active') ? "IconDelete IconDeletesix" : "IconDelete";
  2047.             coeurElement.html(
  2048.                 `<i class="bi bi-heart ${clas}" onclick="AddFavoris(${$id}, ${$idSejour})"></i>`
  2049.             );
  2050.             // Mettre à jour le compteur des favoris
  2051.             const likeCountLabel = document.getElementById('likeCount');
  2052.            const likeMesFavLabel = document.getElementById('mesFavCount');
  2053.              if (likeMesFavLabel) {
  2054.                 let currentCount = parseInt(likeMesFavLabel.textContent.trim(), 10) || 0;
  2055.                 currentCount = Math.max(0, currentCount - 1); // Empêche le compteur d'aller en dessous de 0
  2056.                 likeMesFavLabel.textContent = currentCount;
  2057.             }
  2058.             if (likeCountLabel) {
  2059.                 let currentCount = parseInt(likeCountLabel.textContent.trim(), 10) || 0;
  2060.                 currentCount = Math.max(0, currentCount - 1); // Empêche le compteur d'aller en dessous de 0
  2061.                 likeCountLabel.textContent = currentCount;
  2062.                 // Mettre à jour la valeur dans l'input hidden
  2063.                 const nbFavCurrentInput = $('#nbFavCurrent');
  2064.                 if (nbFavCurrentInput.length) {
  2065.                     nbFavCurrentInput.val(currentCount);
  2066.                 }
  2067.             }
  2068.             // Préparation des données pour l'Ajax
  2069.             const $_data = { 'id': $id, 'idSejour': $idSejour };
  2070.             // Appel Ajax pour supprimer le favori
  2071.             $.ajax({
  2072.                 type: "POST",
  2073.                 url: "{{ path('Supprimer_fav') }}",
  2074.                 data: $_data,
  2075.                 success: function () {
  2076.                     // Réactiver les icônes après succès
  2077.                     $('.IconDelete').each(function () {
  2078.                         $(this).css('pointer-events', '');
  2079.                     });
  2080.                 },
  2081.                 error: function (xhr, status, error) {
  2082.                     console.error('Erreur lors de la suppression du favori :', error);
  2083.                 }
  2084.             });
  2085.         }
  2086.         function AddFavoris($id, $idSejour, $urlimg, $description) {
  2087.            // console.log('Adding favorite:', { attachmentId, sejourId, path, description });
  2088.   $("#close-favorites-btn").click()
  2089.             favoriteButton.classList.add('active');
  2090.    const likeMesFavLabel = document.getElementById('mesFavCount');
  2091.       
  2092.             const likeCountLabel = document.getElementById('likeCount');
  2093.             if (likeCountLabel) {
  2094.                 let currentCount = parseInt(likeCountLabel.textContent.trim(), 10) || 0;
  2095.                 likeCountLabel.textContent = currentCount + 1;
  2096.                      likeMesFavLabel.textContent = currentCount + 1;
  2097.             }
  2098.         // Retirer l'animation après qu'elle soit jouée
  2099.         setTimeout(() => {
  2100.             favoriteButton.classList.remove('active');
  2101.         }, 600); // La durée doit correspondre à celle de l'animation
  2102.             $('#coeur' + $id).empty();
  2103.             var clas = $('.IconImag6').hasClass('active') ? "IconDelete IconDeletesix" : "IconDelete";
  2104.             $('#coeur' + $id).html("<i class=\"bi bi-heart-fill favSelect " + clas + "\" onclick=\"supprimerFavoris(" + $id + "," + $idSejour + ")\"></i>");
  2105.             var $total = parseInt($("#totalLike").html()) + 1;
  2106.             $("#totalLike").html($total);
  2107.             $("#totalLikeTitle").html($total);
  2108.             $("#totalLikeMobile").html($total);
  2109.             var $data = { 'id': $id, 'idSejour': $idSejour };
  2110.             $.ajax({
  2111.                 type: "POST",
  2112.                 url: "{{ path('Ajouter_fav') }}",
  2113.                 data: $data,
  2114.                 success: function () {
  2115.                     $('.IconDelete').each(function () {
  2116.                         $(this).css('pointer-events', '');
  2117.                     });
  2118.                     if ($description === undefined) {
  2119.                         $description = ''; // Set it to an empty string
  2120.                     }
  2121.                     $('.rowMaselection').append(
  2122.                         '<div class="column" id="column-' + $id + '">'+
  2123.                         '<a style="position: relative;" title="Enlever de ma sélection" onclick="supprimerFavoris(' + $id + ',' + $idSejour + ')" class="iconeSuppImg"><i class="bi bi-x" style="font-size:17px;cursor:pointer;color:#d30909;float:right;margin-top:-3%;margin-right:2%"></i></a>'+
  2124.                         '<a class="photo-zoom">'+
  2125.                         '<img data-idAtach="'+$id+'" id="'+$idSejour+'" src="'+$urlimg+'"></a>'+
  2126.                         ($description ? '<h4 id="commint" class="titleHeadPhoto">'+$description+'</h4>' : '')+ // Only add the <h4> if $description is not empty
  2127.                         '</div>'
  2128.                     );
  2129.                     // Directly update nbLikes count in the header
  2130.                     var currentNbLikes = parseInt($('#favoris-link-Accueilpayment .nbrpanier').text());
  2131.                     var newNbLikes = currentNbLikes + 1;
  2132.                     $('#favoris-link-Accueilpayment .nbrpanier').text(newNbLikes);
  2133.                 },
  2134.                 error: function (xhr, status, error) {
  2135.                     console.error('Error:', error);
  2136.                 }
  2137.             });
  2138.         }
  2139.         $(document).on('click', '.bi-heart, .bi-heart-fill', function () {
  2140.         const heartIcon       = $(this);
  2141.         const heartContainer  = heartIcon.closest('.heart-icon');
  2142.         // Extract data attributes
  2143.         const attachmentId    = heartContainer.data('id');
  2144.         const sejourId        = heartContainer.data('sejour-id');
  2145.         const path            = heartContainer.data('path');
  2146.         const description     = heartContainer.data('description');
  2147.         const isFavorite      = heartIcon.hasClass('bi-heart-fill');
  2148.         // Get the input that contains the favorite count
  2149.         const likeFavInput    = document.getElementById('nbFavCurrent');
  2150.         let favoriteNb        = parseInt(likeFavInput.value, 10);
  2151.         if (isFavorite) {
  2152.             // Remove from favorites
  2153.             supprimerFavoris(attachmentId, sejourId);
  2154.             favoriteNb = Math.max(0, favoriteNb - 1);
  2155.             likeFavInput.value = favoriteNb;
  2156.             updateCardContent(favoriteNb);
  2157.               updateFavoritesSidebar();
  2158.                  $("#close-favorites-btn").click()
  2159.         } else {
  2160.             // Add to favorites
  2161.             AddFavoris(attachmentId, sejourId, path, description);
  2162.             favoriteNb = favoriteNb + 1;
  2163.             likeFavInput.value = favoriteNb;
  2164.             updateCardContent(favoriteNb);
  2165.        
  2166.             updateFavoritesSidebar();
  2167.                $("#close-favorites-btn").click()
  2168.         }
  2169.         // **** SIMPLE STEP: Update the purchase alert ****
  2170.         // This will refresh the progress bars, count, etc.
  2171.         updatePurchaseAlert(favoriteNb);
  2172.     });
  2173.         // Gestion dynamique du clic sur les icônes cœur
  2174.         $(document).on('click', '.bi-hsddddeart, .bi-hdddeart-fill', function () {
  2175.             const heartIcon = $(this);
  2176.           //  const heartIcon = $(this);
  2177.             //const attachmentId = heartIcon.data('id'); // Récupère l'ID directement
  2178.             const attachmentId = heartIcon.closest('.heart-icon').attr('id').replace('coeur', '');
  2179.             const sejourId = heartIcon.data('sejour-id'); // Store the sejour ID in a data attribute
  2180.             const isFavorite = heartIcon.hasClass('bi-heart-fill');
  2181.             // Récupérer l'input contenant le nombre de favoris
  2182.             const likeFavInput = document.getElementById('nbFavCurrent');
  2183.             let favoriteNb = parseInt(likeFavInput.value, 10); // Utiliser .value pour les inputs
  2184.             // Validation pour éviter les NaN
  2185.             if (isNaN(favoriteNb)) {
  2186.                 favoriteNb = 0;
  2187.             }
  2188.             if (isFavorite) {
  2189.                 // Si c'est un favori, le supprimer
  2190.                 supprimerFavoris(attachmentId, sejourId);
  2191.                 // Décrémenter le compteur
  2192.                 favoriteNb = Math.max(0, favoriteNb - 1);
  2193.                 likeFavInput.value = favoriteNb; // Mettre à jour la valeur de l'input
  2194.                 // Mettre à jour dynamiquement le contenu des cartes ou popovers
  2195.                 updateCardContent(favoriteNb);
  2196.             } else {
  2197.                 // Si ce n'est pas un favori, l'ajouter
  2198.                 const path = heartIcon.data('path'); // Path de l'attachement
  2199.                 const description = heartIcon.data('description'); // Description de l'attachement
  2200.                 AddFavoris(attachmentId, sejourId, path, description);
  2201.           // Décrémenter le compteur
  2202.                 favoriteNb = Math.max(0, favoriteNb + 1);
  2203.                 likeFavInput.value = favoriteNb; // Mettre à jour la valeur de l'input
  2204.                 // Incrémenter le compteur
  2205.                 // Mettre à jour dynamiquement le contenu des cartes ou popovers
  2206.                 updateCardContent(favoriteNb);
  2207.             }
  2208.             // Mettre à jour dynamiquement la popover ou d'autres éléments liés
  2209.         });
  2210.         // Ajoutez les événements sur les icônes de cœur
  2211.         document.querySelectorAll('.IconDelete').forEach((icon) => {
  2212.             icon.addEventListener('click', (event) => {
  2213.                 const isFavorite = icon.classList.contains('bi-heart-fill');
  2214.                 if (isFavorite) {
  2215.                     removeFavorite();
  2216.                     icon.classList.remove('bi-heart-fill');
  2217.                     icon.classList.add('bi-heart');
  2218.                 } else {
  2219.                     addFavorite();
  2220.                     icon.classList.remove('bi-heart');
  2221.                     icon.classList.add('bi-heart-fill');
  2222.                 }
  2223.             });
  2224.         });
  2225.         // Vérifie l'état initial
  2226.         checkFavorites();
  2227.   </script>
  2228.   <!-- Initialisation -->
  2229.   <script>
  2230.     AOS.init({
  2231.       duration: 800, // Duration of animations in milliseconds
  2232.       easing: "ease-in-out", // Animation timing function
  2233.     });
  2234.     document.addEventListener("DOMContentLoaded", function () {
  2235.       const dateCards = document.querySelectorAll(".date-card");
  2236.       const sections = document.querySelectorAll(".collapse");
  2237.       dateCards.forEach((card) => {
  2238.         card.addEventListener("click", function () {
  2239.           // Supprimer les classes actives des autres cartes et sections
  2240.           dateCards.forEach((c) => c.classList.remove("active"));
  2241.           sections.forEach((s) => s.classList.remove("show"));
  2242.           // Ajouter la classe active à la carte cliquée
  2243.           this.classList.add("active");
  2244.           // Récupérer la cible et afficher la bonne section
  2245.           const targetId = this.getAttribute("data-bs-target");
  2246.           const targetSection = document.querySelector(targetId);
  2247.           if (targetSection) {
  2248.             targetSection.classList.add("show");
  2249.           }
  2250.         });
  2251.       });
  2252.     });
  2253.     document.addEventListener("DOMContentLoaded", function () {
  2254.       // Initialisation du carrousel Splide
  2255.       var splide = new Splide("#imageSlider", {
  2256.         type: "loop",
  2257.         perPage: 1,
  2258.         autoplay: true,
  2259.         interval: 6000,
  2260.         pauseOnHover: false,
  2261.         pauseOnFocus: false,
  2262.         pagination: false, // Désactive la pagination
  2263.         arrows: false,
  2264.       });
  2265.       splide.mount();
  2266.       // Fonction pour faire défiler automatiquement vers la section suivante avec un ajustement personnalisé de la hauteur
  2267.       function scrollToNextSection() {
  2268.         const targetSection = document.getElementById("scrollTarget");
  2269.         if (targetSection) {
  2270.           const targetPosition =
  2271.             targetSection.getBoundingClientRect().top + window.scrollY; // Position de la section
  2272.           const adjustedPosition = targetPosition - 50; // Réduit la hauteur du scroll de 150px (ajustez selon vos besoins)
  2273.           // Scroll vers la position ajustée
  2274.           window.scrollTo({
  2275.             top: adjustedPosition,
  2276.             behavior: "smooth",
  2277.           });
  2278.         }
  2279.       }
  2280.       // Démarrer le timer pour le scroll automatique après 10 secondes
  2281.       setTimeout(scrollToNextSection, 5000); // 10 secondes
  2282.     });
  2283.   </script>
  2284.   <script>
  2285.         document.addEventListener('DOMContentLoaded', function () {
  2286.             var myModal = new bootstrap.Modal(document.getElementById('PubProd'));
  2287.             myModal.show();
  2288.         });
  2289.         // Function to close the modal
  2290.     function closeModal() {
  2291.         var myModal = bootstrap.Modal.getInstance(document.getElementById('PubProd'));
  2292.         if (myModal) {
  2293.             myModal.hide();
  2294.         }
  2295.     }
  2296.     const favoriteButton = document.querySelector('.fav-button');
  2297.     favoriteButton.addEventListener('click', () => {
  2298.         // Ajouter la classe 'active' pour déclencher l'éclat
  2299.         favoriteButton.classList.add('active');
  2300.         // Retirer l'animation après qu'elle soit jouée
  2301.         setTimeout(() => {
  2302.             favoriteButton.classList.remove('active');
  2303.         }, 600); // La durée doit correspondre à celle de l'animation
  2304.     });
  2305.     
  2306.     //const HeartAddButton = document.querySelector('.IconDelete');
  2307.     $(".IconDelete").on('click', () => {
  2308.         // Ajouter la classe 'active' pour déclencher l'éclat
  2309.         favoriteButton.classList.add('active');
  2310.         // Retirer l'animation après qu'elle soit jouée
  2311.         setTimeout(() => {
  2312.             favoriteButton.classList.remove('active');
  2313.         }, 600); // La durée doit correspondre à celle de l'animation
  2314.     });
  2315.     $(document).ready(function() {
  2316.         // Attach click event to collapse triggers
  2317.         const lastCard = $('.date-card.modern-card.active');
  2318.         const lastTargetId = lastCard.attr('data-bs-target');
  2319.         if (lastTargetId) {
  2320.             $(lastTargetId).collapse('show'); // Expand the last collapse section
  2321.             LoadImagesCloud($(lastTargetId)); // Load images for the last day
  2322.         }
  2323.         $('[data-bs-toggle="collapse"]').on('click', function() {
  2324.             var targetId = $(this).attr('data-bs-target'); // Get the target ID
  2325.             $('.date-card.modern-card').removeClass('active'); // Remove 'active' class from all cards
  2326.             $(this).addClass('active'); // Add 'active' class to the clicked card
  2327.             LoadImagesCloud($(targetId)); // Ensure this function works as expected
  2328.                // Hide all other collapses except the one clicked
  2329.                $('[data-bs-target]').each(function() {
  2330.                 var currentTargetId = $(this).attr('data-bs-target');
  2331.                 // If the current collapse is not the one clicked, hide it
  2332.                 if (currentTargetId !== targetId) {
  2333.                     $(currentTargetId).collapse('hide');
  2334.                     //$('[data-bs-toggle="collapse"]').removeClass('active'); // Remove active class from all cards
  2335.                     //Modifier leurs style en non active aussi
  2336.                 }
  2337.             });
  2338.         });
  2339.     });
  2340.     function rotateIcone(iconId) {
  2341.         // Use the icon ID to target the specific element
  2342.         var icon = $('#' + iconId);
  2343.         // Toggle the rotate-right class to apply rotation
  2344.         if (icon.hasClass('rotate-right')) {
  2345.             icon.removeClass('rotate-right'); // Remove rotation class
  2346.         } else {
  2347.             icon.addClass('rotate-right'); // Add rotation class
  2348.         }
  2349.     }
  2350.             $(document).ready(function () {
  2351.                 $total1 = parseInt($("#esphoto").find('strong').html().replace('(', '').replace(')', ''));
  2352.                 $('[data-bs-toggle="tooltip"]').tooltip();
  2353.                 {% if app.session.get("paymentmoniteco") %}
  2354.                 {% if app.session.get("paymentmoniteco") == "succses" %}
  2355.                 Swal.fire({
  2356.                     icon: 'success',
  2357.                     title: ' succès ',
  2358.                     text: 'votre commande est validée'
  2359.                 });
  2360.                 {% endif %}
  2361.                 {% endif %}
  2362.                 if ($total1 > 0) {
  2363.                     $('.iconeFleche').first().click();
  2364.                     //  $([document.documentElement, document.body]).animate({
  2365.                     //  scrollTop: $('.iconeFleche').last().offset().top
  2366.                     //  }, );
  2367.                 }
  2368.                 else {
  2369.                     $(window).scrollTop(0);
  2370.                 }
  2371.                 var slider = $('.responsive').slick({
  2372.                     infinite: true,
  2373.                     slidesToShow: 1,
  2374.                     slidesToScroll: 1,
  2375.                     autoplay: true,
  2376.                     autoplaySpeed: 4000,
  2377.                     pauseOnFocus: false,
  2378.                     pauseOnHover: false,
  2379.                     draggable: false,
  2380.                     fade: true
  2381.                 });
  2382.                 $('.responsive').css('display', 'block');
  2383.                 $('.namePRD').css('display', 'block');
  2384.                 var currSlide = 0;
  2385.                 var nextSlide = 0;
  2386.                 slider.on('afterChange', function (event, slick, currentSlide) {
  2387.                     console.log(typeof ($('.slick-active .slick-current').find('.imgproduit2')) != "undefined");
  2388.                     if (typeof ($('.slick-active .slick-current').find('.imgproduit2')) != "undefined") {
  2389.                         setTimeout(function () {
  2390.                             $('.slick-active .imgproduit1').removeClass('animated fadeIn');
  2391.                             $('.slick-active .imgproduit1').addClass('animated fadeOut');
  2392.                             $('.slick-active .imgproduit1').css('display', 'none');
  2393.                             $('.slick-active .imgproduit2').css('display', 'block');
  2394.                             $('.slick-active .imgproduit2').removeClass('animated fadeOut');
  2395.                             $('.slick-active .imgproduit2').addClass('animated fadeIn');
  2396.                         }, 2000);
  2397.                     }
  2398.                 });
  2399.                 slider.on('beforeChange', function (event, slick, currentSlide, nextSlide) {
  2400.                     currSlide = currentSlide;
  2401.                     $('.imgproduit2').each(function () {
  2402.                         $(this).removeClass('animated fadeIn');
  2403.                         $(this).addClass('animated fadeOut');
  2404.                         $(this).css('display', 'none');
  2405.                     });
  2406.                     $('.imgproduit1').each(function () {
  2407.                         $(this).css('display', 'block');
  2408.                         $(this).removeClass('animated fadeOut');
  2409.                         $(this).addClass('animated fadeIn');
  2410.                     });
  2411.                 });
  2412.                 $('.columnPub').each(function () {
  2413.                     $(this).slick({
  2414.                         infinite: true,
  2415.                         speed: 50,
  2416.                         fade: true,
  2417.                         slidesToShow: 1,
  2418.                         slidesToScroll: 1,
  2419.                         autoplay: true,
  2420.                         pauseOnFocus: false,
  2421.                         pauseOnHover: false,
  2422.                         draggable: false
  2423.                     });
  2424.                     $(this).css('display', 'block');
  2425.                 });
  2426.                 $("#offrePack").click();
  2427.                 {%if app.user.showpubprod != 'false' %}
  2428.                 $('#btnPubProd').click();
  2429.                 $('.modal-backdrop').css('background-color', 'rgba(0, 0, 0, 0.2)');
  2430.                 {% endif %}
  2431.             });
  2432.             $("#closeImage").click(function () {
  2433.                 $('#myModalImage').css('display', "none");
  2434.             });
  2435.             $.ajax({
  2436.                 type: "POST",
  2437.                 url: "{{ path("delateSession_parent") }}",
  2438.                 success: function () { }
  2439.             });
  2440.             function afficheDiv(elem) {
  2441.                 $('.nav-link').each(function () {
  2442.                     $(this).removeClass('active');
  2443.                 });
  2444.                 elem.addClass('active');
  2445.                 if (elem.attr('id') === "esphoto" || elem.attr('id') === "esphotoMobile") {
  2446.                     $("#espacphoto").show();
  2447.                     $("#espacemessage").hide();
  2448.                     $("#espaceMa_selection").hide();
  2449.                     pageMenu = 'MonSejour'
  2450.                     $(this).addClass('active');
  2451.                    $('#imageActifphoto').css('display', 'block');
  2452.                      $('#imagenoActifphoto').css('display', 'none');
  2453.                    $('#VocalActivee').css('display', 'none');
  2454.                      $('#noActifVocal').css('display', 'block');
  2455.                 }
  2456.                 if (elem.attr('id') === "esmessage" || elem.attr('id') === "esmessageMobile") {
  2457.                     $("#espacphoto").hide();
  2458.                     $("#espaceMa_selection").hide();
  2459.                     $("#espacemessage").show();
  2460.                     pageMenu = 'BoiteVocale'
  2461.                     $("#espaceMa_selection").hide();
  2462.                     $(this).addClass('active');
  2463.                   $('#imageActifphoto').css('display', 'none');
  2464.                      $('#imagenoActifphoto').css('display', 'block');
  2465.                    $('#VocalActivee').css('display', 'block');
  2466.                      $('#noActifVocal').css('display', 'none');
  2467.                 }
  2468.                 if (elem.attr('id') === "esselection" || elem.attr('id') === "esselectionMobile") {
  2469.                     $("#espacphoto").hide();
  2470.                     $("#espacemessage").hide();
  2471.                     $("#espaceMa_selection").show();
  2472.                     $(homeNavmob).removeClass('bi bi-house-door-fill');
  2473.                     $(homeNavmob).addClass('bi bi-house-door');
  2474.                     $(micromob).removeClass('bi bi-mic-fill');
  2475.                     $(micromob).addClass('bi bi-mic');
  2476.                     $(selecNavmob).removeClass('bi bi-heart');
  2477.                     $(selecNavmob).addClass('bi bi-heart-fill');
  2478.                 }
  2479.             }
  2480.             function LoadImagesCloud($element) {
  2481.                 $element.find('.photo-zoom img').each(function ($this) {
  2482.                     if ($(this).attr('data-src') != $(this).attr('src')) {
  2483.                         $(this).attr('src', $(this).attr('data-src'));
  2484.                     }
  2485.                 });
  2486.             }
  2487.       function afficheDivFooterMobile(elem) {
  2488.              if(elem =='esphotoMobile') {
  2489.                    $("#espacphoto").show();
  2490.                     $("#espacemessage").hide();
  2491.                     $("#espaceMa_selection").hide();
  2492.                     $("#storevide").hide();
  2493.                     $("#storefull").show();
  2494.                     $("#fullphoto").show();
  2495.                     $("#videphoto").hide()
  2496.                     $("#vocalfull").hide();
  2497.                     $("#vocalvide").show();
  2498.                 }
  2499.                 if (elem === "esmessageMobile" ) {
  2500.                     $("#espacphoto").hide();
  2501.                     $("#espacemessage").show();
  2502.                     $("#espaceMa_selection").hide();
  2503.                     $("#storefull").hide();
  2504.                     $("#storevide").show();
  2505.                     $("#fullphoto").hide();
  2506.                     $("#videphoto").show()
  2507.                     $("#vocalfull").show();
  2508.                     $("#vocalvide").hide();
  2509.                 }
  2510.             }
  2511.             function permutation(elem) {
  2512.                 $(".IconImag").each(function () {
  2513.                     $(this).removeClass('active');
  2514.                 });
  2515.                 elem.addClass("active");
  2516.             }
  2517.             function per(elem) {
  2518.                 $(".list-group-item ").each(function () {
  2519.                     $(this).removeClass('show');
  2520.                 });
  2521.                 elem.addClass("active");
  2522.                 $("#iconeFleche").addClass('active');
  2523.             }
  2524.            function setidattach(id) {
  2525.                 $("#idattachipmut").val(id)
  2526.             }
  2527.             var ParentAjouterALL_fav = "{{ path('ParentAjouterALL_fav') }}";
  2528.             function AllFavoris($idSejour) {
  2529.                 $('#SelectALL').html('Désélectionner tout');
  2530.                 $('#SelectALL').css('pointer-events', 'none');
  2531.                 $('#SelectALL').css('opacity', '0.5');
  2532.                 $('#SelectALL').css('cursor', 'no-drop');
  2533.                 $('#SelectALL1').html('Désélectionner tout');
  2534.                 $('#SelectALL1').css('pointer-events', 'none');
  2535.                 $('#SelectALL1').css('opacity', '0.5');
  2536.                 $('#SelectALL1').css('cursor', 'no-drop');
  2537.                 $data = { 'idSejour': $idSejour }
  2538.                 $.ajax({
  2539.                     type: "POST",
  2540.                     url: "{{ path('ParentAjouterALL_fav') }}",
  2541.                     data: $data,
  2542.                     success: function () {
  2543.                         location.reload();
  2544.                     }
  2545.                 });
  2546.             }
  2547.             function RemoveAllFavoris($idSejour) {
  2548.                 $('#SelectALL').html('Sélectionner tout');
  2549.                 $('#SelectALL').css('pointer-events', 'none');
  2550.                 $('#SelectALL').css('opacity', '0.5');
  2551.                 $('#SelectALL').css('cursor', 'no-drop');
  2552.                 $('#SelectALL1').html('Sélectionner tout');
  2553.                 $('#SelectALL1').css('pointer-events', 'none');
  2554.                 $('#SelectALL1').css('opacity', '0.5');
  2555.                 $('#SelectALL1').css('cursor', 'no-drop');
  2556.                 $data = { 'idSejour': $idSejour }
  2557.                 $.ajax({
  2558.                     type: "POST",
  2559.                     url: "{{ path('ParentSupprimer_ALLfav') }}",
  2560.                     data: $data,
  2561.                     success: function () {
  2562.                         location.reload();
  2563.                     }
  2564.                 });
  2565.             }
  2566.             // Get the elements with class="column"
  2567.             var elements = document.getElementsByClassName("column");
  2568.             // Declare a "loop" variable
  2569.             var i;
  2570.             // Full-width images
  2571.             function Four() {
  2572.                 for (i = 0; i < elements.length; i++) {
  2573.                     elements[i].style.flex = "0 0 25%";
  2574.                 }
  2575.                 $('.IconDelete').attr('class', 'IconDelete ');
  2576.                 $('.photo-zoom ').attr('class', 'photo-zoom');
  2577.                 $('.localistaion').css('visibility', 'visible');
  2578.                 $('.localistaion').attr('class', 'localistaion');
  2579.                 $('.legend').css('visibility', 'visible');
  2580.                 $('.columnPub').each(function () {
  2581.                     $(this).css('max-width', '25%');
  2582.                     $(this).find('.slick-list').removeClass('miniature');
  2583.                     $(this).find('.single_service').removeClass('miniature');
  2584.                     $(this).find('.bottomdivpub').removeClass('miniature');
  2585.                 });
  2586.             }
  2587.             // Two images side by side
  2588.             function six() {
  2589.                 for (i = 0; i < elements.length; i++) {
  2590.                     elements[i].style.flex = "0 0 15%";
  2591.                 }
  2592.                 $('.column').css('padding', '0px 10px 0px 0px');
  2593.                 $('.localistaion').attr('class', 'localistaion localistaionsix');
  2594.                 $('.IconDelete').attr('class', 'IconDelete IconDeletesix');
  2595.                 $('.legend').css('visibility', 'visible');
  2596.                 $('.photo-zoom ').attr('class', 'photo-zoom heightimg');
  2597.                 $('.columnPub').each(function () {
  2598.                     $(this).css('max-width', '15%');
  2599.                     $(this).find('.slick-list').addClass('miniature');
  2600.                     $(this).find('.single_service').addClass('miniature');
  2601.                     $(this).find('.bottomdivpub').addClass('miniature');
  2602.                 });
  2603.             }
  2604.             // Four images side by side
  2605.             function two() {
  2606.                 for (i = 0; i < elements.length; i++) {
  2607.                     elements[i].style.flex = "0 0 40%";
  2608.                 }
  2609.                 $('.column').css('padding', '14px 10px');
  2610.                 $('.column').css('max-width', '40%');
  2611.                 $('.localistaion').css('visibility', 'visible');
  2612.                 $('.legend').css('visibility', 'visible');
  2613.                 $('.photo-zoom ').attr('class', 'photo-zoom');
  2614.                 $('.localistaion').attr('class', 'localistaion localistaiontwo');
  2615.                 $('.IconDelete').attr('class', 'IconDelete IconDeletetwo');
  2616.                 $('.legend').attr('class', 'legend legendtwo');
  2617.                 $('.columnPub').each(function () {
  2618.                     $(this).css('max-width', '40%');
  2619.                     $(this).find('.slick-list').removeClass('miniature');
  2620.                     $(this).find('.single_service').removeClass('miniature');
  2621.                     $(this).find('.bottomdivpub').removeClass('miniature');
  2622.                 });
  2623.             }
  2624.             function hidePopPub() {
  2625.                 $('.modal-backdrop').css('background-color', 'rgb(0, 0, 0)');
  2626.             }
  2627.             function changeHref(elem, newhref) {
  2628.                 $(elem).parent().attr('href', newhref);
  2629.             }
  2630.             function VerifNbLikes(nblikes) {
  2631.                 $('#allerAlaBoutique').click();
  2632.             }
  2633.     function handleMenuClick(menuId, pageMenu) {
  2634.         // Reset all icons
  2635.         document.getElementById('imagenoActifphoto').style.display = 'block';
  2636.         document.getElementById('imageActifphoto').style.display = 'none';
  2637.         document.getElementById('nofavorisVocal').style.display = 'block';
  2638.         document.getElementById('favorisActive').style.display = 'none';
  2639.         document.getElementById('noActifVocal').style.display = 'block';
  2640.         document.getElementById('VocalActivee').style.display = 'none';
  2641.         // Set selected icon
  2642.         if (menuId === 'photo') {
  2643.             document.getElementById('imagenoActifphoto').style.display = 'none';
  2644.             document.getElementById('imageActifphoto').style.display = 'block';
  2645.         } else if (menuId === 'selection') {
  2646.             document.getElementById('nofavorisVocal').style.display = 'none';
  2647.             document.getElementById('favorisActive').style.display = 'block';
  2648.         } else if (menuId === 'message') {
  2649.             document.getElementById('noActifVocal').style.display = 'none';
  2650.             document.getElementById('VocalActivee').style.display = 'block';
  2651.         }
  2652.         // Handle any other necessary logic
  2653.         $('#list-tab-photo').removeClass('show');
  2654.         $('#list-tab-message').removeClass('show');
  2655.         afficheDiv($(`#${menuId}`));
  2656.     }
  2657.   </script>
  2658.   <script>
  2659.     $(document).ready(function () {
  2660.       $("#PubProd").on("hidden.bs.modal", function () {
  2661.         $(document).trigger("modalClosed");
  2662.       });
  2663.     });
  2664.   </script>
  2665.   <script>
  2666.     $(document).ready(function () {
  2667.       $("#noShow").on("change", function () {
  2668.         if ($(this).is(":checked")) {
  2669.           $.ajax({
  2670.             url: "/Parent/showpub",
  2671.             type: "POST",
  2672.             dataType: "json",
  2673.             success: function (response) {
  2674.               if (response.status === "success") {
  2675.                 console.log("User showpubprod updated successfully.");
  2676.               } else {
  2677.                 console.log("Error:", response.message);
  2678.               }
  2679.             },
  2680.             error: function (xhr, status, error) {
  2681.               console.log("AJAX Error:", error);
  2682.             },
  2683.           });
  2684.         }
  2685.       });
  2686.     });
  2687.   </script>
  2688. </div>
  2689. <!-- Script pour la sidebar des favoris -->
  2690. <script>
  2691.   $(document).ready(function() {
  2692.     // Ouvrir la sidebar
  2693.     $("#openFavoritesSidebar").click(function() {
  2694.       $(".favorites-sidebar").addClass("open");
  2695.       loadFavorites();
  2696.     });
  2697.     
  2698.     // Fermer la sidebar
  2699.     $(".favorites-close").click(function() {
  2700.       $(".favorites-sidebar").removeClass("open");
  2701.     });
  2702.     
  2703.     // Charger les favoris
  2704.     function loadFavorites() {
  2705.       $.ajax({
  2706.         url: "/Parent/mes-favoris",
  2707.         type: "GET",
  2708.         dataType: "json",
  2709.         beforeSend: function() {
  2710.           $("#favorites-grid").html("<div style='text-align:center'>Chargement...</div>");
  2711.         },
  2712.         success: function(data) {
  2713.           $("#favorites-grid").empty();
  2714.           
  2715.           if (data.data && data.data.length > 0) {
  2716.             $("#favorites-empty-state").hide();
  2717.             
  2718.             $.each(data.data, function(i, fav) {
  2719.               var item = $("<div class='favorite-item'></div>");
  2720.               var img = $("<img>").attr("src", fav.path).attr("alt", fav.descreption || "Photo favorite");
  2721.               var overlay = $("<div class='favorite-overlay'></div>");
  2722.         
  2723.               
  2724.               btn.click(function(e) {
  2725.                 e.preventDefault();
  2726.                 e.stopPropagation();
  2727.                 removeFavorite(fav.id);
  2728.               });
  2729.               
  2730.               overlay.append(btn);
  2731.               item.append(img).append(overlay);
  2732.               $("#favorites-grid").append(item);
  2733.             });
  2734.             
  2735.             $("#favorites-counter").text(data.data.length);
  2736.             var percentage = (data.data.length / 10) * 100;
  2737.             $("#favorites-progress").css("width", percentage + "%");
  2738.             
  2739.           } else {
  2740.             $("#favorites-empty-state").show();
  2741.             $("#favorites-counter").text("0");
  2742.             $("#favorites-progress").css("width", "0%");
  2743.           }
  2744.         },
  2745.         error: function() {
  2746.           $("#favorites-grid").html("<div style='color:red;text-align:center'>Erreur de chargement</div>");
  2747.         }
  2748.       });
  2749.     }
  2750.     
  2751.     // Supprimer un favori
  2752.     function removeFavorite(id) {
  2753.       $.ajax({
  2754.         url: "/Parent/remove-favorite/" + id,
  2755.         type: "POST",
  2756.         success: function() {
  2757.           loadFavorites();
  2758.           
  2759.           // Mettre à jour le compteur global
  2760.           var count = parseInt($("#likeCount").text());
  2761.           if (!isNaN(count)) {
  2762.             $("#likeCount").text(count - 1);
  2763.           }
  2764.           
  2765.           var countFav = parseInt($("#mesFavCount").text());
  2766.           if (!isNaN(countFav)) {
  2767.             $("#mesFavCount").text(countFav - 1);
  2768.           }
  2769.         },
  2770.         error: function() {
  2771.           alert("Erreur lors de la suppression du favori");
  2772.         }
  2773.       });
  2774.     }
  2775.   });
  2776. </script>
  2777. <!-- Script pour la sidebar des favoris -->
  2778. <script>
  2779. $(document).ready(function() {
  2780.     // Fonctions pour ouvrir/fermer la sidebar
  2781.     $("#openFavoritesSidebar").click(function() {
  2782.         $("#favorites-sidebar").css("right", "0");
  2783.         loadFavorites();
  2784.     });
  2785.     
  2786.     $("#close-favorites-btn").click(function() {
  2787.         $("#favorites-sidebar").css("right", "-400px");
  2788.     });
  2789.     
  2790.     // Fermer en cliquant en dehors
  2791.     $(document).click(function(event) {
  2792.         if (!$(event.target).closest("#favorites-sidebar").length && 
  2793.             !$(event.target).closest("#openFavoritesSidebar").length && 
  2794.             $("#favorites-sidebar").css("right") === "0px") {
  2795.             $("#favorites-sidebar").css("right", "-400px");
  2796.         }
  2797.     });
  2798.     
  2799.    // Variables globales
  2800. let selectedFavorites = [];
  2801. let allFavorites = [];
  2802. let coverPhotoId = null; // ID de la photo de couverture
  2803. // Fonction pour mettre à jour la sidebar
  2804. function loadFavorites() {
  2805.     $("#favorites-grid").html("<div style='text-align:center;padding:20px;'>Chargement...</div>");
  2806.     
  2807.     $.ajax({
  2808.         url: "/Parent/mes-favoris",
  2809.         type: "GET",
  2810.         dataType: "json",
  2811.         success: function(data) {
  2812.             $("#favorites-grid").empty();
  2813.             allFavorites = data.data || [];
  2814.             
  2815.             if (allFavorites.length > 0) {
  2816.                 $("#favorites-empty-state").hide();
  2817.                 
  2818.                 // Ajouter l'option de photo de couverture au-dessus de la grille
  2819.                 if (!$("#cover-photo-section").length) {
  2820.                     const coverSection = $(`
  2821.                         <div id="cover-photo-section" style="margin-bottom:15px;">
  2822.                             <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;">
  2823.                                 <h4 style="margin:0;font-size:15px;color:#333;">Photo de couverture</h4>
  2824.                                 <span style="font-size:12px;color:#777;">Pour la personnalisation des produits</span>
  2825.                             </div>
  2826.                             <div id="cover-photo-container" style="height:120px;background:#f5f5f5;border-radius:8px;display:flex;align-items:center;justify-content:center;overflow:hidden;position:relative;border:1px dashed #ccc;">
  2827.                                 <div id="cover-photo-placeholder" style="text-align:center;padding:15px;color:#777;">
  2828.                                     <i class="bi bi-image" style="font-size:24px;display:block;margin-bottom:8px;"></i>
  2829.                                     <p style="margin:0;font-size:13px;">Sélectionnez une photo comme couverture</p>
  2830.                                 </div>
  2831.                                 <div id="cover-photo-preview" style="display:none;width:100%;height:100%;position:relative;">
  2832.                                     <img src="" style="width:100%;height:100%;object-fit:cover;" />
  2833.                                     <button id="remove-cover-photo" style="position:absolute;top:5px;right:5px;background:#F56040;color:white;border:none;width:24px;height:24px;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;">
  2834.                                         <i class="bi bi-x"></i>
  2835.                                     </button>
  2836.                                 </div>
  2837.                             </div>
  2838.                         </div>
  2839.                     `);
  2840.                     
  2841.                     $("#photos-content").prepend(coverSection);
  2842.                     
  2843.                     // Événement pour retirer la photo de couverture
  2844.                     $("#remove-cover-photo").click(function(e) {
  2845.                         e.stopPropagation();
  2846.                         setCoverPhoto(null);
  2847.                     });
  2848.                 }
  2849.                 
  2850.                 // Mettre à jour l'affichage de la photo de couverture
  2851.                 updateCoverPhotoDisplay();
  2852.                 
  2853.                 // Générer la grille de photos
  2854.                 $.each(allFavorites, function(i, fav) {
  2855.                     var isSelected = selectedFavorites.includes(fav.id);
  2856.                     var isCoverPhoto = (coverPhotoId === fav.id);
  2857.                     
  2858.                     // Conteneur principal avec styles conditionnels
  2859.                     var item = $("<div class='favorite-item' data-id='" + fav.id + "' style='position:relative;border-radius:8px;overflow:hidden;aspect-ratio:1;cursor:pointer;transition:all 0.2s;border:3px solid " + (isSelected ? "#F56040" : (isCoverPhoto ? "#4CAF50" : "transparent")) + ";'></div>");
  2860.                     
  2861.                     var img = $("<img style='width:100%;height:100%;object-fit:cover;'>").attr("src", fav.path).attr("alt", fav.descreption || "Photo favorite");
  2862.                     
  2863.                     // Badge de sélection
  2864.                     var selectionBadge = $("<div class='selection-badge' style='position:absolute;top:5px;right:5px;width:22px;height:22px;border-radius:50%;background:#F56040;display:" + (isSelected ? "flex" : "none") + ";align-items:center;justify-content:center;color:white;font-size:12px;z-index:10;'><i class='bi bi-check'></i></div>");
  2865.                     
  2866.                     // Badge de photo de couverture
  2867.                     var coverBadge = $("<div class='cover-badge' style='position:absolute;top:5px;left:5px;padding:2px 6px;background:#4CAF50;color:white;font-size:10px;border-radius:3px;display:" + (isCoverPhoto ? "block" : "none") + ";z-index:10;'><i class='bi bi-star-fill' style='margin-right:3px;font-size:8px;'></i>Couverture</div>");
  2868.                     
  2869.                     // Overlay simple pour effet au survol
  2870.                     var hoverOverlay = $("<div class='hover-overlay' style='position:absolute;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.2);opacity:0;transition:opacity 0.2s;z-index:5;'></div>");
  2871.                     
  2872.                     // Actions sur hover
  2873.                     var actionsOverlay = $("<div class='actions-overlay' style='position:absolute;bottom:5px;left:5px;right:5px;display:flex;justify-content:center;gap:8px;opacity:0;transition:opacity 0.2s;z-index:15;'></div>");
  2874.                     
  2875.                     // Bouton pour définir comme photo de couverture
  2876.                     var setCoverBtn = $("<button style='background:" + (isCoverPhoto ? "#4CAF50" : "rgba(255,255,255,0.8)") + ";color:" + (isCoverPhoto ? "white" : "#333") + ";border:none;border-radius:3px;font-size:11px;padding:5px 8px;cursor:pointer;'><i class='bi bi-star" + (isCoverPhoto ? "-fill" : "") + "' style='margin-right:3px;'></i>Couverture</button>");
  2877.                     
  2878.                     setCoverBtn.click(function(e) {
  2879.                         e.stopPropagation();
  2880.                         if (isCoverPhoto) {
  2881.                             setCoverPhoto(null);
  2882.                         } else {
  2883.                             setCoverPhoto(fav.id);
  2884.                         }
  2885.                     });
  2886.                     
  2887.                     actionsOverlay.append(setCoverBtn);
  2888.                     
  2889.                     // Ajouter effet de survol
  2890.                     item.hover(
  2891.                         function() { 
  2892.                             $(this).find(".hover-overlay").css("opacity", "1");
  2893.                             $(this).find(".actions-overlay").css("opacity", "1");
  2894.                         },
  2895.                         function() { 
  2896.                             $(this).find(".hover-overlay").css("opacity", "0");
  2897.                             $(this).find(".actions-overlay").css("opacity", "0");
  2898.                         }
  2899.                     );
  2900.                     
  2901.                     // Gérer le clic pour la sélection
  2902.                     item.click(function(e) {
  2903.                         e.stopPropagation();
  2904.                         toggleSelection($(this).data('id'));
  2905.                     });
  2906.                     
  2907.                     item.append(img).append(hoverOverlay).append(selectionBadge).append(coverBadge).append(actionsOverlay);
  2908.                     
  2909.                     // Ajouter explicitement une classe pour le style
  2910.                     item.addClass("no-trash-button");
  2911.                     
  2912.                     $("#favorites-grid").append(item);
  2913.                 });
  2914.                 
  2915.                 // Supprimer tout bouton de suppression qui pourrait être ajouté dynamiquement
  2916.                 setTimeout(function() {
  2917.                     $(".favorite-item .remove-favorite, .favorite-item button:has(.bi-trash), .favorite-overlay button").remove();
  2918.                 }, 100);
  2919.                 
  2920.                 $("#favorites-counter").text(allFavorites.length);
  2921.                 $("#openFavoritesSidebar span").text(allFavorites.length);
  2922.                 updateProductsView();
  2923.                 
  2924.             } else {
  2925.                 $("#favorites-empty-state").show();
  2926.                 $("#favorites-counter").text("0");
  2927.                 $("#openFavoritesSidebar span").text("0");
  2928.                 $("#selection-count").text("0");
  2929.                 updateProductsView();
  2930.             }
  2931.         },
  2932.         error: function() {
  2933.             $("#favorites-grid").html("<div style='color:red;text-align:center;padding:20px;'>Erreur de chargement</div>");
  2934.         }
  2935.     });
  2936. }
  2937. // Fonction pour définir la photo de couverture
  2938. function setCoverPhoto(id) {
  2939.     coverPhotoId = id;
  2940.     
  2941.     // Mettre à jour l'affichage
  2942.     updateCoverPhotoDisplay();
  2943.     
  2944.     // Mettre à jour le style des photos dans la grille
  2945.     $(".favorite-item").each(function() {
  2946.         const itemId = $(this).data('id');
  2947.         const isSelected = selectedFavorites.includes(itemId);
  2948.         const isCover = (itemId === coverPhotoId);
  2949.         
  2950.         // Mettre à jour la bordure
  2951.         $(this).css("border", "3px solid " + (isSelected ? "#F56040" : (isCover ? "#4CAF50" : "transparent")));
  2952.         
  2953.         // Mettre à jour le badge de couverture
  2954.         $(this).find(".cover-badge").css("display", isCover ? "block" : "none");
  2955.         
  2956.         // Mettre à jour le bouton de couverture
  2957.         const coverBtn = $(this).find(".actions-overlay button:first");
  2958.         coverBtn.css({
  2959.             "background": isCover ? "#4CAF50" : "rgba(255,255,255,0.8)",
  2960.             "color": isCover ? "white" : "#333"
  2961.         });
  2962.         coverBtn.find("i").attr("class", "bi bi-star" + (isCover ? "-fill" : ""));
  2963.     });
  2964.     
  2965.     // Enregistrer l'ID de la photo de couverture (si nécessaire pour le backend)
  2966.     if (id) {
  2967.         console.log("Photo de couverture définie avec l'ID:", id);
  2968.         // Ici vous pouvez ajouter une requête AJAX pour enregistrer ce choix sur le serveur
  2969.         
  2970.         // Ajouter automatiquement la photo de couverture à la sélection si elle n'y est pas déjà
  2971.         if (!selectedFavorites.includes(id)) {
  2972.             toggleSelection(id);
  2973.         }
  2974.     } else {
  2975.         console.log("Photo de couverture supprimée");
  2976.     }
  2977. }
  2978. // Mettre à jour l'affichage de la photo de couverture
  2979. function updateCoverPhotoDisplay() {
  2980.     if (coverPhotoId) {
  2981.         // Trouver la photo correspondante
  2982.         const coverPhoto = allFavorites.find(fav => fav.id === coverPhotoId);
  2983.         if (coverPhoto) {
  2984.             $("#cover-photo-placeholder").hide();
  2985.             $("#cover-photo-preview").show();
  2986.             $("#cover-photo-preview img").attr("src", coverPhoto.path);
  2987.         } else {
  2988.             // Si l'ID ne correspond à aucune photo (cas rare)
  2989.             coverPhotoId = null;
  2990.             $("#cover-photo-placeholder").show();
  2991.             $("#cover-photo-preview").hide();
  2992.         }
  2993.     } else {
  2994.         $("#cover-photo-placeholder").show();
  2995.         $("#cover-photo-preview").hide();
  2996.     }
  2997. }
  2998. // Modifier la fonction updateProductsView pour tenir compte de la photo de couverture
  2999. function updateProductsView() {
  3000.     const current = selectedFavorites.length;
  3001.     const hasCoverPhoto = coverPhotoId !== null;
  3002.     
  3003.     $("#product-photo-count").text(current);
  3004.     
  3005.     let remainingForAlbum = Math.max(0, 20 - current);
  3006.     let remainingForPochette = Math.max(0, 12 - current);
  3007.     let remainingForPack = Math.max(0, 12 - current);
  3008.     const progressBar = (count, total, color) => `
  3009.         <div style="margin: 5px 0;">
  3010.             <div style="background-color: #e9ecef; border-radius: 5px; overflow: hidden; height: 8px;">
  3011.                 <div style="width: ${(count / total) * 100}%; background-color: ${color}; height: 100%;"></div>
  3012.             </div>
  3013.             <small style="font-size: 12px;">${count}/${total} photos</small>
  3014.         </div>
  3015.     `;
  3016.     // Liste des produits
  3017.     const products = [
  3018.         {
  3019.             name: "Pochette photo (12 photos)",
  3020.             required: 12,
  3021.             remaining: Math.max(0, 12 - current),
  3022.             image: "/images/produit/PochettePhoto5sur5-2.jpg",
  3023.             color: "#2196f3",
  3024.             link: "{{ path('AjoutPochettePhotos_Favoris', {'nbr': 12}) }}",
  3025.             needsCover: true
  3026.         },
  3027.         {
  3028.             name: "Pack numérique (20 photos)",
  3029.             required: 20,
  3030.             remaining: Math.max(0, 20 - current),
  3031.             image: "/images/produit/photoNumerique.jpg",
  3032.             color: "#4caf50",
  3033.             link: "{{ path('PackPhotosNumerique_Favoris', {'nbr': 20}) }}",
  3034.             needsCover: false
  3035.         },
  3036.        
  3037.       
  3038.     ].sort((a, b) => a.remaining - b.remaining);
  3039.     const productList = products
  3040.         .map((product) => {
  3041.             const count = current;
  3042.             const total = product.required;
  3043.             const remaining = product.remaining;
  3044.             const coverRequired = product.needsCover && !hasCoverPhoto;
  3045.             return `
  3046.                 <li style="margin-bottom: 20px; position: relative;">
  3047.                     ${coverRequired ? `<div style="position: absolute; top: 0; right: 0; background: #FFC107; color: #333; font-size: 10px; padding: 2px 6px; border-radius: 3px; z-index: 5;">
  3048.                         <i class="bi bi-exclamation-triangle"></i> Photo de couverture requise
  3049.                     </div>` : ''}
  3050.                     <div style="display: flex; align-items: center; gap: 10px;">
  3051.                         <img src="${product.image}" alt="${product.name}" style="width: 70px; height: 70px; border-radius: 5px; object-fit: cover;" />
  3052.                         <div style="flex: 1;">
  3053.                             <strong style="font-size: 14px;">${product.name}</strong>
  3054.                             ${progressBar(count, total, product.color)}
  3055.                             ${
  3056.                                 remaining > 0
  3057.                                 ? `<small style="color: ${product.color}; font-size: 12px;">
  3058.                                     Encore ${remaining} photos pour compléter ${product.name.toLowerCase()}
  3059.                                 </small>`
  3060.                                 : coverRequired
  3061.                                 ? `<button
  3062.                                     style="
  3063.                                         margin-top: 5px;
  3064.                                         padding: 6px 12px;
  3065.                                         background-color: #FFC107;
  3066.                                         color: #333;
  3067.                                         border: none;
  3068.                                         border-radius: 5px;
  3069.                                         font-size: 13px;
  3070.                                         cursor: pointer;
  3071.                                     "
  3072.                                     onclick="$('#tab-photos').click(); /* Rediriger vers l'onglet photos */"
  3073.                                 >
  3074.                                     Choisir une couverture
  3075.                                 </button>`
  3076.                                 : `<button
  3077.                                     style="
  3078.                                         margin-top: 5px;
  3079.                                         padding: 6px 12px;
  3080.                                         background-color: ${product.color};
  3081.                                         color: white;
  3082.                                         border: none;
  3083.                                         border-radius: 5px;
  3084.                                         font-size: 13px;
  3085.                                         cursor: pointer;
  3086.                                     "
  3087.                                     onclick="window.location.href='${product.link}'"
  3088.                                 >
  3089.                                     Commander
  3090.                                 </button>`
  3091.                             }
  3092.                         </div>
  3093.                     </div>
  3094.                 </li>
  3095.             `;
  3096.         })
  3097.         .join("");
  3098.     const boutiqueButton = `
  3099.         <li style="margin-top: 25px; text-align: center;">
  3100.             <button
  3101.                 style="
  3102.                     padding: 8px 15px;
  3103.                     background-color: #F56040;
  3104.                     color: white;
  3105.                     border: none;
  3106.                     border-radius: 5px;
  3107.                     font-size: 14px;
  3108.                     width: 170px;
  3109.                     height: 40px;
  3110.                     cursor: pointer;
  3111.                 "
  3112.                 onclick="window.location.href='{{ path('boutique5sur5') }}'"
  3113.             >
  3114.                 Voir toute la boutique
  3115.             </button>
  3116.         </li>
  3117.     `;
  3118.     $("#product-list").html(productList + boutiqueButton);
  3119. }
  3120. });
  3121. </script>
  3122. {% endblock %}