Boutique Officielle Certifiée
Kammoura print
Kammoura print
Sfax
13 Références
4.9 Score de Confiance
À Propos de Nous
Navigation Rayons
Collection Exclusive
Découvrez notre sélection rigoureuse de produits.
Trier par :
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 : "PRD-MWHHLDF6";
},
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: "Pack \u00e9tiquettes scolaires"
});
}
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:\/\/tamssmall.tn\/catalogue\/produit\/pack-etiquettes-scolaires-6a4e236da0da8",
name: "Pack \u00e9tiquettes scolaires",
summary: "Fini les affaires perdues ou m\u00e9lang\u00e9es ! Pack \u00e9tiquettes scolaires \u00e0 15 DT",
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:\/\/tamssmall.tn\/storage\/products\/cEBBfUgV-1783505773.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/cEBBfUgV-1783505773.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kammoura print","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kammoura-print-XSfv","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/I6YPJzN70rZUdcV4o9F2xgTOfoxPRB3qVZN8Gp5g.jpg"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21653522750?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Pack+%C3%A9tiquettes+scolaires",
booking_enabled: true,
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:\/\/tamssmall.tn\/storage\/products\/cEBBfUgV-1783505773.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://tamssmall.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://tamssmall.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: "Pack \u00e9tiquettes scolaires",
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: #095155; --secondary-color: #ff429a;">
Vite, plus que
Aucun avis
En Rupture
Pack étiquettes scolaires
Sur Devis
0,000
TND
/ pièce
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 : "PRD-ET6DWVVQ";
},
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: "100 cartes visite recto"
});
}
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:\/\/tamssmall.tn\/catalogue\/produit\/100-cartes-visite-recto-6a4e080885eb2",
name: "100 cartes visite recto",
summary: "100 cartes de visite (recto) = 25 DT",
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:\/\/tamssmall.tn\/storage\/products\/ojjGBrGc-1783498760.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/ojjGBrGc-1783498760.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kammoura print","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kammoura-print-XSfv","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/I6YPJzN70rZUdcV4o9F2xgTOfoxPRB3qVZN8Gp5g.jpg"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21653522750?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+100+cartes+visite+recto",
booking_enabled: true,
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:\/\/tamssmall.tn\/storage\/products\/ojjGBrGc-1783498760.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://tamssmall.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://tamssmall.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: "100 cartes visite recto",
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: #095155; --secondary-color: #ff429a;">
Vite, plus que
Aucun avis
En Rupture
100 cartes visite recto
Sur Devis
0,000
TND
/ pièce
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 : "PRD-XDYQURUI";
},
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: "100 \u00e9tiquettes rondes"
});
}
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:\/\/tamssmall.tn\/catalogue\/produit\/100-etiquettes-rondes-6a4cf83c92b38",
name: "100 \u00e9tiquettes rondes",
summary: "100 \u00e9tiquettes rondes (diam\u00e8tre 4 cm)",
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:\/\/tamssmall.tn\/storage\/products\/VtzLeVZU-1785224942.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/VtzLeVZU-1785224942.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kammoura print","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kammoura-print-XSfv","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/I6YPJzN70rZUdcV4o9F2xgTOfoxPRB3qVZN8Gp5g.jpg"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21653522750?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+100+%C3%A9tiquettes+rondes",
booking_enabled: true,
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:\/\/tamssmall.tn\/storage\/products\/VtzLeVZU-1785224942.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://tamssmall.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://tamssmall.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: "100 \u00e9tiquettes rondes",
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: #095155; --secondary-color: #ff429a;">
Vite, plus que
Aucun avis
En Rupture
100 étiquettes rondes
Sur Devis
0,000
TND
/ pièce
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 : "PRD-QHLK0B7E";
},
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: "100 cartes d'invitation"
});
}
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:\/\/tamssmall.tn\/catalogue\/produit\/100-cartes-dinvitation-6a4cf72f5701c",
name: "100 cartes d'invitation",
summary: "Offre sp\u00e9ciale !",
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:\/\/tamssmall.tn\/storage\/products\/ABRfcqpz-1785226530.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/ABRfcqpz-1785226530.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kammoura print","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kammoura-print-XSfv","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/I6YPJzN70rZUdcV4o9F2xgTOfoxPRB3qVZN8Gp5g.jpg"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21653522750?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+100+cartes+d%27invitation",
booking_enabled: true,
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:\/\/tamssmall.tn\/storage\/products\/ABRfcqpz-1785226530.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://tamssmall.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://tamssmall.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: "100 cartes d'invitation",
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: #095155; --secondary-color: #ff429a;">
Vite, plus que
Aucun avis
En Rupture
100 cartes d'invitation
Sur Devis
0,000
TND
/ pièce
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 : "PROD-C9349";
},
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: "Pull en coton \u00e0 personnalise"
});
}
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:\/\/tamssmall.tn\/catalogue\/produit\/pull-en-100-coton-personnalise-ayuag",
name: "Pull en coton \u00e0 personnalise",
summary: "Pull en 100% coton \u00e0 personnalise",
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:\/\/tamssmall.tn\/storage\/products\/Ny3EYIl1-1776332204.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/Ny3EYIl1-1776332204.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kammoura print","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kammoura-print-XSfv","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/I6YPJzN70rZUdcV4o9F2xgTOfoxPRB3qVZN8Gp5g.jpg"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21653522750?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Pull+en++coton+%C3%A0+personnalise",
booking_enabled: true,
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:\/\/tamssmall.tn\/storage\/products\/Ny3EYIl1-1776332204.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://tamssmall.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://tamssmall.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: "Pull en coton \u00e0 personnalise",
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: #095155; --secondary-color: #ff429a;">
Vite, plus que
Aucun avis
En Rupture
Pull en coton à personnalise
Sur Devis
0,000
TND
/ pièce
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 : "SKU-84MDNF";
},
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: "Bourse \u00e0 personnaliser"
});
}
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:\/\/tamssmall.tn\/catalogue\/produit\/bourse-personnalise-pour-vos-evenements-hohiv",
name: "Bourse \u00e0 personnaliser",
summary: "Bourse \u00e0 personnaliser",
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:\/\/tamssmall.tn\/storage\/products\/ERj8leGP-1776332203.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/ERj8leGP-1776332203.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kammoura print","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kammoura-print-XSfv","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/I6YPJzN70rZUdcV4o9F2xgTOfoxPRB3qVZN8Gp5g.jpg"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21653522750?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Bourse+%C3%A0+personnaliser",
booking_enabled: true,
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:\/\/tamssmall.tn\/storage\/products\/ERj8leGP-1776332203.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://tamssmall.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://tamssmall.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: "Bourse \u00e0 personnaliser",
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: #095155; --secondary-color: #ff429a;">
Vite, plus que
Aucun avis
En Rupture
Bourse à personnaliser
Sur Devis
0,000
TND
/ pièce
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 : "SKU-RK74XP";
},
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: "Porte cl\u00e9s personnalis\u00e9"
});
}
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:\/\/tamssmall.tn\/catalogue\/produit\/porte-cles-personnalise-69ba8933717a3",
name: "Porte cl\u00e9s personnalis\u00e9",
summary: "Porte cl\u00e9s en aluminium recto verso, peut \u00eatre imprim\u00e9 des deux faces",
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:\/\/tamssmall.tn\/storage\/products\/vFczj2Yr-1776332203.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/vFczj2Yr-1776332203.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kammoura print","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kammoura-print-XSfv","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/I6YPJzN70rZUdcV4o9F2xgTOfoxPRB3qVZN8Gp5g.jpg"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21653522750?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Porte+cl%C3%A9s+personnalis%C3%A9",
booking_enabled: true,
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:\/\/tamssmall.tn\/storage\/products\/vFczj2Yr-1776332203.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://tamssmall.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://tamssmall.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: "Porte cl\u00e9s personnalis\u00e9",
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: #095155; --secondary-color: #ff429a;">
Vite, plus que
Aucun avis
En Rupture
Porte clés personnalisé
Sur Devis
0,000
TND
/ pièce
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 : "SKU-63G9E6";
},
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: "Mug magique"
});
}
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:\/\/tamssmall.tn\/catalogue\/produit\/mug-magique-69ba816fc26e1",
name: "Mug magique",
summary: "mug magique sur lequel vous pouvez choisir d'imprimer le design que vous voulez",
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:\/\/tamssmall.tn\/storage\/products\/IYjefEIO-1776332203.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/IYjefEIO-1776332203.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kammoura print","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kammoura-print-XSfv","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/I6YPJzN70rZUdcV4o9F2xgTOfoxPRB3qVZN8Gp5g.jpg"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21653522750?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Mug+magique",
booking_enabled: true,
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:\/\/tamssmall.tn\/storage\/products\/IYjefEIO-1776332203.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://tamssmall.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://tamssmall.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: "Mug magique",
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: #095155; --secondary-color: #ff429a;">
Vite, plus que
Aucun avis
En Rupture
Mug magique
Sur Devis
0,000
TND
/ pièce
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 : "SKU-3DFQ5K";
},
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: "Tote Bag personnalis\u00e9"
});
}
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:\/\/tamssmall.tn\/catalogue\/produit\/tote-bag-personnalise-69ba7e6c6009e",
name: "Tote Bag personnalis\u00e9",
summary: "Tote bag \u00e0 personnaliser",
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:\/\/tamssmall.tn\/storage\/products\/eaQWMigu-1776332203.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/eaQWMigu-1776332203.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kammoura print","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kammoura-print-XSfv","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/I6YPJzN70rZUdcV4o9F2xgTOfoxPRB3qVZN8Gp5g.jpg"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21653522750?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Tote+Bag+personnalis%C3%A9",
booking_enabled: true,
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:\/\/tamssmall.tn\/storage\/products\/eaQWMigu-1776332203.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://tamssmall.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://tamssmall.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: "Tote Bag personnalis\u00e9",
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: #095155; --secondary-color: #ff429a;">
Vite, plus que
Aucun avis
En Rupture
Tote Bag personnalisé
Sur Devis
0,000
TND
/ pièce
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 : "SKU-CZOJA1";
},
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: "Coussin personnalis\u00e9"
});
}
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:\/\/tamssmall.tn\/catalogue\/produit\/coussin-personnalise-69ba7caada9f9",
name: "Coussin personnalis\u00e9",
summary: "Coussin personnalis\u00e9 en satin",
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:\/\/tamssmall.tn\/storage\/products\/BqPBeXZY-1776332203.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/BqPBeXZY-1776332203.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kammoura print","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kammoura-print-XSfv","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/I6YPJzN70rZUdcV4o9F2xgTOfoxPRB3qVZN8Gp5g.jpg"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21653522750?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Coussin+personnalis%C3%A9",
booking_enabled: true,
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:\/\/tamssmall.tn\/storage\/products\/BqPBeXZY-1776332203.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://tamssmall.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://tamssmall.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: "Coussin personnalis\u00e9",
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: #095155; --secondary-color: #ff429a;">
Vite, plus que
Aucun avis
En Rupture
Coussin personnalisé
Sur Devis
0,000
TND
/ pièce
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 : "SKU-SAJNVUAT";
},
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: "Sweat \u00e0 Capuche (Hoodie) Personnalis\u00e9 \u2013 Confort & Style"
});
}
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:\/\/tamssmall.tn\/catalogue\/produit\/sweat-a-capuche-hoodie-personnalise-confort-style-mb1j5",
name: "Sweat \u00e0 Capuche (Hoodie) Personnalis\u00e9 \u2013 Confort & Style",
summary: "Affirmez votre style avec notre sweat \u00e0 capuche premium, enti\u00e8rement personnalisable ! Un basique indispensable, doux et chaud, disponible en 4 coloris intemporels. Que ce soit pour un logo, une citation ou une illustrat...",
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:\/\/tamssmall.tn\/storage\/products\/qP5kA5fO-1776332200.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/qP5kA5fO-1776332200.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kammoura print","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kammoura-print-XSfv","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/I6YPJzN70rZUdcV4o9F2xgTOfoxPRB3qVZN8Gp5g.jpg"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21653522750?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Sweat+%C3%A0+Capuche+%28Hoodie%29+Personnalis%C3%A9+%E2%80%93+Confort+%26+Style",
booking_enabled: true,
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:\/\/tamssmall.tn\/storage\/products\/qP5kA5fO-1776332200.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://tamssmall.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://tamssmall.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: "Sweat \u00e0 Capuche (Hoodie) Personnalis\u00e9 \u2013 Confort & Style",
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: #095155; --secondary-color: #ff429a;">
Vite, plus que
Aucun avis
En Rupture
Sweat à Capuche (Hoodie) Personnalisé – Confort & Style
Sur Devis
0,000
TND
/ pièce
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 : "SKU-OEENF3ZX";
},
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: "Mug Personnalis\u00e9 Double Face \u2013 Design Sur Mesure"
});
}
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:\/\/tamssmall.tn\/catalogue\/produit\/mug-personnalise-double-face-design-sur-mesure",
name: "Mug Personnalis\u00e9 Double Face \u2013 Design Sur Mesure",
summary: "Transformez vos pauses caf\u00e9 avec un mug unique ! Personnalisez les deux faces (Recto\/Verso) avec vos photos, logos ou messages pr\u00e9f\u00e9r\u00e9s. Qualit\u00e9 d'impression haute d\u00e9finition par Kammoura Print, r\u00e9sistante au lave-vaisse...",
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:\/\/tamssmall.tn\/storage\/products\/IiEXc4vV-1776332200.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/IiEXc4vV-1776332200.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kammoura print","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kammoura-print-XSfv","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/I6YPJzN70rZUdcV4o9F2xgTOfoxPRB3qVZN8Gp5g.jpg"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21653522750?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Mug+Personnalis%C3%A9+Double+Face+%E2%80%93+Design+Sur+Mesure",
booking_enabled: true,
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:\/\/tamssmall.tn\/storage\/products\/IiEXc4vV-1776332200.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://tamssmall.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://tamssmall.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: "Mug Personnalis\u00e9 Double Face \u2013 Design Sur Mesure",
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: #095155; --secondary-color: #ff429a;">
Vite, plus que
Aucun avis
En Rupture
Mug Personnalisé Double Face – Design Sur Mesure
Sur Devis
0,000
TND
/ pièce
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 : "VND-NEUNPKXP";
},
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: "Porte-cl\u00e9s Illustr\u00e9s \"Petits Mondes\" \u2013 Collection Enfantine"
});
}
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:\/\/tamssmall.tn\/catalogue\/produit\/porte-cles-illustres-petits-mondes-collection-enfantine-twtXdy",
name: "Porte-cl\u00e9s Illustr\u00e9s \"Petits Mondes\" \u2013 Collection Enfantine",
summary: "Ajoutez une touche de po\u00e9sie \u00e0 votre quotidien avec notre collection de porte-cl\u00e9s illustr\u00e9s. Pr\u00e9sentant des personnages attachants dans des d\u00e9cors color\u00e9s et printaniers, ces accessoires sont parfaits pour personnaliser...",
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:\/\/tamssmall.tn\/storage\/products\/sMnf8Sqe-1776332195.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/sMnf8Sqe-1776332195.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "13,000",
seller: {"name":"Kammoura print","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kammoura-print-XSfv","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/I6YPJzN70rZUdcV4o9F2xgTOfoxPRB3qVZN8Gp5g.jpg"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21653522750?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Porte-cl%C3%A9s+Illustr%C3%A9s+%22Petits+Mondes%22+%E2%80%93+Collection+Enfantine",
booking_enabled: true,
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:\/\/tamssmall.tn\/storage\/products\/sMnf8Sqe-1776332195.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://tamssmall.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://tamssmall.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: "Porte-cl\u00e9s Illustr\u00e9s \"Petits Mondes\" \u2013 Collection Enfantine",
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: #095155; --secondary-color: #ff429a;">
Vite, plus que
Aucun avis
En Rupture
-10%
Porte-clés Illustrés "Petits Mondes" – Collection Enfantine
Sur Devis
13,000
TND
/ pièce
FR
EN
AR