PageSourceSearch

https://www.aratice.fr/wp-content/themes/aratice/assets/js/quote-notifications.js?ver=1780661389

js aratice.fr collected 2026-10-08 19:25:35 UTC 8,742 bytes, 188 lines download raw bytes

1/**
2 * Aratice Quote Notifications
3 * Système de notifications pour les actions sur le devis
4 */
5
6(function ($) {
7  "use strict";
8
9  // Container pour les notifications (créé dynamiquement)
10  let $notificationContainer = null;
11
12  /**
13   * Initialiser le container de notifications
14   */
15  function initNotificationContainer() {
16    if ($notificationContainer) {
17      return;
18    }
19
20    // Injecter les styles critiques inline pour garantir l'affichage
21    // même si le CSS externe est différé/supprimé par un plugin de cache
22    if (!document.getElementById("aratice-notif-inline-css")) {
23      var style = document.createElement("style");
24      style.id = "aratice-notif-inline-css";
25      style.textContent =
26        ".aratice-notifications-container{position:fixed;top:24px;right:24px;z-index:99999;display:flex;flex-direction:column;gap:12px;pointer-events:none;max-width:420px}" +
27        ".aratice-notification{display:flex;align-items:flex-start;gap:12px;padding:16px 20px;background:#fff;border-radius:12px;box-shadow:0 4px 12px rgba(0,0,0,.15),0 0 0 1px rgba(0,0,0,.05);pointer-events:auto;opacity:0;transform:translateX(400px);transition:all .3s cubic-bezier(.4,0,.2,1);max-width:100%;position:relative;overflow:hidden;font-family:'Lexend Deca',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif}" +
28        ".aratice-notification-show{opacity:1;transform:translateX(0)}" +
29        ".aratice-notification::before{content:'';position:absolute;bottom:0;left:0;height:3px;width:100%;transform-origin:left;animation:notifProg 3s linear forwards}" +
30        "@keyframes notifProg{from{transform:scaleX(1)}to{transform:scaleX(0)}}" +
31        ".aratice-notification-icon{flex-shrink:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center}" +
32        ".aratice-notification-icon svg{width:24px;height:24px}" +
33        ".aratice-notification-message{flex:1;font-size:14px;line-height:1.5;color:#1a1a1a;word-break:break-word}" +
34        ".aratice-notification-message strong{font-weight:600;color:#000}" +
35        ".aratice-notification-close{flex-shrink:0;width:20px;height:20px;padding:0;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:4px;color:#666}" +
36        ".aratice-notification-close svg{width:16px;height:16px}" +
37        ".aratice-notification-success{border-left:4px solid #7EAD53}" +
38        ".aratice-notification-success .aratice-notification-icon{color:#7EAD53}" +
39        ".aratice-notification-success::before{background:#7EAD53}" +
40        ".aratice-notification-error{border-left:4px solid #ef4444}" +
41        ".aratice-notification-error .aratice-notification-icon{color:#ef4444}" +
42        ".aratice-notification-error::before{background:#ef4444}" +
43        ".aratice-notification-info{border-left:4px solid #2B4B7C}" +
44        ".aratice-notification-info .aratice-notification-icon{color:#2B4B7C}" +
45        ".aratice-notification-info::before{background:#2B4B7C}" +
46        ".aratice-notification-warning{border-left:4px solid #f59e0b}" +
47        ".aratice-notification-warning .aratice-notification-icon{color:#f59e0b}" +
48        ".aratice-notification-warning::before{background:#f59e0b}";
49      document.head.appendChild(style);
50    }
51
52    $notificationContainer = $(
53      '<div class="aratice-notifications-container"></div>'
54    );
55    $("body").append($notificationContainer);
56  }
57
58  /**
59   * Afficher une notification
60   * @param {string} message - Message à afficher
61   * @param {string} type - Type de notification (success, error, info, warning)
62   * @param {number} duration - Durée d'affichage en ms (0 = permanent)
63   */
64  function showNotification(message, type = "success", duration = 3000) {
65    initNotificationContainer();
66
67    // Icône selon le type
68    const icons = {
69      success: `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
70                <path d="M9 12L11 14L15 10M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" 
71                stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
72              </svg>`,
73      error: `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
74              <path d="M12 8V12M12 16H12.01M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" 
75              stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
76            </svg>`,
77      info: `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
78             <path d="M12 16V12M12 8H12.01M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" 
79             stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
80           </svg>`,
81      warning: `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
82                <path d="M12 9V13M12 17H12.01M10.29 3.86L1.82 18C1.64537 18.3024 1.55297 18.6453 1.55199 18.9945C1.55101 19.3437 1.64149 19.6871 1.81441 19.9905C1.98733 20.2939 2.23641 20.5467 2.53682 20.7239C2.83723 20.9012 3.17975 20.9962 3.53 21H20.47C20.8203 20.9962 21.1628 20.9012 21.4632 20.7239C21.7636 20.5467 22.0127 20.2939 22.1856 19.9905C22.3585 19.6871 22.449 19.3437 22.448 18.9945C22.447 18.6453 22.3546 18.3024 22.18 18L13.71 3.86C13.5317 3.56611 13.2807 3.32312 12.9812 3.15448C12.6817 2.98585 12.3437 2.89725 12 2.89725C11.6563 2.89725 11.3183 2.98585 11.0188 3.15448C10.7193 3.32312 10.4683 3.56611 10.29 3.86Z" 
83                stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
84              </svg>`,
85    };
86
87    // Créer la notification
88    const $notification = $(`
89      <div class="aratice-notification aratice-notification-${type}">
90        <div class="aratice-notification-icon">
91          ${icons[type] || icons.info}
92        </div>
93        <div class="aratice-notification-message">${message}</div>
94        <button class="aratice-notification-close" aria-label="Fermer">
95          <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
96            <path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
97          </svg>
98        </button>
99      </div>
100    `);
101
102    // Ajouter au container
103    $notificationContainer.append($notification);
104
105    // Animation d'entrée
106    setTimeout(() => {
107      $notification.addClass("aratice-notification-show");
108    }, 10);
109
110    // Bouton fermer
111    $notification.find(".aratice-notification-close").on("click", function () {
112      closeNotification($notification);
113    });
114
115    // Auto-fermeture si durée définie
116    if (duration > 0) {
117      setTimeout(() => {
118        closeNotification($notification);
119      }, duration);
120    }
121
122    return $notification;
123  }
124
125  /**
126   * Fermer une notification
127   * @param {jQuery} $notification - Élément notification à fermer
128   */
129  function closeNotification($notification) {
130    $notification.removeClass("aratice-notification-show");
131    setTimeout(() => {
132      $notification.remove();
133    }, 300);
134  }
135
136  /**
137   * Écouter les événements de devis
138   */
139  function listenToQuoteEvents() {
140    // Ajout de produit uniquement
141    $(document).on(
142      "aratice:product_added_to_quote",
143      function (e, productId, data) {
144        // Gérer deux formats de données :
145        // 1. { product: result.item, totals } (products-grid, quote-drag-drop, etc.)
146        // 2. result.item directement (product-options-sidebar, product-cart)
147        let productName = "Produit";
148        
149        if (data?.product?.title) {
150          // Format 1: data contient product
151          productName = data.product.title;
152        } else if (data?.title) {
153          // Format 2: data est directement l'item
154          productName = data.title;
155        }
156
157        showNotification(
158          `<strong>${productName}</strong> ajouté au devis`,
159          "success",
160          3000
161        );
162      }
163    );
164  }
165
166  /**
167   * Initialisation
168   */
169  $(document).ready(function () {
170    // Attendre que QuoteStorage soit disponible
171    const initInterval = setInterval(() => {
172      if (window.QuoteStorage) {
173        clearInterval(initInterval);
174        listenToQuoteEvents();
175        console.log("✅ Quote Notifications initialisées");
176      }
177    }, 100);
178
179    // Timeout après 5 secondes
180    setTimeout(() => {
181      clearInterval(initInterval);
182    }, 5000);
183  });
184
185  // Exposer la fonction globalement pour utilisation externe
186  window.araticeShowNotification = showNotification;
187})(jQuery);
188

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.