templates/pack/packFront.html.twig line 1

Open in your IDE?
  1. {% extends 'backfront.html.twig' %}
  2. {% block title %}Packs SIP Academy - Formations groupées et économiques{% endblock %}
  3. {% block meta_description %}
  4.     Découvrez nos packs de formation chez SIP Academy. Des offres groupées pour économiser sur vos formations et accélérer votre carrière.
  5. {% endblock %}
  6. {% block body %}
  7.     <style>
  8.         /* ===== COULEURS MODERNES ===== */
  9.         :root {
  10.             --gold: #FFAE27;
  11.             --gold-dark: #e09500;
  12.             --gold-light: #fff8e6;
  13.             --navy: #1F3971;
  14.             --navy-dark: #162d5a;
  15.             --navy-light: #e8edf8;
  16.             --text-dark: #1a2a3a;
  17.             --text-muted: #6c757d;
  18.             --border-light: #eef2f6;
  19.         }
  20.         /* ===== BREADCRUMB MODERNE ===== */
  21.         .breadcrumb-area {
  22.             background: linear-gradient(135deg, var(--navy) 0%, var(--navy-dark) 100%);
  23.             padding: 100px 0 120px;
  24.             position: relative;
  25.             text-align: center;
  26.         }
  27.         .breadcrumb-title h1 {
  28.             color: #fff;
  29.             font-size: 48px;
  30.             font-weight: 800;
  31.             margin-bottom: 10px;
  32.             letter-spacing: -1px;
  33.         }
  34.         .breadcrumb-list {
  35.             list-style: none;
  36.             padding: 0;
  37.             margin: 0;
  38.             display: flex;
  39.             justify-content: center;
  40.             gap: 15px;
  41.             align-items: center;
  42.         }
  43.         .breadcrumb-list li, .breadcrumb-list li a {
  44.             color: rgba(255,255,255,0.7);
  45.             font-size: 15px;
  46.             text-decoration: none;
  47.             transition: color 0.3s;
  48.         }
  49.         .breadcrumb-list li a:hover {
  50.             color: var(--gold);
  51.         }
  52.         .breadcrumb-list li.active {
  53.             color: var(--gold);
  54.         }
  55.         .breadcrumb-list li i {
  56.             font-size: 14px;
  57.             color: var(--gold);
  58.         }
  59.         /* ===== SECTION TITRES ===== */
  60.         .section-title-wrapper {
  61.             text-align: center;
  62.             margin-bottom: 50px;
  63.         }
  64.         .section-title h3 {
  65.             font-size: 36px;
  66.             font-weight: 800;
  67.             color: var(--text-dark);
  68.             margin-bottom: 12px;
  69.             position: relative;
  70.             display: inline-block;
  71.         }
  72.         .section-title h3::after {
  73.             content: '';
  74.             position: absolute;
  75.             bottom: -12px;
  76.             left: 50%;
  77.             transform: translateX(-50%);
  78.             width: 60px;
  79.             height: 4px;
  80.             background: linear-gradient(90deg, var(--gold), var(--gold-dark));
  81.             border-radius: 2px;
  82.         }
  83.         .section-title p {
  84.             font-size: 16px;
  85.             color: var(--text-muted);
  86.             margin-top: 20px;
  87.         }
  88.         /* ===== COURSE AREA ===== */
  89.         .course-area {
  90.             padding: 80px 0;
  91.             background: #fff;
  92.         }
  93.         /* CARTE PACK - HAUTEUR ÉGALE */
  94.         .single-item {
  95.             background: #fff;
  96.             border-radius: 20px;
  97.             overflow: hidden;
  98.             box-shadow: 0 5px 20px rgba(0,0,0,0.05);
  99.             transition: all 0.3s cubic-bezier(0.4,0,0.2,1);
  100.             height: 100%;
  101.             display: flex;
  102.             flex-direction: column;
  103.             border: 1px solid var(--border-light);
  104.         }
  105.         .single-item:hover {
  106.             transform: translateY(-8px);
  107.             box-shadow: 0 20px 40px rgba(31,57,113,0.15);
  108.             border-color: var(--gold);
  109.         }
  110.         /* IMAGE */
  111.         .single-item-image {
  112.             position: relative;
  113.             overflow: hidden;
  114.             height: 220px;
  115.             background: linear-gradient(135deg, #f8faff 0%, #fff 100%);
  116.             display: flex;
  117.             align-items: center;
  118.             justify-content: center;
  119.         }
  120.         .single-item-image a {
  121.             display: flex;
  122.             align-items: center;
  123.             justify-content: center;
  124.             width: 100%;
  125.             height: 100%;
  126.         }
  127.         .single-item-image img {
  128.             width: auto;
  129.             height: auto;
  130.             max-width: 100%;
  131.             max-height: 100%;
  132.             object-fit: contain;
  133.             transition: transform 0.4s ease;
  134.         }
  135.         .single-item:hover .single-item-image img {
  136.             transform: scale(1.05);
  137.         }
  138.         /* BADGE PACK (optionnel) */
  139.         .pack-badge {
  140.             position: absolute;
  141.             top: 15px;
  142.             right: 15px;
  143.             background: linear-gradient(135deg, var(--gold), var(--gold-dark));
  144.             color: var(--navy);
  145.             padding: 6px 14px;
  146.             border-radius: 20px;
  147.             font-size: 11px;
  148.             font-weight: 800;
  149.             text-transform: uppercase;
  150.             letter-spacing: 1px;
  151.             z-index: 3;
  152.             box-shadow: 0 4px 12px rgba(255,174,39,0.3);
  153.         }
  154.         /* CORPS DE LA CARTE */
  155.         .single-item-text {
  156.             padding: 20px;
  157.             flex: 1;
  158.             display: flex;
  159.             flex-direction: column;
  160.         }
  161.         .single-item-text h4 {
  162.             font-size: 18px;
  163.             font-weight: 700;
  164.             margin-bottom: 12px;
  165.             line-height: 1.4;
  166.             min-height: 50px;
  167.         }
  168.         .single-item-text h4 a {
  169.             color: var(--text-dark);
  170.             text-decoration: none;
  171.             transition: color 0.2s;
  172.         }
  173.         .single-item-text h4 a:hover {
  174.             color: var(--gold);
  175.         }
  176.         /* DESCRIPTION */
  177.         .single-item-text > p {
  178.             font-size: 13px;
  179.             color: var(--text-muted);
  180.             line-height: 1.6;
  181.             margin-bottom: 16px;
  182.             display: -webkit-box;
  183.             -webkit-line-clamp: 2;
  184.             -webkit-box-orient: vertical;
  185.             overflow: hidden;
  186.         }
  187.         /* BADGE ÉCONOMIE */
  188.         .economy-badge {
  189.             display: inline-block;
  190.             background: rgba(255,174,39,0.15);
  191.             color: var(--gold-dark);
  192.             font-size: 11px;
  193.             font-weight: 700;
  194.             padding: 4px 10px;
  195.             border-radius: 20px;
  196.             margin-bottom: 15px;
  197.             width: fit-content;
  198.         }
  199.         /* INFOS CARTE (PRIX + PANIER) */
  200.         .single-item-content {
  201.             display: flex;
  202.             justify-content: space-between;
  203.             align-items: center;
  204.             margin-top: auto;
  205.             padding-top: 15px;
  206.             border-top: 1px solid var(--border-light);
  207.         }
  208.         .single-item-comment-view {
  209.             display: flex;
  210.             gap: 15px;
  211.             align-items: center;
  212.         }
  213.         .single-item-comment-view span {
  214.             font-size: 18px;
  215.             font-weight: 700;
  216.             color: var(--gold);
  217.             display: flex;
  218.             align-items: center;
  219.             gap: 5px;
  220.         }
  221.         .single-item-comment-view span svg {
  222.             width: 24px;
  223.             height: 24px;
  224.         }
  225.         .single-item-comment-view span svg path {
  226.             fill: var(--gold);
  227.         }
  228.         /* PRIX BARRÉ (ancien prix) */
  229.         .old-price {
  230.             font-size: 13px;
  231.             color: var(--text-muted);
  232.             text-decoration: line-through;
  233.             margin-left: 8px;
  234.             font-weight: normal;
  235.         }
  236.         /* BOUTON PANIER */
  237.         .btn-ajout-panier {
  238.             background: linear-gradient(135deg, var(--navy), var(--navy-dark));
  239.             border: none;
  240.             color: white;
  241.             padding: 10px 15px;
  242.             border-radius: 12px;
  243.             transition: all 0.3s ease;
  244.             cursor: pointer;
  245.             display: flex;
  246.             align-items: center;
  247.             justify-content: center;
  248.         }
  249.         .btn-ajout-panier:hover {
  250.             background: linear-gradient(135deg, var(--gold), var(--gold-dark));
  251.             transform: translateY(-2px);
  252.             box-shadow: 0 4px 12px rgba(255,174,39,0.3);
  253.         }
  254.         .btn-ajout-panier svg {
  255.             width: 22px;
  256.             height: 22px;
  257.         }
  258.         .btn-ajout-panier svg path {
  259.             fill: #fff;
  260.             transition: fill 0.3s ease;
  261.         }
  262.         .btn-ajout-panier:hover svg path {
  263.             fill: var(--navy);
  264.         }
  265.         .btn-ajout-panier:disabled {
  266.             opacity: 0.5;
  267.             cursor: not-allowed;
  268.             transform: none;
  269.         }
  270.         /* MESSAGE AUCUN PACK */
  271.         .no-packs-message {
  272.             text-align: center;
  273.             padding: 60px 40px;
  274.             background: #fff;
  275.             border-radius: 24px;
  276.             border: 1px solid var(--border-light);
  277.             box-shadow: 0 5px 20px rgba(0,0,0,0.05);
  278.             max-width: 500px;
  279.             margin: 0 auto;
  280.         }
  281.         .no-packs-icon {
  282.             font-size: 64px;
  283.             color: var(--gold);
  284.             margin-bottom: 20px;
  285.         }
  286.         .no-packs-message h3 {
  287.             font-size: 24px;
  288.             font-weight: 700;
  289.             color: var(--text-dark);
  290.             margin-bottom: 12px;
  291.         }
  292.         .no-packs-message p {
  293.             font-size: 15px;
  294.             color: var(--text-muted);
  295.             margin-bottom: 25px;
  296.         }
  297.         /* PAGINATION */
  298.         .pagination-wrapper {
  299.             margin-top: 40px;
  300.             text-align: center;
  301.         }
  302.         .pagination {
  303.             display: flex;
  304.             justify-content: center;
  305.             gap: 8px;
  306.             list-style: none;
  307.             padding: 0;
  308.             margin: 0;
  309.         }
  310.         .pagination .page-item {
  311.             list-style: none;
  312.         }
  313.         .pagination .page-link {
  314.             display: flex;
  315.             align-items: center;
  316.             justify-content: center;
  317.             width: 40px;
  318.             height: 40px;
  319.             border-radius: 12px;
  320.             background: #fff;
  321.             border: 1px solid var(--border-light);
  322.             color: var(--navy);
  323.             font-weight: 500;
  324.             text-decoration: none;
  325.             transition: all 0.3s ease;
  326.         }
  327.         .pagination .page-link:hover {
  328.             background: var(--gold);
  329.             border-color: var(--gold);
  330.             color: var(--navy);
  331.         }
  332.         .pagination .active .page-link {
  333.             background: linear-gradient(135deg, var(--navy), var(--navy-dark));
  334.             border-color: var(--navy);
  335.             color: #fff;
  336.         }
  337.         /* RESPONSIVE */
  338.         @media (max-width: 768px) {
  339.             .section-title h3 {
  340.                 font-size: 28px;
  341.             }
  342.             .single-item-image {
  343.                 height: 180px;
  344.             }
  345.             .single-item-text h4 {
  346.                 font-size: 16px;
  347.                 min-height: auto;
  348.             }
  349.             .pagination .page-link {
  350.                 width: 36px;
  351.                 height: 36px;
  352.                 font-size: 13px;
  353.             }
  354.             .breadcrumb-title h1 {
  355.                 font-size: 32px;
  356.             }
  357.             .single-item-comment-view span {
  358.                 font-size: 16px;
  359.             }
  360.             .single-item-comment-view span svg {
  361.                 width: 20px;
  362.                 height: 20px;
  363.             }
  364.             .btn-ajout-panier {
  365.                 padding: 8px 12px;
  366.             }
  367.             .btn-ajout-panier svg {
  368.                 width: 18px;
  369.                 height: 18px;
  370.             }
  371.         }
  372.     </style>
  373.     <!-- BREADCRUMB AREA -->
  374.     <div class="breadcrumb-area">
  375.         <div class="container">
  376.             <div class="row">
  377.                 <div class="col-md-12">
  378.                     <div class="breadcrumb-title">
  379.                         <h1>Nos Packs</h1>
  380.                         <ul class="breadcrumb-list">
  381.                             <li><a href="{{ path('app_home') }}">Accueil</a></li>
  382.                             <li><i class="zmdi zmdi-chevron-right"></i></li>
  383.                             <li class="active">Packs</li>
  384.                         </ul>
  385.                     </div>
  386.                 </div>
  387.             </div>
  388.         </div>
  389.     </div>
  390.     <!-- COURSE AREA -->
  391.     <div class="course-area">
  392.         <div class="container">
  393.             <div class="row">
  394.                 <div class="col-md-12">
  395.                     <div class="section-title-wrapper">
  396.                         <div class="section-title">
  397.                             <h3>Nos Packs</h3>
  398.                             <p>Des offres groupées économiques pour accélérer votre carrière</p>
  399.                         </div>
  400.                     </div>
  401.                 </div>
  402.             </div>
  403.             <div class="row">
  404.                 {% if packs is empty %}
  405.                     <div class="col-md-12">
  406.                         <div class="no-packs-message">
  407.                             <div class="no-packs-icon">
  408.                                 <i class="zmdi zmdi-info-outline"></i>
  409.                             </div>
  410.                             <h3>Aucun pack disponible</h3>
  411.                             <p>De nouveaux packs seront bientôt disponibles. Revenez prochainement !</p>
  412.                         </div>
  413.                     </div>
  414.                 {% else %}
  415.                     {% for pack in packs %}
  416.                         <div class="col-lg-4 col-md-6 col-12 mb-4 d-flex">
  417.                             <div class="single-item w-100">
  418.                                 <div class="single-item-image overlay-effect">
  419.                                     <a href="#">
  420.                                         <img src="{{ asset('uploads/formation/' ~ pack.image) }}" alt="{{ pack.libelle }}">
  421.                                     </a>
  422.                                 </div>
  423.                                 <div class="single-item-text">
  424.                                     <h4><a href="#">{{ pack.libelle }}</a></h4>
  425. {#                                    <div class="economy-badge">#}
  426. {#                                        <i class="zmdi zmdi-trending-down"></i> Économisez jusqu'à 30%#}
  427. {#                                    </div>#}
  428.                                     <p>
  429.                                         {% if pack.description|striptags|length > 100 %}
  430.                                             {{ pack.description|striptags|slice(0, 100) }}...
  431.                                         {% else %}
  432.                                             {{ pack.description|striptags }}
  433.                                         {% endif %}
  434.                                     </p>
  435.                                     <div class="single-item-content">
  436.                                         <div class="single-item-comment-view">
  437.                                             <span>
  438.                                                 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  439.                                                     <path d="M4.616 19q-.691 0-1.153-.462T3 17.384V6.616q0-.691.463-1.153T4.615 5h14.77q.69 0 1.152.463T21 6.616v10.769q0 .69-.463 1.153T19.385 19zm5.884-4.5H7q-.213 0-.356.144t-.144.357t.144.356T7 15.5h1.5v.5q0 .213.144.356t.357.144t.356-.144T9.5 16v-.5h1.23q.328 0 .549-.221t.221-.548v-2.462q0-.327-.221-.548t-.548-.221H7.5v-2H11q.213 0 .356-.144t.144-.357t-.144-.356T11 8.5H9.5V8q0-.213-.145-.356q-.146-.144-.36-.144q-.203 0-.317.16q-.115.161-.178.34v.5H7.27q-.328 0-.549.221T6.5 9.27v2.462q0 .327.221.548t.548.221H10.5zm5.637 1.344l1.054-1.053q.105-.106.055-.227t-.192-.122h-2.112q-.132 0-.185.122q-.053.12.053.227l1.053 1.053q.056.056.135.056t.139-.056m-1.19-6.036h2.111q.133 0 .185-.121q.053-.121-.052-.227l-1.054-1.053q-.056-.057-.135-.057t-.138.056L14.81 9.46q-.106.106-.056.227q.05.12.192.12"/>
  440.                                                 </svg>
  441.                                                 {{ pack.prix }} DT
  442.                                             </span>
  443.                                         </div>
  444.                                         <button class="btn-ajout-panier" data-id="{{ pack.id }}">
  445.                                             <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
  446.                                                 <path d="M1015.66 284a31.82 31.82 0 0 0-25.999-13.502h-99.744L684.78 95.666c-24.976-24.976-65.52-25.008-90.495 0L392.638 270.498h-82.096l-51.408-177.28c-20.16-69.808-68.065-77.344-87.713-77.344H34.333c-17.568 0-31.776 14.224-31.776 31.776S16.78 79.425 34.332 79.425h137.056c4.336 0 17.568 0 26.593 31.184l176.848 649.936c3.84 13.712 16.336 23.183 30.592 23.183h431.968c13.408 0 25.376-8.4 29.904-21.024l152.256-449.68c3.504-9.744 2.048-20.592-3.888-29.024zM639.537 140.93l152.032 129.584H487.457zm175.488 579.263H429.538L328.386 334.065h616.096zm-63.023 127.936c-44.192 0-80 35.808-80 80s35.808 80 80 80s80-35.808 80-80s-35.808-80-80-80m-288 0c-44.192 0-80 35.808-80 80s35.808 80 80 80s80-35.808 80-80s-35.808-80-80-80"/>
  447.                                             </svg>
  448.                                         </button>
  449.                                     </div>
  450.                                 </div>
  451.                             </div>
  452.                         </div>
  453.                     {% endfor %}
  454.                 {% endif %}
  455.             </div>
  456.             <!-- PAGINATION -->
  457.             {% if paginator is defined and paginator.pageCount > 1 %}
  458.                 <div class="row">
  459.                     <div class="col-12">
  460.                         <div class="pagination-wrapper">
  461.                             {{ knp_pagination_render(paginator, 'formation/custom_pagination.html.twig') }}
  462.                         </div>
  463.                     </div>
  464.                 </div>
  465.             {% endif %}
  466.         </div>
  467.     </div>
  468.     <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
  469.     <script>
  470.         document.addEventListener('DOMContentLoaded', () => {
  471.             const cartCount = document.getElementById('cart-count');
  472.             document.querySelectorAll('.btn-ajout-panier').forEach(button => {
  473.                 button.addEventListener('click', () => {
  474.                     const packId = button.dataset.id;
  475.                     fetch(`/panier/ajouter/${packId}`, {
  476.                         method: 'POST',
  477.                         headers: { 'X-Requested-With': 'XMLHttpRequest' }
  478.                     })
  479.                         .then(response => response.json())
  480.                         .then(data => {
  481.                             if (data.status === 'ok') {
  482.                                 if (cartCount) cartCount.textContent = data.total_items;
  483.                                 Swal.fire({
  484.                                     icon: 'success',
  485.                                     title: 'Pack ajouté au panier !',
  486.                                     text: data.message,
  487.                                     timer: 1500,
  488.                                     showConfirmButton: false,
  489.                                     background: '#fff',
  490.                                     customClass: {
  491.                                         popup: 'swal-popup'
  492.                                     }
  493.                                 });
  494.                                 button.disabled = true;
  495.                                 button.style.opacity = '0.6';
  496.                                 button.style.cursor = 'not-allowed';
  497.                             } else if (data.status === 'already_in_cart') {
  498.                                 Swal.fire({
  499.                                     icon: 'info',
  500.                                     title: 'Déjà dans le panier',
  501.                                     text: data.message,
  502.                                     confirmButtonColor: '#FFAE27'
  503.                                 });
  504.                                 button.disabled = true;
  505.                                 button.style.opacity = '0.6';
  506.                                 button.style.cursor = 'not-allowed';
  507.                             } else {
  508.                                 Swal.fire({
  509.                                     icon: 'error',
  510.                                     title: 'Erreur',
  511.                                     text: data.message ?? 'Erreur lors de l\'ajout au panier.',
  512.                                     confirmButtonColor: '#FFAE27'
  513.                                 });
  514.                             }
  515.                         })
  516.                         .catch(() => {
  517.                             Swal.fire({
  518.                                 icon: 'error',
  519.                                 title: 'Erreur réseau',
  520.                                 text: 'Impossible d\'ajouter le pack.',
  521.                                 confirmButtonColor: '#FFAE27'
  522.                             });
  523.                         });
  524.                 });
  525.             });
  526.         });
  527.     </script>
  528. {% endblock %}