templates/formation_elearning/formationFront.html.twig line 1

Open in your IDE?
  1. {% extends 'backfront.html.twig' %}
  2. {% block title %}Formations E-learning SIP Academy - Apprenez en ligne à votre rythme{% endblock %}
  3. {% block meta_description %}
  4.     Découvrez nos formations E-learning chez SIP Academy. Apprenez en ligne à votre rythme avec nos cours certifiants et formateurs experts.
  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 FORMATION - 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.         /* OVERLAY HOVER */
  139.         .overlay-effect {
  140.             position: relative;
  141.         }
  142.         .courses-hover-info {
  143.             position: absolute;
  144.             bottom: -100%;
  145.             left: 0;
  146.             right: 0;
  147.             background: linear-gradient(135deg, rgba(31,57,113,0.95), rgba(22,45,90,0.95));
  148.             padding: 15px;
  149.             transition: bottom 0.3s ease;
  150.             backdrop-filter: blur(5px);
  151.             z-index: 10;
  152.         }
  153.         .single-item:hover .courses-hover-info {
  154.             bottom: 0;
  155.         }
  156.         .courses-hover-action {
  157.             display: flex;
  158.             align-items: center;
  159.             gap: 12px;
  160.             flex-wrap: wrap;
  161.         }
  162.         .courses-hover-thumb img {
  163.             width: 40px;
  164.             height: 40px;
  165.             border-radius: 50%;
  166.             object-fit: cover;
  167.             border: 2px solid var(--gold);
  168.         }
  169.         .courses-hover-action h4 a {
  170.             color: #fff;
  171.             font-size: 14px;
  172.             font-weight: 600;
  173.             text-decoration: none;
  174.         }
  175.         .courses-hover-action h4 a:hover {
  176.             color: var(--gold);
  177.         }
  178.         .crs-separator {
  179.             color: var(--gold);
  180.         }
  181.         .courses-hover-action p {
  182.             color: rgba(255,255,255,0.8);
  183.             font-size: 11px;
  184.             margin: 0;
  185.         }
  186.         /* CORPS DE LA CARTE */
  187.         .single-item-text {
  188.             padding: 20px;
  189.             flex: 1;
  190.             display: flex;
  191.             flex-direction: column;
  192.         }
  193.         .single-item-text h4 {
  194.             font-size: 18px;
  195.             font-weight: 700;
  196.             margin-bottom: 12px;
  197.             line-height: 1.4;
  198.             min-height: 50px;
  199.         }
  200.         .single-item-text h4 a {
  201.             color: var(--text-dark);
  202.             text-decoration: none;
  203.             transition: color 0.2s;
  204.         }
  205.         .single-item-text h4 a:hover {
  206.             color: var(--gold);
  207.         }
  208.         /* DESCRIPTION */
  209.         .single-item-text > p {
  210.             font-size: 13px;
  211.             color: var(--text-muted);
  212.             line-height: 1.6;
  213.             margin-bottom: 16px;
  214.             display: -webkit-box;
  215.             -webkit-line-clamp: 2;
  216.             -webkit-box-orient: vertical;
  217.             overflow: hidden;
  218.         }
  219.         /* INFOS CARTE (PRIX + PANIER) */
  220.         .single-item-content {
  221.             display: flex;
  222.             justify-content: space-between;
  223.             align-items: center;
  224.             margin-top: auto;
  225.             padding-top: 15px;
  226.             border-top: 1px solid var(--border-light);
  227.         }
  228.         .single-item-comment-view {
  229.             display: flex;
  230.             gap: 15px;
  231.             align-items: center;
  232.         }
  233.         .single-item-comment-view span {
  234.             font-size: 18px;
  235.             font-weight: 700;
  236.             color: var(--gold);
  237.             display: flex;
  238.             align-items: center;
  239.             gap: 5px;
  240.         }
  241.         .single-item-comment-view span svg {
  242.             width: 24px;
  243.             height: 24px;
  244.         }
  245.         .single-item-comment-view span svg path {
  246.             fill: var(--gold);
  247.         }
  248.         /* BOUTON PANIER */
  249.         .btn-ajout-panier {
  250.             background: linear-gradient(135deg, var(--navy), var(--navy-dark));
  251.             border: none;
  252.             color: white;
  253.             padding: 10px 15px;
  254.             border-radius: 12px;
  255.             transition: all 0.3s ease;
  256.             cursor: pointer;
  257.             display: flex;
  258.             align-items: center;
  259.             justify-content: center;
  260.         }
  261.         .btn-ajout-panier:hover {
  262.             background: linear-gradient(135deg, var(--gold), var(--gold-dark));
  263.             transform: translateY(-2px);
  264.             box-shadow: 0 4px 12px rgba(255,174,39,0.3);
  265.         }
  266.         .btn-ajout-panier svg {
  267.             width: 22px;
  268.             height: 22px;
  269.         }
  270.         .btn-ajout-panier svg path {
  271.             fill: #fff;
  272.             transition: fill 0.3s ease;
  273.         }
  274.         .btn-ajout-panier:hover svg path {
  275.             fill: var(--navy);
  276.         }
  277.         .btn-ajout-panier:disabled {
  278.             opacity: 0.5;
  279.             cursor: not-allowed;
  280.             transform: none;
  281.         }
  282.         /* MESSAGE AUCUNE FORMATION */
  283.         .no-formations-message {
  284.             text-align: center;
  285.             padding: 60px 40px;
  286.             background: #fff;
  287.             border-radius: 24px;
  288.             border: 1px solid var(--border-light);
  289.             box-shadow: 0 5px 20px rgba(0,0,0,0.05);
  290.             max-width: 500px;
  291.             margin: 0 auto;
  292.         }
  293.         .no-formations-icon {
  294.             font-size: 64px;
  295.             color: var(--gold);
  296.             margin-bottom: 20px;
  297.         }
  298.         .no-formations-message h3 {
  299.             font-size: 24px;
  300.             font-weight: 700;
  301.             color: var(--text-dark);
  302.             margin-bottom: 12px;
  303.         }
  304.         .no-formations-message p {
  305.             font-size: 15px;
  306.             color: var(--text-muted);
  307.             margin-bottom: 25px;
  308.         }
  309.         /* PAGINATION */
  310.         .pagination-wrapper {
  311.             margin-top: 40px;
  312.             text-align: center;
  313.         }
  314.         .pagination {
  315.             display: flex;
  316.             justify-content: center;
  317.             gap: 8px;
  318.             list-style: none;
  319.             padding: 0;
  320.             margin: 0;
  321.         }
  322.         .pagination .page-item {
  323.             list-style: none;
  324.         }
  325.         .pagination .page-link {
  326.             display: flex;
  327.             align-items: center;
  328.             justify-content: center;
  329.             width: 40px;
  330.             height: 40px;
  331.             border-radius: 12px;
  332.             background: #fff;
  333.             border: 1px solid var(--border-light);
  334.             color: var(--navy);
  335.             font-weight: 500;
  336.             text-decoration: none;
  337.             transition: all 0.3s ease;
  338.         }
  339.         .pagination .page-link:hover {
  340.             background: var(--gold);
  341.             border-color: var(--gold);
  342.             color: var(--navy);
  343.         }
  344.         .pagination .active .page-link {
  345.             background: linear-gradient(135deg, var(--navy), var(--navy-dark));
  346.             border-color: var(--navy);
  347.             color: #fff;
  348.         }
  349.         /* RESPONSIVE */
  350.         @media (max-width: 768px) {
  351.             .section-title h3 {
  352.                 font-size: 28px;
  353.             }
  354.             .single-item-image {
  355.                 height: 180px;
  356.             }
  357.             .single-item-text h4 {
  358.                 font-size: 16px;
  359.                 min-height: auto;
  360.             }
  361.             .pagination .page-link {
  362.                 width: 36px;
  363.                 height: 36px;
  364.                 font-size: 13px;
  365.             }
  366.             .breadcrumb-title h1 {
  367.                 font-size: 32px;
  368.             }
  369.             .single-item-comment-view span {
  370.                 font-size: 16px;
  371.             }
  372.         }
  373.         @media (max-width: 576px) {
  374.             .single-item-comment-view span svg {
  375.                 width: 20px;
  376.                 height: 20px;
  377.             }
  378.             .btn-ajout-panier {
  379.                 padding: 8px 12px;
  380.             }
  381.             .btn-ajout-panier svg {
  382.                 width: 18px;
  383.                 height: 18px;
  384.             }
  385.         }
  386.         /* Informations formateur dans la carte */
  387.         .formateur-info {
  388.             display: flex;
  389.             align-items: center;
  390.             gap: 12px;
  391.             margin-bottom: 15px;
  392.             padding: 10px;
  393.             background: var(--navy-light);
  394.             border-radius: 12px;
  395.             transition: all 0.3s ease;
  396.         }
  397.         .single-item:hover .formateur-info {
  398.             background: rgba(255,174,39,0.1);
  399.             transform: translateX(5px);
  400.         }
  401.         .formateur-avatar img {
  402.             width: 40px;
  403.             height: 40px;
  404.             border-radius: 50%;
  405.             object-fit: cover;
  406.             border: 2px solid var(--gold);
  407.         }
  408.         .formateur-details {
  409.             display: flex;
  410.             flex-direction: column;
  411.         }
  412.         .formateur-name {
  413.             font-size: 13px;
  414.             font-weight: 700;
  415.             color: var(--text-dark);
  416.         }
  417.         .formateur-poste {
  418.             font-size: 11px;
  419.             color: var(--text-muted);
  420.         }
  421.         /* ===== TOAST NOTIFICATIONS STYLE ===== */
  422.         .toast-notification {
  423.             position: fixed;
  424.             bottom: 30px;
  425.             right: 30px;
  426.             z-index: 9999;
  427.             min-width: 320px;
  428.             max-width: 400px;
  429.             background: white;
  430.             border-radius: 16px;
  431.             box-shadow: 0 10px 40px rgba(0,0,0,0.15);
  432.             padding: 0;
  433.             overflow: hidden;
  434.             animation: slideInRight 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
  435.             border-left: 4px solid;
  436.         }
  437.         @keyframes slideInRight {
  438.             from {
  439.                 transform: translateX(100%);
  440.                 opacity: 0;
  441.             }
  442.             to {
  443.                 transform: translateX(0);
  444.                 opacity: 1;
  445.             }
  446.         }
  447.         .toast-notification.toast-success {
  448.             border-left-color: #28a745;
  449.         }
  450.         .toast-notification.toast-success .toast-header {
  451.             background: linear-gradient(135deg, #28a745, #20c997);
  452.         }
  453.         .toast-notification.toast-success .toast-icon i {
  454.             color: #28a745;
  455.         }
  456.         .toast-notification.toast-info {
  457.             border-left-color: #17a2b8;
  458.         }
  459.         .toast-notification.toast-info .toast-header {
  460.             background: linear-gradient(135deg, #17a2b8, #6f42c1);
  461.         }
  462.         .toast-notification.toast-info .toast-icon i {
  463.             color: #17a2b8;
  464.         }
  465.         .toast-notification.toast-error {
  466.             border-left-color: #dc3545;
  467.         }
  468.         .toast-notification.toast-error .toast-header {
  469.             background: linear-gradient(135deg, #dc3545, #c82333);
  470.         }
  471.         .toast-notification.toast-error .toast-icon i {
  472.             color: #dc3545;
  473.         }
  474.         .toast-notification.toast-warning {
  475.             border-left-color: #ffc107;
  476.         }
  477.         .toast-notification.toast-warning .toast-header {
  478.             background: linear-gradient(135deg, #ffc107, #fd7e14);
  479.         }
  480.         .toast-content {
  481.             display: flex;
  482.             align-items: center;
  483.             padding: 16px;
  484.             gap: 12px;
  485.         }
  486.         .toast-icon {
  487.             flex-shrink: 0;
  488.             width: 40px;
  489.             height: 40px;
  490.             background: rgba(0,0,0,0.05);
  491.             border-radius: 50%;
  492.             display: flex;
  493.             align-items: center;
  494.             justify-content: center;
  495.         }
  496.         .toast-icon i {
  497.             font-size: 20px;
  498.         }
  499.         .toast-text {
  500.             flex: 1;
  501.         }
  502.         .toast-title {
  503.             font-weight: 700;
  504.             font-size: 14px;
  505.             color: #1a2a3a;
  506.             margin-bottom: 4px;
  507.         }
  508.         .toast-message {
  509.             font-size: 12px;
  510.             color: #6c757d;
  511.             line-height: 1.4;
  512.         }
  513.         .toast-close {
  514.             flex-shrink: 0;
  515.             width: 28px;
  516.             height: 28px;
  517.             border-radius: 50%;
  518.             background: rgba(0,0,0,0.05);
  519.             border: none;
  520.             cursor: pointer;
  521.             display: flex;
  522.             align-items: center;
  523.             justify-content: center;
  524.             transition: all 0.2s;
  525.         }
  526.         .toast-close:hover {
  527.             background: rgba(0,0,0,0.1);
  528.         }
  529.         .toast-close i {
  530.             font-size: 14px;
  531.             color: #6c757d;
  532.         }
  533.         .toast-progress {
  534.             height: 3px;
  535.             background: rgba(0,0,0,0.1);
  536.             width: 100%;
  537.         }
  538.         .toast-progress-bar {
  539.             height: 100%;
  540.             width: 100%;
  541.             background: linear-gradient(90deg, #FFAE27, #e09500);
  542.             animation: progress 3s linear forwards;
  543.         }
  544.         @keyframes progress {
  545.             from { width: 100%; }
  546.             to { width: 0%; }
  547.         }
  548.         /* Responsive */
  549.         @media (max-width: 576px) {
  550.             .toast-notification {
  551.                 left: 15px;
  552.                 right: 15px;
  553.                 bottom: 15px;
  554.                 min-width: auto;
  555.                 max-width: none;
  556.             }
  557.         }
  558.     </style>
  559.     <!-- BREADCRUMB AREA -->
  560.     <div class="breadcrumb-area">
  561.         <div class="container">
  562.             <div class="row">
  563.                 <div class="col-md-12">
  564.                     <div class="breadcrumb-title">
  565.                         <h1>Formations E-learning</h1>
  566.                         <ul class="breadcrumb-list">
  567.                             <li><a href="{{ path('app_home') }}">Accueil</a></li>
  568.                             <li><i class="zmdi zmdi-chevron-right"></i></li>
  569.                             <li class="active">E-learning</li>
  570.                         </ul>
  571.                     </div>
  572.                 </div>
  573.             </div>
  574.         </div>
  575.     </div>
  576.     <!-- COURSE AREA -->
  577.     <div class="course-area">
  578.         <div class="container">
  579.             <div class="row">
  580.                 <div class="col-md-12">
  581.                     <div class="section-title-wrapper">
  582.                         <div class="section-title">
  583.                             <h3>
  584.                                 {% if slug is not null %}
  585.                                     Formations : {{ categories|filter(cat => cat.slug == slug)|first.libelle }}
  586.                                 {% else %}
  587.                                     Toutes les formations E-learning
  588.                                 {% endif %}
  589.                             </h3>
  590.                             <p>Apprenez en ligne à votre rythme avec nos formations certifiantes</p>
  591.                         </div>
  592.                     </div>
  593.                 </div>
  594.             </div>
  595.             <div class="row">
  596.                 {% if formation_elearnings is empty %}
  597.                     <div class="col-md-12">
  598.                         <div class="no-formations-message">
  599.                             <div class="no-formations-icon">
  600.                                 <i class="zmdi zmdi-info-outline"></i>
  601.                             </div>
  602.                             <h3>Aucune formation disponible</h3>
  603.                             <p>De nouvelles formations seront bientôt ajoutées. Revenez prochainement !</p>
  604.                         </div>
  605.                     </div>
  606.                 {% else %}
  607.                     {% for formation in formation_elearnings %}
  608.                         <div class="col-lg-4 col-md-6 col-12 mb-4 d-flex">
  609.                             <div class="single-item w-100">
  610.                                 <div class="single-item-image overlay-effect">
  611.                                     <a href="{{ path('app_formation_detailsfrontElearning', {'slug': formation.slug}) }}">
  612.                                         <img src="{{ asset('uploads/formation/' ~ formation.affiche) }}" alt="{{ formation.titre }}">
  613.                                     </a>
  614.                                 </div>
  615.                                 <div class="single-item-text">
  616.                                     <h4><a href="{{ path('app_formation_detailsfrontElearning', {'slug': formation.slug}) }}">{{ formation.titre }}</a></h4>
  617.                                     {% if formation.formateur %}
  618.                                         <div class="formateur-info">
  619.                                             <div class="formateur-avatar">
  620.                                                 <img src="{{ asset('uploads/coach/' ~ formation.formateur.logo) }}" alt="{{ formation.formateur.prenom }}">
  621.                                             </div>
  622.                                             <div class="formateur-details">
  623.                                                 <span class="formateur-name">{{ formation.formateur.prenom }} {{ formation.formateur.nom }}</span>
  624.                                                 <span class="formateur-poste">{{ formation.formateur.poste }}</span>
  625.                                             </div>
  626.                                         </div>
  627.                                     {% endif %}
  628.                                     <p>
  629.                                         {{ formation.description|striptags|slice(0, 200)|raw }}
  630.                                         {% if formation.description|striptags|length > 200 %}...{% endif %}
  631.                                     </p>
  632.                                     <div class="single-item-content">
  633.                                         <div class="single-item-comment-view">
  634.                                             <span>
  635.                                                 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  636.                                                     <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"/>
  637.                                                 </svg>
  638.                                                 {{ formation.prix }} DT
  639.                                             </span>
  640.                                         </div>
  641.                                         <button class="btn-ajout-panier" data-id="{{ formation.id }}">
  642.                                             <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
  643.                                                 <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"/>
  644.                                             </svg>
  645.                                         </button>
  646.                                     </div>
  647.                                 </div>
  648.                             </div>
  649.                         </div>
  650.                     {% endfor %}
  651.                 {% endif %}
  652.             </div>
  653.             <!-- PAGINATION -->
  654.             {% if paginator is defined and paginator.pageCount > 1 %}
  655.                 <div class="row">
  656.                     <div class="col-12">
  657.                         <div class="pagination-wrapper">
  658.                             {{ knp_pagination_render(paginator, 'formation/custom_pagination.html.twig') }}
  659.                         </div>
  660.                     </div>
  661.                 </div>
  662.             {% endif %}
  663.         </div>
  664.     </div>
  665.     <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
  666.     <script>
  667.         // Fonction Toast personnalisée
  668.         function showToast(type, title, message, duration = 3000) {
  669.             const icons = {
  670.                 success: '<i class="fa fa-check-circle"></i>',
  671.                 info: '<i class="fa fa-info-circle"></i>',
  672.                 error: '<i class="fa fa-exclamation-circle"></i>',
  673.                 warning: '<i class="fa fa-exclamation-triangle"></i>'
  674.             };
  675.             const toast = document.createElement('div');
  676.             toast.className = `toast-notification toast-${type}`;
  677.             toast.innerHTML = `
  678.         <div class="toast-content">
  679.             <div class="toast-icon">
  680.                 ${icons[type]}
  681.             </div>
  682.             <div class="toast-text">
  683.                 <div class="toast-title">${title}</div>
  684.                 <div class="toast-message">${message}</div>
  685.             </div>
  686.             <button class="toast-close">
  687.                 <i class="fa fa-times"></i>
  688.             </button>
  689.         </div>
  690.         <div class="toast-progress">
  691.             <div class="toast-progress-bar" style="animation-duration: ${duration}ms;"></div>
  692.         </div>
  693.     `;
  694.             document.body.appendChild(toast);
  695.             // Fermeture avec bouton
  696.             const closeBtn = toast.querySelector('.toast-close');
  697.             closeBtn.addEventListener('click', () => {
  698.                 toast.remove();
  699.             });
  700.             // Auto-fermeture
  701.             setTimeout(() => {
  702.                 if (toast.parentNode) toast.remove();
  703.             }, duration);
  704.         }
  705.         document.addEventListener('DOMContentLoaded', () => {
  706.             const cartCount = document.getElementById('cart-count');
  707.             document.querySelectorAll('.btn-ajout-panier').forEach(button => {
  708.                 button.addEventListener('click', () => {
  709.                     const formationId = button.dataset.id;
  710.                     fetch(`/panier/ajouter/${formationId}`, {
  711.                         method: 'POST',
  712.                         headers: { 'X-Requested-With': 'XMLHttpRequest' }
  713.                     })
  714.                         .then(response => response.json())
  715.                         .then(data => {
  716.                             if (data.status === 'ok') {
  717.                                 if (cartCount) cartCount.textContent = data.total_items;
  718.                                 showToast('success', 'Ajouté au panier !', data.message, 2000);
  719.                                 button.disabled = true;
  720.                                 button.style.opacity = '0.6';
  721.                                 button.style.cursor = 'not-allowed';
  722.                             } else if (data.status === 'already_in_cart') {
  723.                                 showToast('info', 'Déjà dans le panier', data.message, 2500);
  724.                                 button.disabled = true;
  725.                                 button.style.opacity = '0.6';
  726.                                 button.style.cursor = 'not-allowed';
  727.                                 showToast('error', 'Erreur', data.message ?? 'Erreur lors de l\'ajout au panier.', 3000);
  728.                             }
  729.                         })
  730.                         .catch(() => {
  731.                             showToast('error', 'Erreur réseau', 'Impossible d\'ajouter la formation.', 3000);
  732.                         });
  733.                 });
  734.             });
  735.         });
  736.     </script>
  737. {% endblock %}