templates/Accueil/album.html.twig line 1

Open in your IDE?
  1. {# * Product Gallery Page - 5sur5séjour * Clean rewrite with self-contained
  2. styles * Original purpose: Display products with image galleries and ordering
  3. capability #} {% extends 'Accueil/layoutAccueil.html.twig' %} {% block
  4. stylesheets %}
  5. {{ parent() }}
  6. <style>
  7.   /* ============================================
  8.            5sur5séjour Product Gallery - Clean Styles
  9.            ============================================ */
  10.   :root {
  11.     --primary: #41a2aa;
  12.     --primary-dark: #359ba3;
  13.     --primary-light: rgba(65, 162, 170, 0.1);
  14.     --orange: #f56040;
  15.     --text-dark: #1a1a1a;
  16.     --text-muted: #6b7280;
  17.     --bg-light: #f8fafb;
  18.     --white: #ffffff;
  19.     --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.08);
  20.     --shadow-md: 0 4px 20px rgba(0, 0, 0, 0.1);
  21.     --shadow-lg: 0 8px 30px rgba(0, 0, 0, 0.15);
  22.     --radius-sm: 8px;
  23.     --radius-md: 12px;
  24.     --radius-lg: 20px;
  25.   }
  26.   /* Page Container */
  27.   .product-page {
  28.     background: var(--bg-light);
  29.     min-height: 100vh;
  30.     padding: 40px 20px;
  31.   }
  32.   .product-container {
  33.     max-width: 1200px;
  34.     margin: 0 auto;
  35.   }
  36.   /* Login Modal */
  37.   .login-modal-overlay {
  38.     display: none;
  39.     position: fixed;
  40.     top: 0;
  41.     left: 0;
  42.     right: 0;
  43.     bottom: 0;
  44.     background: rgba(0, 0, 0, 0.5);
  45.     z-index: 10000;
  46.     align-items: center;
  47.     justify-content: center;
  48.   }
  49.   .login-modal-overlay.active {
  50.     display: flex;
  51.   }
  52.   .login-modal {
  53.     background: var(--white);
  54.     border-radius: var(--radius-lg);
  55.     padding: 32px;
  56.     max-width: 400px;
  57.     width: 90%;
  58.     text-align: center;
  59.     box-shadow: var(--shadow-lg);
  60.   }
  61.   .login-modal h3 {
  62.     color: var(--text-dark);
  63.     font-size: 20px;
  64.     font-weight: 600;
  65.     margin-bottom: 24px;
  66.   }
  67.   .login-modal-close {
  68.     position: absolute;
  69.     top: 16px;
  70.     right: 16px;
  71.     background: none;
  72.     border: none;
  73.     font-size: 24px;
  74.     cursor: pointer;
  75.     color: var(--text-muted);
  76.   }
  77.   /* Product Card */
  78.   .product-card {
  79.     display: none;
  80.     background: var(--white);
  81.     border-radius: var(--radius-lg);
  82.     box-shadow: var(--shadow-md);
  83.     overflow: hidden;
  84.     margin-bottom: 30px;
  85.   }
  86.   .product-card.active {
  87.     display: block;
  88.   }
  89.   .product-card-inner {
  90.     display: grid;
  91.     grid-template-columns: 1fr 1fr;
  92.     gap: 0;
  93.   }
  94.   /* Gallery Section */
  95.   .product-gallery {
  96.     padding: 30px;
  97.     display: flex;
  98.     flex-direction: column;
  99.     align-items: center;
  100.   }
  101.   .main-image-container {
  102.     position: relative;
  103.     width: 100%;
  104.     max-width: 500px;
  105.     margin-bottom: 20px;
  106.   }
  107.   .main-image {
  108.     width: 100%;
  109.     height: auto;
  110.     border-radius: var(--radius-md);
  111.     box-shadow: var(--shadow-md);
  112.     transition: transform 0.3s ease, opacity 0.2s ease;
  113.     cursor: zoom-in;
  114.   }
  115.   .main-image:hover {
  116.     transform: scale(1.02);
  117.   }
  118.   .thumbnails {
  119.     display: flex;
  120.     flex-wrap: wrap;
  121.     gap: 10px;
  122.     justify-content: center;
  123.     max-width: 500px;
  124.   }
  125.   .thumbnail {
  126.     width: 70px;
  127.     height: 70px;
  128.     border-radius: var(--radius-sm);
  129.     object-fit: cover;
  130.     cursor: pointer;
  131.     border: 3px solid transparent;
  132.     transition: all 0.3s ease;
  133.     box-shadow: var(--shadow-sm);
  134.   }
  135.   .thumbnail:hover {
  136.     transform: translateY(-3px);
  137.     box-shadow: var(--shadow-md);
  138.   }
  139.   .thumbnail.active {
  140.     border-color: var(--primary);
  141.   }
  142.   /* Product Info Section */
  143.   .product-info {
  144.     padding: 40px;
  145.     display: flex;
  146.     flex-direction: column;
  147.   }
  148.   .product-title {
  149.     font-size: 28px;
  150.     font-weight: 700;
  151.     color: var(--text-dark);
  152.     margin-bottom: 24px;
  153.     line-height: 1.3;
  154.   }
  155.   /* Feature Blocks */
  156.   .feature-block {
  157.     background: var(--primary-light);
  158.     border-radius: var(--radius-md);
  159.     padding: 20px;
  160.     margin-bottom: 16px;
  161.     border: 1px solid rgba(65, 162, 170, 0.15);
  162.   }
  163.   .feature-header {
  164.     display: flex;
  165.     align-items: center;
  166.     gap: 12px;
  167.     margin-bottom: 12px;
  168.   }
  169.   .feature-icon {
  170.     width: 24px;
  171.     height: 24px;
  172.     flex-shrink: 0;
  173.   }
  174.   .feature-title {
  175.     font-size: 16px;
  176.     font-weight: 600;
  177.     color: var(--text-dark);
  178.     margin: 0;
  179.   }
  180.   .feature-content {
  181.     font-size: 14px;
  182.     color: var(--text-muted);
  183.     line-height: 1.7;
  184.     margin: 0;
  185.   }
  186.   /* Order Button */
  187.   .order-btn {
  188.     display: inline-flex;
  189.     align-items: center;
  190.     justify-content: center;
  191.     gap: 8px;
  192.     background: linear-gradient(
  193.       135deg,
  194.       var(--primary) 0%,
  195.       var(--primary-dark) 100%
  196.     );
  197.     color: var(--white);
  198.     border: none;
  199.     border-radius: var(--radius-md);
  200.     padding: 16px 32px;
  201.     font-size: 16px;
  202.     font-weight: 600;
  203.     cursor: pointer;
  204.     transition: all 0.3s ease;
  205.     box-shadow: 0 4px 14px rgba(65, 162, 170, 0.35);
  206.     margin-top: auto;
  207.     width: fit-content;
  208.   }
  209.   .order-btn:hover {
  210.     transform: translateY(-2px);
  211.     box-shadow: 0 6px 20px rgba(65, 162, 170, 0.45);
  212.   }
  213.   .order-btn:active {
  214.     transform: translateY(0);
  215.   }
  216.   /* Navigation Controls */
  217.   .product-nav {
  218.     display: flex;
  219.     justify-content: center;
  220.     gap: 16px;
  221.     margin-top: 20px;
  222.   }
  223.   .nav-btn {
  224.     width: 50px;
  225.     height: 50px;
  226.     border-radius: 50%;
  227.     background: var(--white);
  228.     border: none;
  229.     box-shadow: var(--shadow-md);
  230.     cursor: pointer;
  231.     display: flex;
  232.     align-items: center;
  233.     justify-content: center;
  234.     transition: all 0.3s ease;
  235.   }
  236.   .nav-btn:hover {
  237.     transform: scale(1.1);
  238.     box-shadow: var(--shadow-lg);
  239.   }
  240.   .nav-btn svg {
  241.     width: 20px;
  242.     height: 20px;
  243.     fill: var(--text-dark);
  244.   }
  245.   /* Product Dots Navigation */
  246.   .product-dots {
  247.     display: flex;
  248.     justify-content: center;
  249.     gap: 8px;
  250.     margin-top: 16px;
  251.   }
  252.   .dot {
  253.     width: 10px;
  254.     height: 10px;
  255.     border-radius: 50%;
  256.     background: #ddd;
  257.     border: none;
  258.     cursor: pointer;
  259.     transition: all 0.3s ease;
  260.   }
  261.   .dot.active {
  262.     background: var(--primary);
  263.     transform: scale(1.2);
  264.   }
  265.   .dot:hover {
  266.     background: var(--primary-dark);
  267.   }
  268.   /* ============================================
  269.            Mobile Styles
  270.            ============================================ */
  271.   .mobile-slider {
  272.     display: none;
  273.   }
  274.   @media (max-width: 991px) {
  275.     .product-card-inner {
  276.       grid-template-columns: 1fr;
  277.     }
  278.     .product-gallery {
  279.       padding: 20px;
  280.     }
  281.     .product-info {
  282.       padding: 24px;
  283.     }
  284.     .product-title {
  285.       font-size: 22px;
  286.     }
  287.   }
  288.   @media (max-width: 768px) {
  289.     .product-page {
  290.       padding: 20px 12px;
  291.     }
  292.     .desktop-view {
  293.       display: none;
  294.     }
  295.     .mobile-slider {
  296.       display: block;
  297.     }
  298.     .mobile-product-card {
  299.       background: var(--white);
  300.       border-radius: var(--radius-lg);
  301.       box-shadow: var(--shadow-md);
  302.       overflow: hidden;
  303.       margin-bottom: 20px;
  304.     }
  305.     .mobile-main-image {
  306.       width: 100%;
  307.       height: auto;
  308.       display: block;
  309.     }
  310.     .mobile-thumbnails {
  311.       display: flex;
  312.       gap: 8px;
  313.       padding: 12px;
  314.       overflow-x: auto;
  315.       -webkit-overflow-scrolling: touch;
  316.     }
  317.     .mobile-thumbnail {
  318.       width: 60px;
  319.       height: 60px;
  320.       border-radius: var(--radius-sm);
  321.       object-fit: cover;
  322.       flex-shrink: 0;
  323.       cursor: pointer;
  324.       border: 2px solid transparent;
  325.       transition: border-color 0.3s ease;
  326.     }
  327.     .mobile-thumbnail.active {
  328.       border-color: var(--primary);
  329.     }
  330.     .mobile-product-info {
  331.       padding: 20px;
  332.     }
  333.     .mobile-product-title {
  334.       font-size: 20px;
  335.       font-weight: 700;
  336.       color: var(--text-dark);
  337.       margin-bottom: 16px;
  338.     }
  339.     .feature-block {
  340.       padding: 16px;
  341.       margin-bottom: 12px;
  342.     }
  343.     .feature-title {
  344.       font-size: 15px;
  345.     }
  346.     .feature-content {
  347.       font-size: 13px;
  348.     }
  349.     .order-btn {
  350.       width: 100%;
  351.       padding: 14px 24px;
  352.     }
  353.     .thumbnail {
  354.       width: 55px;
  355.       height: 55px;
  356.     }
  357.   }
  358.   /* Slick Slider Overrides for Mobile */
  359.   .mobile-slider .slick-slide {
  360.     padding: 0 5px;
  361.   }
  362.   .mobile-slider .slick-dots {
  363.     bottom: -30px;
  364.   }
  365.   .mobile-slider .slick-dots li button:before {
  366.     color: var(--primary);
  367.   }
  368.   .mobile-slider .slick-prev,
  369.   .mobile-slider .slick-next {
  370.     z-index: 10;
  371.   }
  372.   .mobile-slider .slick-prev {
  373.     left: 10px;
  374.   }
  375.   .mobile-slider .slick-next {
  376.     right: 10px;
  377.   }
  378.   /* Image Loading States */
  379.   .main-image.loading {
  380.     opacity: 0.6;
  381.   }
  382.   /* Lightbox (optional enhancement) */
  383.   .lightbox-overlay {
  384.     display: none;
  385.     position: fixed;
  386.     top: 0;
  387.     left: 0;
  388.     right: 0;
  389.     bottom: 0;
  390.     background: rgba(0, 0, 0, 0.9);
  391.     z-index: 10001;
  392.     align-items: center;
  393.     justify-content: center;
  394.     cursor: zoom-out;
  395.   }
  396.   .lightbox-overlay.active {
  397.     display: flex;
  398.   }
  399.   .lightbox-image {
  400.     max-width: 90%;
  401.     max-height: 90%;
  402.     border-radius: var(--radius-md);
  403.   }
  404.   .lightbox-close {
  405.     position: absolute;
  406.     top: 20px;
  407.     right: 20px;
  408.     background: var(--white);
  409.     border: none;
  410.     width: 40px;
  411.     height: 40px;
  412.     border-radius: 50%;
  413.     font-size: 24px;
  414.     cursor: pointer;
  415.     display: flex;
  416.     align-items: center;
  417.     justify-content: center;
  418.   }
  419. </style>
  420. {% endblock %} {% block Header %} {% if app.user %}
  421. {{
  422.   render(controller("App\\Controller\\EspaceParentController::headerparenrt"))
  423. }}
  424. {% else %}
  425. {{ render(controller("App\\Controller\\AccueilController::header")) }}
  426. {% endif %} {% endblock %} {% block Content %}
  427. <div class="product-page">
  428.   <div class="product-container">
  429.     <!-- Login Required Modal -->
  430.     <div class="login-modal-overlay" id="loginModal">
  431.       <div class="login-modal">
  432.         <h3>Veuillez d'abord vous connecter !</h3>
  433.         <a href="/" class="order-btn">OK</a>
  434.       </div>
  435.     </div>
  436.     <!-- Lightbox for Image Zoom -->
  437.     <div class="lightbox-overlay" id="lightbox" onclick="closeLightbox()">
  438.       <button class="lightbox-close" onclick="closeLightbox()">&times;</button>
  439.       <img class="lightbox-image" id="lightboxImage" src="" alt="" />
  440.     </div>
  441.     <!-- Desktop View -->
  442.     <div class="desktop-view">
  443.       {% for product in produit %} {% if product.labeleType != "Connexion" %}
  444.       <div
  445.         class="product-card"
  446.         id="product-{{ loop.index }}"
  447.         data-product-id="{{ product.labeleType|replace({' ': ''}) }}"
  448.         {%
  449.         if
  450.         loop.first
  451.         %}style="display: block;"
  452.         {%
  453.         endif
  454.         %}
  455.       >
  456.         <div class="product-card-inner">
  457.           <!-- Gallery -->
  458.           <div class="product-gallery">
  459.             <div class="main-image-container">
  460.               <img
  461.                 class="main-image"
  462.                 id="mainImage-{{ loop.index }}"
  463.                 src="{{ (product.attachements[0].idAttachement.path)|replace({'/upload/': '/upload/f_auto,q_auto,w_800/'}) }}"
  464.                 alt="{{ product.labeleType }}"
  465.                 onclick="openLightbox(this.src)"
  466.                 loading="eager"
  467.               />
  468.             </div>
  469.             <div class="thumbnails">
  470.               {% for attachment in product.attachements %} {% if
  471.               attachment.statut == "pageProduit" %}
  472.               <img
  473.                 class="thumbnail {% if loop.first %}active{% endif %}"
  474.                 src="{{ attachment.idAttachement.path|replace({'/upload/': '/upload/f_auto,q_auto,w_150,h_150,c_fill/'}) }}"
  475.                 data-full="{{ attachment.idAttachement.path|replace({'/upload/': '/upload/f_auto,q_auto,w_800/'}) }}"
  476.                 alt="{{ product.labeleType }} - Photo {{ loop.index }}"
  477.                 onclick="changeMainImage(this, 'mainImage-{{
  478.                   loop.parent.loop.index
  479.                 }}')"
  480.                 loading="lazy"
  481.               />
  482.               {% endif %} {% endfor %}
  483.             </div>
  484.           </div>
  485.           <!-- Product Info -->
  486.           <div class="product-info">
  487.             <h2 class="product-title">{{ product.labeleType }}</h2>
  488.             <!-- Caractéristiques -->
  489.             <div class="feature-block">
  490.               <div class="feature-header">
  491.                 <img
  492.                   class="feature-icon"
  493.                   src="{{ asset('images/SVG/5sur5-caracteristiques.svg') }}"
  494.                   alt=""
  495.                 />
  496.                 <h4 class="feature-title">Caractéristiques produit</h4>
  497.               </div>
  498.               <p class="feature-content">
  499.                 {% if product.description %}{{ product.description | nl2br }}{%
  500.                 endif %}
  501.               </p>
  502.             </div>
  503.             <!-- Les Plus -->
  504.             <div class="feature-block">
  505.               <div class="feature-header">
  506.                 <img
  507.                   class="feature-icon"
  508.                   src="{{ asset('images/LesPlus5sur5.svg') }}"
  509.                   alt=""
  510.                 />
  511.                 <h4 class="feature-title">Les plus produit</h4>
  512.               </div>
  513.               <p class="feature-content">
  514.                 {{ product.plusDescription | nl2br }}
  515.               </p>
  516.             </div>
  517.             <!-- Tarifs -->
  518.             <div class="feature-block">
  519.               <div class="feature-header">
  520.                 <img
  521.                   class="feature-icon"
  522.                   src="{{ asset('images/SVG/5sur5-tarifs.svg') }}"
  523.                   alt=""
  524.                 />
  525.                 <h4 class="feature-title">Tarif & Frais de port</h4>
  526.               </div>
  527.               <p class="feature-content">{{ product.tarifs | nl2br }}</p>
  528.             </div>
  529.             <!-- Order Button -->
  530.             {% if app.user %} {% if is_granted('ROLE_PARENT') %}
  531.             <button
  532.               class="order-btn"
  533.               onclick="location.href='{{ path('projet-Parent') }}'"
  534.             >
  535.               Commander
  536.             </button>
  537.             {% elseif is_granted('ROLE_ACC') %}
  538.             <button
  539.               class="order-btn"
  540.               onclick="location.href='{{
  541.                 path('ProjetsAccompagnateur', { id: sejour.id })
  542.               }}'"
  543.             >
  544.               Commander
  545.             </button>
  546.             {% endif %} {% else %}
  547.             <button class="order-btn" onclick="showLoginModal()">
  548.               Commander
  549.             </button>
  550.             {% endif %}
  551.           </div>
  552.         </div>
  553.       </div>
  554.       {% endif %} {% endfor %}
  555.       <!-- Navigation -->
  556.       {% set productCount = 0 %} {% for product in produit %} {% if
  557.       product.labeleType != "Connexion" %} {% set productCount = productCount +
  558.       1 %} {% endif %} {% endfor %} {% if productCount > 1 %}
  559.       <div class="product-nav">
  560.         <button
  561.           class="nav-btn"
  562.           onclick="navigateProduct(-1)"
  563.           aria-label="Produit précédent"
  564.         >
  565.           <svg viewBox="0 0 24 24">
  566.             <path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" />
  567.           </svg>
  568.         </button>
  569.         <button
  570.           class="nav-btn"
  571.           onclick="navigateProduct(1)"
  572.           aria-label="Produit suivant"
  573.         >
  574.           <svg viewBox="0 0 24 24">
  575.             <path d="M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z" />
  576.           </svg>
  577.         </button>
  578.       </div>
  579.       <div class="product-dots">
  580.         {% set dotIndex = 0 %} {% for product in produit %} {% if
  581.         product.labeleType != "Connexion" %}
  582.         <button
  583.           class="dot {% if dotIndex == 0 %}active{% endif %}"
  584.           onclick="goToProduct({{ dotIndex }})"
  585.           aria-label="Voir {{ product.labeleType }}"
  586.         ></button>
  587.         {% set dotIndex = dotIndex + 1 %} {% endif %} {% endfor %}
  588.       </div>
  589.       {% endif %}
  590.     </div>
  591.     <!-- Mobile View -->
  592.     <div class="mobile-slider">
  593.       {% for product in produit %} {% if product.labeleType != "Connexion" %}
  594.       <div class="mobile-product-card">
  595.         <img
  596.           class="mobile-main-image"
  597.           id="mobileMainImage-{{ loop.index }}"
  598.           src="{{ (product.attachements[0].idAttachement.path)|replace({'/upload/': '/upload/f_auto,q_auto,w_600/'}) }}"
  599.           alt="{{ product.labeleType }}"
  600.           loading="lazy"
  601.         />
  602.         <div class="mobile-thumbnails">
  603.           {% for attachment in product.attachements %} {% if attachment.statut
  604.           == "pageProduit" %}
  605.           <img
  606.             class="mobile-thumbnail {% if loop.first %}active{% endif %}"
  607.             src="{{ attachment.idAttachement.path|replace({'/upload/': '/upload/f_auto,q_auto,w_120,h_120,c_fill/'}) }}"
  608.             data-full="{{ attachment.idAttachement.path|replace({'/upload/': '/upload/f_auto,q_auto,w_600/'}) }}"
  609.             alt="{{ product.labeleType }} - Photo {{ loop.index }}"
  610.             onclick="changeMobileImage(this, 'mobileMainImage-{{
  611.               loop.parent.loop.index
  612.             }}')"
  613.             loading="lazy"
  614.           />
  615.           {% endif %} {% endfor %}
  616.         </div>
  617.         <div class="mobile-product-info">
  618.           <h2 class="mobile-product-title">{{ product.labeleType }}</h2>
  619.           <div class="feature-block">
  620.             <div class="feature-header">
  621.               <img
  622.                 class="feature-icon"
  623.                 src="{{ asset('images/SVG/5sur5-caracteristiques.svg') }}"
  624.                 alt=""
  625.               />
  626.               <h4 class="feature-title">Caractéristiques produit</h4>
  627.             </div>
  628.             <p class="feature-content">
  629.               {% if product.description %}{{ product.description | nl2br }}{%
  630.               endif %}
  631.             </p>
  632.           </div>
  633.           <div class="feature-block">
  634.             <div class="feature-header">
  635.               <img
  636.                 class="feature-icon"
  637.                 src="{{ asset('images/LesPlus5sur5.svg') }}"
  638.                 alt=""
  639.               />
  640.               <h4 class="feature-title">Les plus produit</h4>
  641.             </div>
  642.             <p class="feature-content">{{ product.plusDescription | nl2br }}</p>
  643.           </div>
  644.           <div class="feature-block">
  645.             <div class="feature-header">
  646.               <img
  647.                 class="feature-icon"
  648.                 src="{{ asset('images/SVG/5sur5-tarifs.svg') }}"
  649.                 alt=""
  650.               />
  651.               <h4 class="feature-title">Tarif & Frais de port</h4>
  652.             </div>
  653.             <p class="feature-content">{{ product.tarifs | nl2br }}</p>
  654.           </div>
  655.           {% if app.user %} {% if is_granted('ROLE_PARENT') %}
  656.           <button
  657.             class="order-btn"
  658.             onclick="location.href='{{ path('projet-Parent') }}'"
  659.           >
  660.             Commander
  661.           </button>
  662.           {% elseif is_granted('ROLE_ACC') %}
  663.           <button
  664.             class="order-btn"
  665.             onclick="location.href='{{
  666.               path('ProjetsAccompagnateur', { id: sejour.id })
  667.             }}'"
  668.           >
  669.             Commander
  670.           </button>
  671.           {% endif %} {% else %}
  672.           <button class="order-btn" onclick="showLoginModal()">
  673.             Commander
  674.           </button>
  675.           {% endif %}
  676.         </div>
  677.       </div>
  678.       {% endif %} {% endfor %}
  679.     </div>
  680.   </div>
  681. </div>
  682. {% endblock %} {% block Footer %}
  683. {{ parent() }}
  684. {% endblock %} {% block javascript %}
  685. {{ parent() }}
  686. <script>
  687.   // ============================================
  688.   // Product Gallery - JavaScript
  689.   // ============================================
  690.   let currentProductIndex = 0;
  691.   const productCards = document.querySelectorAll('.desktop-view .product-card');
  692.   const dots = document.querySelectorAll('.dot');
  693.   const totalProducts = productCards.length;
  694.   // Initialize based on URL parameter or showArt variable
  695.   document.addEventListener('DOMContentLoaded', function() {
  696.       {% if showArt is defined and showArt != "ALL" %}
  697.           const targetId = "{{ showArt|replace({' ': ''}) }}";
  698.           productCards.forEach((card, index) => {
  699.               if (card.dataset.productId === targetId) {
  700.                   goToProduct(index);
  701.               }
  702.           });
  703.       {% endif %}
  704.       // Initialize mobile slider if Slick is available
  705.       if (typeof $.fn.slick !== 'undefined') {
  706.           $('.mobile-slider').slick({
  707.               slidesToShow: 1,
  708.               slidesToScroll: 1,
  709.               autoplay: true,
  710.               autoplaySpeed: 4000,
  711.               dots: true,
  712.               arrows: false,
  713.               adaptiveHeight: true
  714.           });
  715.       }
  716.   });
  717.   // Navigate between products
  718.   function navigateProduct(direction) {
  719.       currentProductIndex += direction;
  720.       if (currentProductIndex >= totalProducts) {
  721.           currentProductIndex = 0;
  722.       } else if (currentProductIndex < 0) {
  723.           currentProductIndex = totalProducts - 1;
  724.       }
  725.       updateProductDisplay();
  726.   }
  727.   // Go to specific product
  728.   function goToProduct(index) {
  729.       currentProductIndex = index;
  730.       updateProductDisplay();
  731.   }
  732.   // Update display
  733.   function updateProductDisplay() {
  734.       productCards.forEach((card, index) => {
  735.           card.style.display = index === currentProductIndex ? 'block' : 'none';
  736.       });
  737.       dots.forEach((dot, index) => {
  738.           dot.classList.toggle('active', index === currentProductIndex);
  739.       });
  740.   }
  741.   // Change main image from thumbnail (Desktop)
  742.   function changeMainImage(thumbnail, mainImageId) {
  743.       const mainImage = document.getElementById(mainImageId);
  744.       const container = thumbnail.closest('.product-gallery');
  745.       // Update active state
  746.       container.querySelectorAll('.thumbnail').forEach(t => t.classList.remove('active'));
  747.       thumbnail.classList.add('active');
  748.       // Animate transition
  749.       mainImage.classList.add('loading');
  750.       mainImage.style.transform = 'scale(0.98)';
  751.       setTimeout(() => {
  752.           mainImage.src = thumbnail.dataset.full;
  753.           mainImage.onload = function() {
  754.               mainImage.classList.remove('loading');
  755.               mainImage.style.transform = 'scale(1)';
  756.           };
  757.       }, 150);
  758.   }
  759.   // Change main image from thumbnail (Mobile)
  760.   function changeMobileImage(thumbnail, mainImageId) {
  761.       const mainImage = document.getElementById(mainImageId);
  762.       const container = thumbnail.closest('.mobile-product-card');
  763.       container.querySelectorAll('.mobile-thumbnail').forEach(t => t.classList.remove('active'));
  764.       thumbnail.classList.add('active');
  765.       mainImage.style.opacity = '0.7';
  766.       setTimeout(() => {
  767.           mainImage.src = thumbnail.dataset.full;
  768.           mainImage.onload = function() {
  769.               mainImage.style.opacity = '1';
  770.           };
  771.       }, 150);
  772.   }
  773.   // Lightbox functions
  774.   function openLightbox(src) {
  775.       const lightbox = document.getElementById('lightbox');
  776.       const lightboxImage = document.getElementById('lightboxImage');
  777.       lightboxImage.src = src;
  778.       lightbox.classList.add('active');
  779.       document.body.style.overflow = 'hidden';
  780.   }
  781.   function closeLightbox() {
  782.       const lightbox = document.getElementById('lightbox');
  783.       lightbox.classList.remove('active');
  784.       document.body.style.overflow = '';
  785.   }
  786.   // Login modal
  787.   function showLoginModal() {
  788.       document.getElementById('loginModal').classList.add('active');
  789.   }
  790.   function hideLoginModal() {
  791.       document.getElementById('loginModal').classList.remove('active');
  792.   }
  793.   // Close modal on overlay click
  794.   document.getElementById('loginModal').addEventListener('click', function(e) {
  795.       if (e.target === this) {
  796.           hideLoginModal();
  797.       }
  798.   });
  799.   // Keyboard navigation
  800.   document.addEventListener('keydown', function(e) {
  801.       if (e.key === 'Escape') {
  802.           closeLightbox();
  803.           hideLoginModal();
  804.       } else if (e.key === 'ArrowLeft') {
  805.           navigateProduct(-1);
  806.       } else if (e.key === 'ArrowRight') {
  807.           navigateProduct(1);
  808.       }
  809.   });
  810. </script>
  811. {% endblock %}