Résultats

Explorez notre Univers.

Des produits d'exception et des services exclusifs réunis en un seul endroit.

0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE PELLUCHE REF TT25011" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-pelluche-ref-tt25011-xtxji", name: "TROUSSE PELLUCHE REF TT25011", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/AzTj4xPr-1783607269.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/AzTj4xPr-1783607269.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+PELLUCHE+REF+TT25011", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/AzTj4xPr-1783607269.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE PELLUCHE REF TT25011", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE PELLUCHE REF TT25011

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "BANANA REF U2056" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/banana-ref-u2056-zfld8", name: "BANANA REF U2056", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/rlbthOcK-1783607410.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/rlbthOcK-1783607410.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "BANANA", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+BANANA+REF+U2056", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/rlbthOcK-1783607410.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "BANANA REF U2056", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

BANANA REF U2056

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SUPPORT CHARIOT REF WL17-18" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/support-chariot-ref-wl17-18-r5cqn", name: "SUPPORT CHARIOT REF WL17-18", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/4HUEpwZk-1783607479.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/4HUEpwZk-1783607479.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SUPPORT CHARIOT", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SUPPORT+CHARIOT+REF+WL17-18", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/4HUEpwZk-1783607479.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SUPPORT CHARIOT REF WL17-18", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SUPPORT CHARIOT REF WL17-18

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF FM24-Y001" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-fm24-y001-u8ris", name: "TROUSSE REF FM24-Y001", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/RvFWHHiZ-1783607944.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/RvFWHHiZ-1783607944.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+FM24-Y001", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/RvFWHHiZ-1783607944.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF FM24-Y001", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF FM24-Y001

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SERVIETTE REF TT25002" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/serviette-ref-tt25002-h3uwe", name: "SERVIETTE REF TT25002", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/vsXlwUYC-1783607234.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/vsXlwUYC-1783607234.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SERVIETTE", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SERVIETTE+REF+TT25002", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/vsXlwUYC-1783607234.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SERVIETTE REF TT25002", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SERVIETTE REF TT25002

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF R2" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-r2-mi50y", name: "TROUSSE REF R2", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/Ht8yWIPr-1783607446.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/Ht8yWIPr-1783607446.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+R2", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/Ht8yWIPr-1783607446.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF R2", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF R2

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TABLEAUX REF N60\/90" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/tableaux-ref-n6090-n4sud", name: "TABLEAUX REF N60\/90", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/ZCazzi6R-1783607961.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/ZCazzi6R-1783607961.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "TABLEAUX", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TABLEAUX+REF+N60%2F90", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/ZCazzi6R-1783607961.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TABLEAUX REF N60\/90", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TABLEAUX REF N60/90

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TABLEAUX REF N90\/120" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/tableaux-ref-n90120-bct9m", name: "TABLEAUX REF N90\/120", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/mS5owy9z-1783607962.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/mS5owy9z-1783607962.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "TABLEAUX", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TABLEAUX+REF+N90%2F120", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/mS5owy9z-1783607962.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TABLEAUX REF N90\/120", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TABLEAUX REF N90/120

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF P003" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-p003-7ks7j", name: "TROUSSE REF P003", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/I1UCF37k-1783607427.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/I1UCF37k-1783607427.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+P003", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/I1UCF37k-1783607427.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF P003", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF P003

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF P007" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-p007-o1jtx", name: "TROUSSE REF P007", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/GuvD6xsu-1783607431.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/GuvD6xsu-1783607431.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+P007", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/GuvD6xsu-1783607431.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF P007", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF P007

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF P019" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-p019-phjdn", name: "TROUSSE REF P019", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/X4gz7UbX-1783607442.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/X4gz7UbX-1783607442.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+P019", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/X4gz7UbX-1783607442.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF P019", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF P019

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SUPPORT CHARIOT REF F27" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/support-chariot-ref-f27-nmiok", name: "SUPPORT CHARIOT REF F27", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/ZyVOZsua-1783607476.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/ZyVOZsua-1783607476.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SUPPORT CHARIOT", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SUPPORT+CHARIOT+REF+F27", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/ZyVOZsua-1783607476.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SUPPORT CHARIOT REF F27", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SUPPORT CHARIOT REF F27

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF FM25002" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-fm25002-tmgqp", name: "TROUSSE REF FM25002", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/YcM0d4gH-1783607260.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/YcM0d4gH-1783607260.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+FM25002", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/YcM0d4gH-1783607260.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF FM25002", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF FM25002

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC A DOS REF FM25006" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/sac-a-dos-ref-fm25006-gdj8v", name: "SAC A DOS REF FM25006", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/Cn6U4Cxm-1783607233.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/Cn6U4Cxm-1783607233.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SAC A DOS", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SAC+A+DOS+REF+FM25006", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/Cn6U4Cxm-1783607233.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC A DOS REF FM25006", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SAC A DOS REF FM25006

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC DE GOUTER REF FM25007" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/sac-de-gouter-ref-fm25007-i89fc", name: "SAC DE GOUTER REF FM25007", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/uA5kPsg5-1783607461.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/uA5kPsg5-1783607461.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SAC DE GOUTE", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SAC+DE+GOUTER+REF+FM25007", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/uA5kPsg5-1783607461.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC DE GOUTER REF FM25007", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SAC DE GOUTER REF FM25007

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC DE GOUTER REF FM25008" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/sac-de-gouter-ref-fm25008-xrekc", name: "SAC DE GOUTER REF FM25008", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/p9VfWBjO-1783607465.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/p9VfWBjO-1783607465.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SAC DE GOUTE", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SAC+DE+GOUTER+REF+FM25008", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/p9VfWBjO-1783607465.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC DE GOUTER REF FM25008", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SAC DE GOUTER REF FM25008

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC DE GOUTER REF FM25009" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/sac-de-gouter-ref-fm25009-sq3c8", name: "SAC DE GOUTER REF FM25009", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/DRbMTJbm-1783607469.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/DRbMTJbm-1783607469.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SAC DE GOUTE", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SAC+DE+GOUTER+REF+FM25009", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/DRbMTJbm-1783607469.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC DE GOUTER REF FM25009", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SAC DE GOUTER REF FM25009

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF FM25012" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-fm25012-jxw1n", name: "TROUSSE REF FM25012", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/1pr9CLyS-1783607319.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/1pr9CLyS-1783607319.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+FM25012", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/1pr9CLyS-1783607319.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF FM25012", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF FM25012

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF FM25016" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-fm25016-7igds", name: "TROUSSE REF FM25016", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/9QR1YzVt-1783607275.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/9QR1YzVt-1783607275.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+FM25016", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/9QR1YzVt-1783607275.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF FM25016", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF FM25016

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF H" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-h-2jdp0", name: "TROUSSE REF H", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/c2sAsqmP-1783607300.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/c2sAsqmP-1783607300.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+H", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/c2sAsqmP-1783607300.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF H", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF H

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC A DOS REF BS01-14" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/sac-a-dos-ref-bs01-14-gop4m", name: "SAC A DOS REF BS01-14", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/AFxTrRcd-1783607475.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/AFxTrRcd-1783607475.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SAC A DOS", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SAC+A+DOS+REF+BS01-14", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/AFxTrRcd-1783607475.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC A DOS REF BS01-14", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SAC A DOS REF BS01-14

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TABLEAU REF 90\/120" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/tableau-ref-90120-r6chu", name: "TABLEAU REF 90\/120", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/Bcqx9uXG-1783607965.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/Bcqx9uXG-1783607965.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "TABLEAUX", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TABLEAU+REF+90%2F120", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/Bcqx9uXG-1783607965.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TABLEAU REF 90\/120", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TABLEAU REF 90/120

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF 599" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-599-jmx1z", name: "TROUSSE REF 599", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/vZ2Dp2OV-1783607394.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/vZ2Dp2OV-1783607394.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+599", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/vZ2Dp2OV-1783607394.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF 599", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF 599

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TABLEAU REF 60\/90" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/tableau-ref-6090-mwrzb", name: "TABLEAU REF 60\/90", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/S3sDkB5h-1783607964.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/S3sDkB5h-1783607964.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "TABLEAUX", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TABLEAU+REF+60%2F90", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/S3sDkB5h-1783607964.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TABLEAU REF 60\/90", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TABLEAU REF 60/90

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF 3005" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-3005-ciodb", name: "TROUSSE REF 3005", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/2C7SnJaz-1783607418.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/2C7SnJaz-1783607418.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+3005", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/2C7SnJaz-1783607418.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF 3005", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF 3005

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC A DOS REF 32003" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/sac-a-dos-ref-32003-pgzqb", name: "SAC A DOS REF 32003", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/6mx8b4VT-1783607256.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/6mx8b4VT-1783607256.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SAC A DOS", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SAC+A+DOS+REF+32003", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/6mx8b4VT-1783607256.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC A DOS REF 32003", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SAC A DOS REF 32003

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC A DOS REF 1814" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/sac-a-dos-ref-1814-xzhx6", name: "SAC A DOS REF 1814", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/zl3wXETv-1783607231.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/zl3wXETv-1783607231.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SAC A DOS", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SAC+A+DOS+REF+1814", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/zl3wXETv-1783607231.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC A DOS REF 1814", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SAC A DOS REF 1814

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "Sac de gouter ref 184" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/sac-de-gouter-ref-184-wlxcg", name: "Sac de gouter ref 184", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/j9fiAEwA-1783607237.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/j9fiAEwA-1783607237.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SAC DE GOUTE", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Sac+de+gouter+ref+184", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/j9fiAEwA-1783607237.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "Sac de gouter ref 184", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

