templates/home/products.html.twig line 1

  1. {% extends 'base.html.twig' %}
  2. {% block stylesheets %}
  3.     {{ parent() }}
  4.     <style>
  5.         .cms-photo-group {
  6.             position: relative;
  7.             display: inline-block;
  8.         }
  9.         .cms-photo-wrapper {
  10.             display: none;
  11.         }
  12.         .cms-photo-wrapper.active {
  13.             display: block;
  14.         }
  15.         .cms-arrow {
  16.             position: absolute;
  17.             top: 50%;
  18.             transform: translateY(-50%);
  19.             background: rgba(0, 0, 0, 0.4);
  20.             color: white;
  21.             border: none;
  22.             cursor: pointer;
  23.             padding: 0.4rem 0.7rem;
  24.             font-size: 1.2rem;
  25.             border-radius: 50%;
  26.         }
  27.         .cms-arrow.left {
  28.             left: 5px;
  29.         }
  30.         .cms-arrow.right {
  31.             right: 5px;
  32.         }
  33.     </style>
  34. {% endblock %}
  35. {% block title %}
  36.     {% for cms_copy in cms_copy_array %}
  37.         {% if cms_copy.ranking == 1 %}
  38.             {% if cms_copy.tabTitle is defined %}
  39.                 {{ attribute(cms_copy,'tabTitle'~LanguagesService.getSelectedLanguageCode)|raw }}
  40.             {% else %}
  41.                 {% if CompanyDetails.getCompanyDetails is not null %}
  42.                     {{ CompanyDetails.getCompanyDetails.companyName }}
  43.                 {% else %}
  44.                     {{ product~Languages.getSelectedLanguageCode }}
  45.                 {% endif %}
  46.             {% endif %}
  47.         {% endif %}
  48.     {% endfor %}
  49. {% endblock %}
  50. {% block body %}
  51.     <section id="my-service-section" class="default-bg-white">
  52.         <div class="default-space"></div>
  53.         <div class="container">
  54.             <div class="row">
  55.                 <div class="col-lg-12 col-md-12 col-sm-12 col-12">
  56.                     <div class="default-title">
  57.                         {% include 'home/products_page/title.html.twig' %}
  58.                     </div>
  59.                 </div>
  60.             </div>
  61.             {% include 'template_parts_project_specific/home_page_project_specific.html.twig' %}
  62.             {# ------------------ 1) Group photos by NON-NUMERIC rank key ------------------ #}
  63.             {% set photos_by_rank = {} %}
  64.             {% for p in cms_photo_array %}
  65.                 {% set rank_str = 'r_' ~ (attribute(p, 'ranking')|default(0)) %}
  66.                 {% set bucket = photos_by_rank[rank_str]|default([]) %}
  67.                 {% set bucket = bucket|merge([p]) %}
  68.                 {% set photos_by_rank = photos_by_rank|merge({ (rank_str): bucket }) %}
  69.             {% endfor %}
  70.             {# ------------------ 2) Render each CMS block by its rank ------------------ #}
  71.             <div class="row">
  72.                 {% for cms_copy in cms_copy_array|sort((a, b) => a.ranking <=> b.ranking) %}
  73.                     {% set rank_str = 'r_' ~ (attribute(cms_copy, 'ranking')|default(0)) %}
  74.                     {% set photos = photos_by_rank[rank_str]|default([]) %}
  75.                     <div class="col-12">
  76.                         <div class="row">
  77.                             {# Left column: CMS copy (full-width if no photo, half if photo exists) #}
  78.                             <div class="{% if photos is not empty %}col-md-6 col-12{% else %}col-12{% endif %}">
  79.                                 {% if is_granted('ROLE_ADMIN') %}
  80.                                     <a target="_blank" href="{{ path('cms_copy_edit', {'id': cms_copy.id}) }}">
  81.                                         <i style="color: red" class="fa fa-pen"> ({{ cms_copy.ranking }})</i>
  82.                                     </a>
  83.                                     {% if cms_copy.product is not null %}
  84.                                         <a target="_blank"
  85.                                            href="{{ path('cms_copy_new', {'product': cms_copy.product.id, 'ranking': (cms_copy.ranking + 1)}) }}">
  86.                                             <i style="color: blue" class="fa fa-plus"></i>
  87.                                         </a>
  88.                                     {% endif %}
  89.                                     {% if photos is empty and cms_copy.product is not null%}
  90.                                         <a target="_blank"
  91.                                            href="{{ path('cms_photo_new', {'product': cms_copy.product.id,'ranking': (cms_copy.ranking )}) }}">
  92.                                             <i style="color: blue" class="fa fa-camera"></i>
  93.                                         </a>
  94.                                     {% endif %}
  95.                                 {% endif %}
  96.                                 {% if cms_copy.pageLayout is not null %}
  97.                                     {% if cms_copy.getPageLayout.name  == "Accordion" %}
  98.                                         {% include 'home/products_page/formats/accordion.html.twig' %}
  99.                                     {% elseif cms_copy.getPageLayout.name  == "Card Layout" %}
  100.                                         {% include 'home/products_page/formats/card_layout.html.twig' %}
  101.                                     {% elseif cms_copy.getPageLayout.name  == "Carousel/Slider" %}
  102.                                         {% include 'home/products_page/formats/carousel_slider.html.twig' %}
  103.                                     {% elseif cms_copy.getPageLayout.name  == "Fullscreen Sections" %}
  104.                                         {% include 'home/products_page/formats/fullscreen_sections.html.twig' %}
  105.                                     {% elseif cms_copy.getPageLayout.name  == "Grid Layout" %}
  106.                                         {% include 'home/products_page/formats/grid_layout.html.twig' %}
  107.                                     {% elseif cms_copy.getPageLayout.name  == "Hero Banner" %}
  108.                                         {% include 'home/products_page/formats/hero_banner.html.twig' %}
  109.                                     {% elseif cms_copy.getPageLayout.name  == "List/Stacked Content" %}
  110.                                         {% include 'home/products_page/formats/list_stacked_content.html.twig' %}
  111.                                     {% elseif cms_copy.getPageLayout.name  == "Masonry Layout" %}
  112.                                         {% include 'home/products_page/formats/masonry_layout.html.twig' %}
  113.                                     {% elseif cms_copy.getPageLayout.name  == "Parallax Scrolling" %}
  114.                                         {% include 'home/products_page/formats/parallax_scrolling.html.twig' %}
  115.                                     {% elseif cms_copy.getPageLayout.name  == "Sidebar Layout" %}
  116.                                         {% include 'home/products_page/formats/sidebar_layout.html.twig' %}
  117.                                     {% elseif cms_copy.getPageLayout.name  == "Single Page Scroll" %}
  118.                                         {% include 'home/products_page/formats/single_page_scroll.html.twig' %}
  119.                                     {% elseif cms_copy.getPageLayout.name  == "Split Screen" %}
  120.                                         {% include 'home/products_page/formats/split_screen.html.twig' %}
  121.                                     {% elseif cms_copy.getPageLayout.name  == "Sticky Header/Footer" %}
  122.                                         {% include 'home/products_page/formats/sticky_header_footer.html.twig' %}
  123.                                     {% elseif cms_copy.getPageLayout.name  == "Tabbed Interface" %}
  124.                                         {% include 'home/products_page/formats/tabbed_interface.html.twig' %}
  125.                                     {% elseif cms_copy.getPageLayout.name  == "Timeline Layout" %}
  126.                                         {% include 'home/products_page/formats/timeline_layout.html.twig' %}
  127.                                     {% else %}
  128.                                         {% include 'home/products_page/formats/accordion.html.twig' %}
  129.                                     {% endif %}
  130.                                 {% else %}
  131.                                     {% include 'home/products_page/formats/accordion.html.twig' %}
  132.                                 {% endif %}
  133.                             </div>
  134.                             {# Right column: matching photos for this rank #}
  135.                             {% if photos is not empty %}
  136.                                 <div class="col-md-6 col-12">
  137.                                     {% for cms_photo in photos %}
  138.                                         <div class="d-inline-block justify-content-center py-1 p-sm-2 product-image-container">
  139.                                             <div class="image-wrapper">
  140.                                                 {% include 'home/products_page/photo_or_video.html.twig' %}
  141.                                             </div>
  142.                                         </div>
  143.                                     {% endfor %}
  144.                                 </div>
  145.                             {% endif %}
  146.                         </div>
  147.                     </div>
  148.                 {% endfor %}
  149.             </div>
  150.             {# ------------------ Sub Pages ------------------ #}
  151.             <div class="row mt-3">
  152.                 <div class="col-12">
  153.                     {% for sub_page in sub_pages %}
  154.                         <ul>
  155.                             <a target="_blank" href="{{ path('sub_page_show', {id: sub_page.id}) }}">
  156.                                 {{ sub_page.title }}
  157.                             </a>
  158.                         </ul>
  159.                     {% endfor %}
  160.                 </div>
  161.             </div>
  162.     </section>
  163.     {% include 'home/parts/contact_form_and_qr_code.html.twig' %}
  164. {% endblock %}
  165. {% block additionaljs %}
  166.     {% if include_contact_form == 1 %}
  167.         <script>
  168.             $(document).ready(function () {
  169.                 $("input[name='website_contacts[status]']").closest(".form-group").remove();
  170.                 $("input[name='website_contacts[dateTime]']").closest(".form-group").remove();
  171.                 $("input[name='website_contacts[dateResponded]']").closest(".form-group").remove();
  172.             });
  173.         </script>
  174.     {% endif %}
  175. {% endblock %}
  176. {% block javascripts %}
  177.     {{ parent() }}
  178.     <script>
  179.         document.addEventListener('DOMContentLoaded', function () {
  180.             const wrappers = Array.from(document.querySelectorAll('.cms-photo-wrapper'));
  181.             const groups = {};
  182.             // Group photos by ranking
  183.             wrappers.forEach(w => {
  184.                 const rank = w.getAttribute('data-rank');
  185.                 if (!groups[rank]) groups[rank] = [];
  186.                 groups[rank].push(w);
  187.             });
  188.             // Initialize groups
  189.             Object.keys(groups).forEach(rank => {
  190.                 const photos = groups[rank];
  191.                 if (photos.length <= 1) {
  192.                     // Single photo: keep normal behaviour (including cms_photo_view link)
  193.                     photos[0].classList.add('active');
  194.                     return;
  195.                 }
  196.                 // >>> Multiple photos with the same rank
  197.                 // 1) Disable cms_photo_view links in this group
  198.                 photos.forEach(wrapper => {
  199.                     const viewLink = wrapper.querySelector('a.cms-photo-view-link');
  200.                     if (viewLink) {
  201.                         // Option A: just prevent navigation
  202.                         viewLink.addEventListener('click', function (e) {
  203.                             e.preventDefault();
  204.                         });
  205.                         // If you prefer to completely remove the link wrapper, use this instead:
  206.                         // const img = viewLink.querySelector('img');
  207.                         // if (img) {
  208.                         //     wrapper.insertBefore(img, viewLink);
  209.                         //     viewLink.remove();
  210.                         // }
  211.                     }
  212.                 });
  213.                 // 2) Wrap them in a container
  214.                 const container = document.createElement('div');
  215.                 container.classList.add('cms-photo-group');
  216.                 const parent = photos[0].parentNode;
  217.                 parent.insertBefore(container, photos[0]);
  218.                 photos.forEach(p => container.appendChild(p));
  219.                 // Show first image
  220.                 let index = 0;
  221.                 photos[index].classList.add('active');
  222.                 // Add navigation arrows
  223.                 const leftArrow = document.createElement('button');
  224.                 leftArrow.className = 'cms-arrow left';
  225.                 leftArrow.innerHTML = '&#10094;'; // ‹
  226.                 const rightArrow = document.createElement('button');
  227.                 rightArrow.className = 'cms-arrow right';
  228.                 rightArrow.innerHTML = '&#10095;'; // ›
  229.                 container.appendChild(leftArrow);
  230.                 container.appendChild(rightArrow);
  231.                 function show(i) {
  232.                     photos.forEach(p => p.classList.remove('active'));
  233.                     photos[i].classList.add('active');
  234.                 }
  235.                 leftArrow.addEventListener('click', () => {
  236.                     index = (index - 1 + photos.length) % photos.length;
  237.                     show(index);
  238.                 });
  239.                 rightArrow.addEventListener('click', () => {
  240.                     index = (index + 1) % photos.length;
  241.                     show(index);
  242.                 });
  243.             });
  244.         });
  245.     </script>
  246. {% endblock %}