templates/blo/home/index.html.twig line 1

Open in your IDE?
  1. {% extends 'blo/base.html.twig' %}
  2. {% block title %}BLO — Achat en ligne{% endblock %}
  3. {% block stylesheets %}
  4. {{ parent() }}
  5. <style>
  6.     .blo-hero-slider-wrap { padding: 1rem 1rem 0; }
  7.     .blo-hero-slider { 
  8.         width: 100%; 
  9.         aspect-ratio: 1920 / 520; 
  10.         border-radius: 20px; 
  11.         overflow: hidden; 
  12.         box-shadow: 0 12px 32px rgba(93,184,91,0.15); 
  13.     }
  14.     .blo-hero-slider .carousel-inner, .blo-hero-slider .carousel { height: 100%; }
  15.     .blo-hero-slide {
  16.         position: relative;
  17.         width: 100%;
  18.         height: 100%;
  19.         background-size: cover;
  20.         background-position: center;
  21.         background-repeat: no-repeat;
  22.         background-color: #1a1a2e;
  23.     }
  24.     .blo-hero-slide::before {
  25.         content: '';
  26.         position: absolute;
  27.         inset: 0;
  28.         background: linear-gradient(90deg, rgba(0,0,0,0.45) 0%, rgba(0,0,0,0.1) 60%, transparent 100%);
  29.         border-radius: 0;
  30.         z-index: 1;
  31.     }
  32.     .blo-hero-slide .slide-content {
  33.         position: absolute;
  34.         inset: 0;
  35.         z-index: 2;
  36.         display: flex;
  37.         flex-direction: column;
  38.         justify-content: center;
  39.         padding: 2rem 2.5rem;
  40.         max-width: 540px;
  41.         color: #fff;
  42.     }
  43.     .blo-hero-slide .slide-content h2 { color: #fff; font-size: 1.8rem; font-weight: 800; margin-bottom: 0.5rem; text-shadow: 0 2px 8px rgba(0,0,0,0.3); }
  44.     .blo-hero-slide .slide-content .price { font-size: 1.6rem; font-weight: 700; text-shadow: 0 2px 6px rgba(0,0,0,0.3); white-space: nowrap; }
  45.     .blo-hero-slide .slide-content .price-old { font-size: 1rem; opacity: 0.7; text-decoration: line-through; margin-left: 0.5rem; }
  46.     .blo-hero-slider .carousel-control-prev, .blo-hero-slider .carousel-control-next { width: 4rem; opacity: 0.9; z-index: 10; }
  47.     .blo-hero-slider .carousel-indicators button { background-color: rgba(255,255,255,0.5); width: 10px; height: 10px; border-radius: 50%; border: none; margin: 0 6px; }
  48.     .blo-hero-slider .carousel-indicators button.active { background-color: #fff; transform: scale(1.2); }
  49.     .blo-scroll-row { display: flex; overflow-x: auto; gap: 1rem; padding-bottom: 1rem; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; }
  50.     .blo-scroll-row .blo-product-box { flex: 0 0 200px; scroll-snap-align: start; }
  51.     @media (min-width: 768px) { .blo-scroll-row .blo-product-box { flex: 0 0 220px; } }
  52.     @media (max-width: 576px) { .blo-hero-slide .slide-content { padding: 1.2rem 1.2rem; } .blo-hero-slide .slide-content h2 { font-size: 1.2rem; } }
  53. </style>
  54. {% endblock %}
  55. {% block body %}
  56. <div class="container-fluid px-0 blo-hero-slider-wrap">
  57.     {# Slider hero (produits configurés en admin) #}
  58.     {% if sliderItems|default([])|length > 0 %}
  59.     <section class="blo-hero-slider container">
  60.         <div id="heroSlider" class="carousel slide h-100" data-bs-ride="carousel">
  61.             <div class="carousel-indicators">
  62.                 {% for item in sliderItems %}
  63.                 <button type="button" data-bs-target="#heroSlider" data-bs-slide-to="{{ loop.index0 }}" {{ loop.first ? 'class="active"' : '' }}></button>
  64.                 {% endfor %}
  65.             </div>
  66.             <div class="carousel-inner h-100">
  67.                 {% for item in sliderItems %}
  68.                 {% set firstImg = item.product is not null ? item.product.images|first : null %}
  69.                 {% set bgImg = item.backgroundImage ? asset('uploads/slider/' ~ item.backgroundImage) : asset('assets/images/background/weatherbg.jpg') %}
  70.                 <div class="carousel-item {{ loop.first ? 'active' : '' }} h-100">
  71.                     <div class="blo-hero-slide" style="background-image: url('{{ bgImg }}');">
  72.                         <div class="container h-100">
  73.                             <div class="row align-items-center h-100">
  74.                                 <div class="col-md-6 text-center text-md-start">
  75.                                     <h2>{{ item.getDisplayTitle() }}</h2>
  76.                                     {% if item.getDisplaySubtitle() %}<p class="mb-2" style="opacity:0.9;">{{ item.getDisplaySubtitle() }}</p>{% endif %}
  77.                                     {% if item.product is not null %}
  78.                                     <p class="mb-3">
  79.                                         <span class="price">
  80.                                             {% if item.product.promoPrice %}{{ item.product.promoPrice|blo_price(item.product.currency) }}{% else %}{{ item.product.price|blo_price(item.product.currency) }}{% endif %}
  81.                                         </span>
  82.                                         {% if item.product.promoPrice %}<span class="price-old">{{ item.product.price|blo_price(item.product.currency) }}</span>{% endif %}
  83.                                     </p>
  84.                                     <a href="{{ path('blo_product_show', {slug: item.product.slug}) }}" class="btn btn-light rounded-pill px-4 fw-bold shadow-sm" style="color:#2e7d32;">Je découvre</a>
  85.                                     {% endif %}
  86.                                 </div>
  87.                                 <div class="col-md-6 text-center d-none d-md-flex align-items-center justify-content-center h-100 py-3">
  88.                                     {% if firstImg %}
  89.                                     <img src="{{ asset('uploads/' ~ firstImg.path) }}" alt="{{ item.getDisplayTitle() }}" style="max-height: 100%; max-width: 90%; object-fit: contain; filter: drop-shadow(0 8px 16px rgba(0,0,0,0.15));">
  90.                                     {% endif %}
  91.                                 </div>
  92.                             </div>
  93.                         </div>
  94.                     </div>
  95.                 </div>
  96.                 {% endfor %}
  97.             </div>
  98.             <button class="carousel-control-prev" type="button" data-bs-target="#heroSlider" data-bs-slide="prev"><span class="carousel-control-prev-icon"></span></button>
  99.             <button class="carousel-control-next" type="button" data-bs-target="#heroSlider" data-bs-slide="next"><span class="carousel-control-next-icon"></span></button>
  100.         </div>
  101.     </section>
  102.     {% endif %}
  103. </div>
  104. <div class="container py-3">
  105.     {# Offres du moment #}
  106.     {% if promoProducts|length > 0 %}
  107.     <section class="blo-section-box">
  108.         <div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-3">
  109.             <h2 class="mb-0">Offres du moment</h2>
  110.             <a href="{{ path('blo_catalog') }}?promo=1" class="small">Voir tout</a>
  111.         </div>
  112.         <div class="row g-3">
  113.             {% for product in promoProducts %}
  114.             <div class="col-6 col-sm-4 col-md-3 col-lg-2">
  115.                     <div class="blo-product-box">
  116.                         <a href="{{ path('blo_product_show', {slug: product.slug}) }}" class="text-decoration-none text-dark d-block">
  117.                             <div class="img-wrap position-relative">
  118.                                 <span class="badge bg-danger position-absolute top-0 start-0 rounded-pill">Promo</span>
  119.                                 {% set firstImage = product.images|first %}
  120.                                 {% if firstImage %}
  121.                                 <img src="{{ asset('uploads/' ~ firstImage.path) }}" alt="{{ product.title }}">
  122.                                 {% else %}
  123.                                 <i class="bi bi-image text-secondary" style="font-size: 3rem;"></i>
  124.                                 {% endif %}
  125.                             </div>
  126.                             <div class="title">{{ product.title }}</div>
  127.                             <p class="price mb-0"><del>{{ product.price|blo_price(product.currency) }}</del> {{ product.promoPrice|blo_price(product.currency) }}</p>
  128.                         </a>
  129.                         <form action="{{ path('blo_cart_add', {productId: product.id}) }}" method="post" class="d-inline">
  130.                             <button type="submit" class="blo-product-add-btn" title="Ajouter au panier"><i class="bi bi-plus-lg fs-5"></i></button>
  131.                         </form>
  132.                     </div>
  133.             </div>
  134.             {% endfor %}
  135.         </div>
  136.     </section>
  137.     {% endif %}
  138.     {# Nouveautés (défilement horizontal sur mobile) #}
  139.     {% if newestProducts|length > 0 %}
  140.     <section class="blo-section-box">
  141.         <div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-3">
  142.             <h2 class="mb-0">Nouveautés</h2>
  143.             <a href="{{ path('blo_catalog') }}?newest=1" class="small">Voir tout</a>
  144.         </div>
  145.         <div class="blo-scroll-row d-md-none">
  146.             {% for product in newestProducts %}
  147.                     <div class="blo-product-box">
  148.                         <a href="{{ path('blo_product_show', {slug: product.slug}) }}" class="text-decoration-none text-dark d-block">
  149.                             <div class="img-wrap">
  150.                                 {% set firstImage = product.images|first %}
  151.                                 {% if firstImage %}<img src="{{ asset('uploads/' ~ firstImage.path) }}" alt="{{ product.title }}">{% else %}<i class="bi bi-image text-secondary"></i>{% endif %}
  152.                             </div>
  153.                             <div class="title">{{ product.title }}</div>
  154.                             <p class="price mb-0">{% if product.promoPrice %}<del>{{ product.price|blo_price(product.currency) }}</del> {{ product.promoPrice|blo_price(product.currency) }}{% else %}{{ product.price|blo_price(product.currency) }}{% endif %}</p>
  155.                         </a>
  156.                         <form action="{{ path('blo_cart_add', {productId: product.id}) }}" method="post" class="d-inline">
  157.                             <button type="submit" class="blo-product-add-btn" title="Ajouter au panier"><i class="bi bi-plus-lg fs-5"></i></button>
  158.                         </form>
  159.                     </div>
  160.             {% endfor %}
  161.         </div>
  162.         <div class="row g-3 d-none d-md-flex">
  163.             {% for product in newestProducts %}
  164.             <div class="col-6 col-lg-3">
  165.                     <div class="blo-product-box h-100">
  166.                         <a href="{{ path('blo_product_show', {slug: product.slug}) }}" class="text-decoration-none text-dark d-block">
  167.                             <div class="img-wrap">
  168.                                 {% set firstImage = product.images|first %}
  169.                                 {% if firstImage %}<img src="{{ asset('uploads/' ~ firstImage.path) }}" alt="{{ product.title }}">{% else %}<i class="bi bi-image text-secondary"></i>{% endif %}
  170.                             </div>
  171.                             <div class="title">{{ product.title }}</div>
  172.                             <p class="price mb-0">{% if product.promoPrice %}<del>{{ product.price|blo_price(product.currency) }}</del> {{ product.promoPrice|blo_price(product.currency) }}{% else %}{{ product.price|blo_price(product.currency) }}{% endif %}</p>
  173.                         </a>
  174.                         <form action="{{ path('blo_cart_add', {productId: product.id}) }}" method="post" class="d-inline">
  175.                             <button type="submit" class="blo-product-add-btn" title="Ajouter au panier"><i class="bi bi-plus-lg fs-5"></i></button>
  176.                         </form>
  177.                     </div>
  178.             </div>
  179.             {% endfor %}
  180.         </div>
  181.     </section>
  182.     {% endif %}
  183.     {# À la une #}
  184.     <section class="blo-section-box">
  185.         <div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-3">
  186.             <h2 class="mb-0">À la une</h2>
  187.             <a href="{{ path('blo_catalog') }}" class="small">Voir tout</a>
  188.         </div>
  189.         <div class="row g-3">
  190.             {% for product in featuredProducts %}
  191.             <div class="col-6 col-sm-4 col-md-3 col-lg-2">
  192.                     <div class="blo-product-box">
  193.                         <a href="{{ path('blo_product_show', {slug: product.slug}) }}" class="text-decoration-none text-dark d-block">
  194.                             <div class="img-wrap">
  195.                                 {% set firstImage = product.images|first %}
  196.                                 {% if firstImage %}<img src="{{ asset('uploads/' ~ firstImage.path) }}" alt="{{ product.title }}">{% else %}<i class="bi bi-image text-secondary"></i>{% endif %}
  197.                             </div>
  198.                             <div class="title">{{ product.title }}</div>
  199.                             <p class="price mb-0">{% if product.promoPrice %}<del>{{ product.price|blo_price(product.currency) }}</del> {{ product.promoPrice|blo_price(product.currency) }}{% else %}{{ product.price|blo_price(product.currency) }}{% endif %}</p>
  200.                         </a>
  201.                         <form action="{{ path('blo_cart_add', {productId: product.id}) }}" method="post" class="d-inline">
  202.                             <button type="submit" class="blo-product-add-btn" title="Ajouter au panier"><i class="bi bi-plus-lg fs-5"></i></button>
  203.                         </form>
  204.                     </div>
  205.             </div>
  206.             {% else %}
  207.             <div class="col-12 text-center py-4 text-muted">Aucun produit. <a href="{{ path('blo_catalog') }}">Parcourir le catalogue</a>.</div>
  208.             {% endfor %}
  209.         </div>
  210.     </section>
  211. </div>
  212. {% endblock %}