Sac de gouter ref 184

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC DE GOUTER REF 192" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/sac-de-gouter-ref-192-yrvwz", name: "SAC DE GOUTER REF 192", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/UPLIupkf-1783607242.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/UPLIupkf-1783607242.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SAC DE GOUTE", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SAC+DE+GOUTER+REF+192", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/UPLIupkf-1783607242.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC DE GOUTER REF 192", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SAC DE GOUTER REF 192

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC DE GOUTER REF 193" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/sac-de-gouter-ref-193-hauwk", name: "SAC DE GOUTER REF 193", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/8YtWSGU1-1783607251.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/8YtWSGU1-1783607251.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SAC DE GOUTE", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SAC+DE+GOUTER+REF+193", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/8YtWSGU1-1783607251.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC DE GOUTER REF 193", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SAC DE GOUTER REF 193

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF 3001" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-3001-iuyoe", name: "TROUSSE REF 3001", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/sscqytnx-1783607321.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/sscqytnx-1783607321.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+3001", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/sscqytnx-1783607321.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF 3001", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF 3001

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF 3002" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-3002-rpsop", name: "TROUSSE REF 3002", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/HbpQUMyK-1783607325.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/HbpQUMyK-1783607325.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+3002", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/HbpQUMyK-1783607325.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF 3002", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF 3002

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC A DOS REF 102" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/sac-a-dos-ref-102-upiww", name: "SAC A DOS REF 102", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/cuPhagmv-1783607459.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/cuPhagmv-1783607459.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SAC A DOS", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SAC+A+DOS+REF+102", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/cuPhagmv-1783607459.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC A DOS REF 102", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SAC A DOS REF 102

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF 104-8.5" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-104-85-3rw8u", name: "TROUSSE REF 104-8.5", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/DQkaTB5j-1783607956.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/DQkaTB5j-1783607956.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+104-8.5", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/DQkaTB5j-1783607956.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF 104-8.5", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF 104-8.5

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SERVIETTE REF 106" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/serviette-ref-106-u9ela", name: "SERVIETTE REF 106", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/0abJj0Jl-1783607460.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/0abJj0Jl-1783607460.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SERVIETTE", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SERVIETTE+REF+106", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/0abJj0Jl-1783607460.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SERVIETTE REF 106", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SERVIETTE REF 106

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF 107-8.5" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/trousse-ref-107-85-y7gbu", name: "TROUSSE REF 107-8.5", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/zrYCnATV-1783607957.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/zrYCnATV-1783607957.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "Trousse", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+TROUSSE+REF+107-8.5", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/zrYCnATV-1783607957.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "TROUSSE REF 107-8.5", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

TROUSSE REF 107-8.5

Aucun avis
0 && this.currentStock <= 5; }, get shouldForceQuote() { return this.isQuoteMode || (this.isService && this.currentPrice <= 0); }, get displaySku() { return (this.selectedVariant && this.selectedVariant.sku) ? this.selectedVariant.sku : null; }, get activeVariantLabel() { if (!this.selectedVariant) return ''; return this.selectedVariant.label || this.selectedVariant.name || ''; }, init() { if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); this.inWishlist = wl.includes(this.id); } window.addEventListener('wishlist-updated', (e) => { if (e.detail.product_id === this.id) { this.inWishlist = e.detail.added; } }); }, get currentPrice() { let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice; return p > 0 ? p : this.basePrice; }, formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); }, handleCardNavigation(event) { if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); if (typeof window.smartTrack === 'function') { window.smartTrack(this.isService ? 'service_click' : 'product_click', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC A DOS REF 1628" }); } this.openQuickView(); }, openQuickView() { const activeGallery = this.galleryImages && this.galleryImages.length ? this.galleryImages : [this.activeImage].filter(Boolean); const mappedVariants = (this.variants || []).map(v => ({ ...v, price_formatted: this.formatPrice(v.price || 0) })); window.dispatchEvent(new CustomEvent('open-product-quickview', { detail: { id: this.id, url: "https:\/\/creationhappy.smartbs.tn\/catalogue\/produit\/sac-a-dos-ref-1628-9rr5k", name: "SAC A DOS REF 1628", summary: "", type: this.isService ? 'service' : 'product', is_service: this.isService, is_quote_mode: this.isQuoteMode, should_force_quote: this.shouldForceQuote, manage_stock: this.productManageStock, allow_backorder: this.allowBackorder, stock: this.currentStock, sku: this.displaySku, unit: "pi\u00e8ce", currency: "TND", image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/hfBEvLwk-1783607474.webp", active_image: this.activeImage || "https:\/\/creationhappy.smartbs.tn\/storage\/products\/hfBEvLwk-1783607474.webp", gallery: activeGallery, price: this.currentPrice, price_formatted: this.formatPrice(this.currentPrice), compare_price_formatted: "0,000", seller: null, category: "SAC A DOS", wa_link: "https:\/\/wa.me\/33123456789?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+SAC+A+DOS+REF+1628", booking_enabled: false, variants: mappedVariants, selected_variant: this.selectedVariant ? { ...this.selectedVariant, price_formatted: this.formatPrice(this.selectedVariant.price || 0) } : null } })); }, selectVariant(v) { if (this.selectedVariant && this.selectedVariant.id === v.id) { this.selectedVariant = null; this.activeImage = "https:\/\/creationhappy.smartbs.tn\/storage\/products\/hfBEvLwk-1783607474.webp"; } else { this.selectedVariant = v; if(v.image) this.activeImage = v.image; } }, selectGalleryImage(img, idx) { this.selectedVariant = null; this.activeImage = img; this.galleryIndex = idx; }, stepGallery(direction) { if (!this.galleryImages.length) return; this.selectedVariant = null; this.galleryIndex = (this.galleryIndex + direction + this.galleryImages.length) % this.galleryImages.length; this.activeImage = this.galleryImages[this.galleryIndex]; }, openQuantityPopup() { if (this.variants.length > 0 && !this.selectedVariant) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.choose_option, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#f59e0b', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.choose_option); } return; } if (this.purchaseBlocked && !this.isQuoteMode) { if (typeof Toastify !== 'undefined') { Toastify({ text: this.trans.out_of_stock, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#ef4444', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(this.trans.out_of_stock); } return; } this.qty = 1; this.openQty = true; }, toggleWishlist() { this.inWishlist = !this.inWishlist; if (!this.isAuth) { let storageKey = 'smartbs_wishlist_' + this.tenantId; let wl = JSON.parse(localStorage.getItem(storageKey) || '[]'); if (this.inWishlist) { if (!wl.includes(this.id)) wl.push(this.id); } else { wl = wl.filter(id => id !== this.id); } localStorage.setItem(storageKey, JSON.stringify(wl)); window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { count: wl.length, product_id: this.id, added: this.inWishlist } })); } else { const url = 'https://creationhappy.smartbs.tn/wishlist/toggle'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, 'Accept': 'application/json' }, body: JSON.stringify({ product_id: this.id }) }).then(res => res.json()) .then(data => { window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: { added: this.inWishlist, product_id: this.id } })); }) .catch(err => { this.inWishlist = !this.inWishlist; }); } if (typeof Toastify !== 'undefined') { Toastify({ text: this.inWishlist ? this.trans.added_fav : this.trans.removed_fav, duration: 2000, gravity: 'bottom', position: 'center', style: { background: this.inWishlist ? '#f43f5e' : '#64748b', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } }, addToCart() { this.openQty = false; let variantId = this.selectedVariant ? this.selectedVariant.id : null; let variantSku = this.selectedVariant ? this.selectedVariant.sku : null; let variantName = this.selectedVariant ? this.selectedVariant.name : null; let payload = { quantity: this.qty, variant_id: variantId, variant_sku: variantSku, variant_name: variantName }; const addUrl = 'https://creationhappy.smartbs.tn/panier/ajouter/' + this.id; const csrfToken = document.querySelector('meta[name=\'csrf-token\']')?.content; fetch(addUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' }, body: JSON.stringify(payload) }).then(res => res.json()).then(data => { const count = data.cart_count ?? data.count ?? '+1'; const total = data.cart_total_formatted ?? data.total_formatted ?? null; document.querySelectorAll('.cart-count-badge').forEach(el => el.innerText = count); if (total) document.querySelectorAll('.cart-total-price').forEach(el => el.innerText = total); window.dispatchEvent(new Event('cart-updated')); if (typeof window.smartTrack === 'function') { window.smartTrack('add_to_cart', { entity_type: this.isService ? 'service' : 'product', item_id: this.id, item_name: "SAC A DOS REF 1628", quantity: this.qty }); } let successMsg = ''; if(this.isQuoteMode) { successMsg = variantName ? this.trans.opt_add_quote.replace(':name', variantName) : this.trans.prod_add_quote; } else { successMsg = variantName ? this.trans.opt_add.replace(':name', variantName) : this.trans.prod_add; } if (typeof Toastify !== 'undefined') { Toastify({ text: '✅ ' + successMsg, duration: 2500, gravity: 'bottom', position: 'center', style: { background: '#10b981', color: '#fff', borderRadius: '10px', fontWeight: 'bold', marginBottom: '80px' } }).showToast(); } else { alert(successMsg + ' !'); } }).catch(error => { console.error('Erreur:', error); }); } }" @mouseenter="isHovered = true" @mouseleave="isHovered = false" class="group relative bg-white rounded-[2rem] p-3 md:p-4 border border-slate-100 hover:border-slate-200 transition-all duration-500 hover:shadow-2xl hover:shadow-slate-200/50 flex flex-col h-full" style="--primary-color: #e4ac07; --secondary-color: #0f172a;">
En Rupture

Vite, plus que

SAC A DOS REF 1628

Aucun avis

Aucun résultat trouvé

Nous ne trouvons aucun article correspondant à vos critères actuels.

Chargement...

Sur devis

Reference

Stock