Boutique Officielle Certifiée
Kahina Art-deco
Kahina Art-deco
Ariana
10 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-TKML4S32";
},
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 en perles"
});
}
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-en-perles-6a19a0562c1ba",
name: "Porte cl\u00e9s en perles",
summary: "Porte cl\u00e9s en perles forme c\u0153ur",
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\/2PIFqBKy26evWBicN4CK93Etx3Xy0WJiqIMG2Ziu.png",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/2PIFqBKy26evWBicN4CK93Etx3Xy0WJiqIMG2Ziu.png",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kahina Art-deco","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kahina-art-deco","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/qwyk7YJ3RXAscnTP7a0x7oytZu46Xovie9r4R3pY.png"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21600000?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Porte+cl%C3%A9s+en+perles",
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\/2PIFqBKy26evWBicN4CK93Etx3Xy0WJiqIMG2Ziu.png";
} 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 en perles",
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 en perles
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-GOME0RGP";
},
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"
});
}
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-6a19986498b43",
name: "Porte cl\u00e9s",
summary: "Porte cl\u00e9s en perles",
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\/dntoJ2z8w97Hi4AOBF6L4nMTuCMyF5FnDJabaqwe.png",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/dntoJ2z8w97Hi4AOBF6L4nMTuCMyF5FnDJabaqwe.png",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kahina Art-deco","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kahina-art-deco","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/qwyk7YJ3RXAscnTP7a0x7oytZu46Xovie9r4R3pY.png"},
category: "Artisanat et fait main",
wa_link: "https:\/\/wa.me\/21600000?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Porte+cl%C3%A9s",
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\/dntoJ2z8w97Hi4AOBF6L4nMTuCMyF5FnDJabaqwe.png";
} 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",
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
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-FXYD45ZI";
},
get activeVariantLabel() {
if (!this.selectedVariant) return '';
return this.selectedVariant.label || this.selectedVariant.name || '';
},
init() {
if (!this.isAuth) {
let storageKey = 'smartbs_wishlist_' + this.tenantId;
let wl = JSON.parse(localStorage.getItem(storageKey) || '[]');
this.inWishlist = wl.includes(this.id);
}
window.addEventListener('wishlist-updated', (e) => {
if (e.detail.product_id === this.id) {
this.inWishlist = e.detail.added;
}
});
},
get currentPrice() {
let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice;
return p > 0 ? p : this.basePrice;
},
formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); },
handleCardNavigation(event) {
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
event.preventDefault();
if (typeof window.smartTrack === 'function') {
window.smartTrack(this.isService ? 'service_click' : 'product_click', {
entity_type: this.isService ? 'service' : 'product',
item_id: this.id,
item_name: "Tableau Chat Fleuri Brod\u00e9 \u00e0 la Main"
});
}
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\/tableau-chat-fleuri-brode-a-la-main-6a157c61e9ff4",
name: "Tableau Chat Fleuri Brod\u00e9 \u00e0 la Main",
summary: "Une cr\u00e9ation d\u00e9licate et pleine de douceur pour les amoureux des chats et de l\u2019artisanat \u2728\r\nCe tableau en broderie artisanale repr\u00e9sente la silhouette \u00e9l\u00e9gante d\u2019un chat d\u00e9cor\u00e9e de jolies fleurs color\u00e9es, enti\u00e8rement r\u00e9...",
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\/mR11f33H-1785312488.webp",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/mR11f33H-1785312488.webp",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kahina Art-deco","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kahina-art-deco","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/qwyk7YJ3RXAscnTP7a0x7oytZu46Xovie9r4R3pY.png"},
category: "Artisanat et fait main",
wa_link: "https:\/\/wa.me\/21600000?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Tableau+Chat+Fleuri+Brod%C3%A9+%C3%A0+la+Main",
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\/mR11f33H-1785312488.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: "Tableau Chat Fleuri Brod\u00e9 \u00e0 la Main",
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
Tableau Chat Fleuri Brodé à la Main
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-ASMMDMPX";
},
get activeVariantLabel() {
if (!this.selectedVariant) return '';
return this.selectedVariant.label || this.selectedVariant.name || '';
},
init() {
if (!this.isAuth) {
let storageKey = 'smartbs_wishlist_' + this.tenantId;
let wl = JSON.parse(localStorage.getItem(storageKey) || '[]');
this.inWishlist = wl.includes(this.id);
}
window.addEventListener('wishlist-updated', (e) => {
if (e.detail.product_id === this.id) {
this.inWishlist = e.detail.added;
}
});
},
get currentPrice() {
let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice;
return p > 0 ? p : this.basePrice;
},
formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); },
handleCardNavigation(event) {
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
event.preventDefault();
if (typeof window.smartTrack === 'function') {
window.smartTrack(this.isService ? 'service_click' : 'product_click', {
entity_type: this.isService ? 'service' : 'product',
item_id: this.id,
item_name: "Tableau Ancre Marine Brod\u00e9 \u00e0 la Main"
});
}
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\/tableau-ancre-marine-brode-a-la-main-6a156bc2d8dfd",
name: "Tableau Ancre Marine Brod\u00e9 \u00e0 la Main",
summary: "Apportez une ambiance marine chic et authentique \u00e0 votre d\u00e9coration",
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\/d8xVlHNSnzTbPtq9w9u0I5oDsxnpncgJKTQWj1iv.png",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/d8xVlHNSnzTbPtq9w9u0I5oDsxnpncgJKTQWj1iv.png",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kahina Art-deco","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kahina-art-deco","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/qwyk7YJ3RXAscnTP7a0x7oytZu46Xovie9r4R3pY.png"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21600000?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Tableau+Ancre+Marine+Brod%C3%A9+%C3%A0+la+Main",
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\/d8xVlHNSnzTbPtq9w9u0I5oDsxnpncgJKTQWj1iv.png";
} 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: "Tableau Ancre Marine Brod\u00e9 \u00e0 la Main",
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
Tableau Ancre Marine Brodé à la Main
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-D4XNZIPD";
},
get activeVariantLabel() {
if (!this.selectedVariant) return '';
return this.selectedVariant.label || this.selectedVariant.name || '';
},
init() {
if (!this.isAuth) {
let storageKey = 'smartbs_wishlist_' + this.tenantId;
let wl = JSON.parse(localStorage.getItem(storageKey) || '[]');
this.inWishlist = wl.includes(this.id);
}
window.addEventListener('wishlist-updated', (e) => {
if (e.detail.product_id === this.id) {
this.inWishlist = e.detail.added;
}
});
},
get currentPrice() {
let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice;
return p > 0 ? p : this.basePrice;
},
formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); },
handleCardNavigation(event) {
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
event.preventDefault();
if (typeof window.smartTrack === 'function') {
window.smartTrack(this.isService ? 'service_click' : 'product_click', {
entity_type: this.isService ? 'service' : 'product',
item_id: this.id,
item_name: "Tableau Palmier Brod\u00e9 \u00e0 la Main"
});
}
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\/tableau-palmier-brode-a-la-main-6a156952d5ec7",
name: "Tableau Palmier Brod\u00e9 \u00e0 la Main",
summary: "Une touche d\u2019\u00e9vasion et de douceur pour votre int\u00e9rieur",
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\/Wu1QITckSBSjbGPbxXEUsgmYgEJJMpNa8V4AKumG.png",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/Wu1QITckSBSjbGPbxXEUsgmYgEJJMpNa8V4AKumG.png",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kahina Art-deco","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kahina-art-deco","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/qwyk7YJ3RXAscnTP7a0x7oytZu46Xovie9r4R3pY.png"},
category: "Artisanat et fait main",
wa_link: "https:\/\/wa.me\/21600000?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Tableau+Palmier+Brod%C3%A9+%C3%A0+la+Main",
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\/Wu1QITckSBSjbGPbxXEUsgmYgEJJMpNa8V4AKumG.png";
} 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: "Tableau Palmier Brod\u00e9 \u00e0 la Main",
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
Tableau Palmier Brodé à la Main
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-6B3JVAHA";
},
get activeVariantLabel() {
if (!this.selectedVariant) return '';
return this.selectedVariant.label || this.selectedVariant.name || '';
},
init() {
if (!this.isAuth) {
let storageKey = 'smartbs_wishlist_' + this.tenantId;
let wl = JSON.parse(localStorage.getItem(storageKey) || '[]');
this.inWishlist = wl.includes(this.id);
}
window.addEventListener('wishlist-updated', (e) => {
if (e.detail.product_id === this.id) {
this.inWishlist = e.detail.added;
}
});
},
get currentPrice() {
let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice;
return p > 0 ? p : this.basePrice;
},
formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); },
handleCardNavigation(event) {
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
event.preventDefault();
if (typeof window.smartTrack === 'function') {
window.smartTrack(this.isService ? 'service_click' : 'product_click', {
entity_type: this.isService ? 'service' : 'product',
item_id: this.id,
item_name: "Tableau \u201cConnexion \u00c9ternelle\u201d \u2013 Brod\u00e9 \u00e0 la main"
});
}
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\/tableau-connexion-eternelle-brode-a-la-main-6a15645a16144",
name: "Tableau \u201cConnexion \u00c9ternelle\u201d \u2013 Brod\u00e9 \u00e0 la main",
summary: "Une cr\u00e9ation artistique raffin\u00e9e qui c\u00e9l\u00e8bre la beaut\u00e9 de la connexion humaine \u00e0 travers un design minimaliste et contemporain.",
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\/VraAUOKVPHycz4prtW6Pz3S2wdMjzMEhRIPzNA87.png",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/VraAUOKVPHycz4prtW6Pz3S2wdMjzMEhRIPzNA87.png",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kahina Art-deco","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kahina-art-deco","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/qwyk7YJ3RXAscnTP7a0x7oytZu46Xovie9r4R3pY.png"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21600000?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Tableau+%E2%80%9CConnexion+%C3%89ternelle%E2%80%9D+%E2%80%93+Brod%C3%A9+%C3%A0+la+main",
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\/VraAUOKVPHycz4prtW6Pz3S2wdMjzMEhRIPzNA87.png";
} 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: "Tableau \u201cConnexion \u00c9ternelle\u201d \u2013 Brod\u00e9 \u00e0 la main",
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
Tableau “Connexion Éternelle” – Brodé à la main
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-LICFMFSP";
},
get activeVariantLabel() {
if (!this.selectedVariant) return '';
return this.selectedVariant.label || this.selectedVariant.name || '';
},
init() {
if (!this.isAuth) {
let storageKey = 'smartbs_wishlist_' + this.tenantId;
let wl = JSON.parse(localStorage.getItem(storageKey) || '[]');
this.inWishlist = wl.includes(this.id);
}
window.addEventListener('wishlist-updated', (e) => {
if (e.detail.product_id === this.id) {
this.inWishlist = e.detail.added;
}
});
},
get currentPrice() {
let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice;
return p > 0 ? p : this.basePrice;
},
formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); },
handleCardNavigation(event) {
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
event.preventDefault();
if (typeof window.smartTrack === 'function') {
window.smartTrack(this.isService ? 'service_click' : 'product_click', {
entity_type: this.isService ? 'service' : 'product',
item_id: this.id,
item_name: "Tableau \u201cDualit\u00e9 Silencieuse\u201d brod\u00e9 \u00e0 la main"
});
}
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\/tableau-dualite-silencieuse-brode-a-la-main-6a156123e08fa",
name: "Tableau \u201cDualit\u00e9 Silencieuse\u201d brod\u00e9 \u00e0 la main",
summary: "Id\u00e9al pour : Salon, bureau, chambre ou galerie moderne",
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\/RbYcAVxHbJ0cl1MlI5s8Iiov7LIcQfu3bZklBvGn.jpg",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/RbYcAVxHbJ0cl1MlI5s8Iiov7LIcQfu3bZklBvGn.jpg",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kahina Art-deco","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kahina-art-deco","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/qwyk7YJ3RXAscnTP7a0x7oytZu46Xovie9r4R3pY.png"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21600000?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Tableau+%E2%80%9CDualit%C3%A9+Silencieuse%E2%80%9D+brod%C3%A9+%C3%A0+la+main",
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\/RbYcAVxHbJ0cl1MlI5s8Iiov7LIcQfu3bZklBvGn.jpg";
} 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: "Tableau \u201cDualit\u00e9 Silencieuse\u201d brod\u00e9 \u00e0 la main",
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
Tableau “Dualité Silencieuse” brodé à la main
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-8MMT3LUZ";
},
get activeVariantLabel() {
if (!this.selectedVariant) return '';
return this.selectedVariant.label || this.selectedVariant.name || '';
},
init() {
if (!this.isAuth) {
let storageKey = 'smartbs_wishlist_' + this.tenantId;
let wl = JSON.parse(localStorage.getItem(storageKey) || '[]');
this.inWishlist = wl.includes(this.id);
}
window.addEventListener('wishlist-updated', (e) => {
if (e.detail.product_id === this.id) {
this.inWishlist = e.detail.added;
}
});
},
get currentPrice() {
let p = this.selectedVariant ? parseFloat(this.selectedVariant.price) : this.basePrice;
return p > 0 ? p : this.basePrice;
},
formatPrice(p) { return Number(p).toLocaleString('fr-TN', { minimumFractionDigits: 3, maximumFractionDigits: 3, useGrouping: false }); },
handleCardNavigation(event) {
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
event.preventDefault();
if (typeof window.smartTrack === 'function') {
window.smartTrack(this.isService ? 'service_click' : 'product_click', {
entity_type: this.isService ? 'service' : 'product',
item_id: this.id,
item_name: "Tableau de chats brod\u00e9s \u00e0 la main avec des d\u00e9tails d\u00e9licats et une touche pleine de douceur"
});
}
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\/tableau-de-chats-brodes-a-la-main-avec-des-details-delicats-et-une-touche-pleine-de-douceur-6a146ad156357",
name: "Tableau de chats brod\u00e9s \u00e0 la main avec des d\u00e9tails d\u00e9licats et une touche pleine de douceur",
summary: "",
type: this.isService ? 'service' : 'product',
is_service: this.isService,
is_quote_mode: this.isQuoteMode,
should_force_quote: this.shouldForceQuote,
manage_stock: this.productManageStock,
allow_backorder: this.allowBackorder,
stock: this.currentStock,
sku: this.displaySku,
unit: "pi\u00e8ce",
currency: "TND",
image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/wUQv1q47s6dtc49lj36uGydjlHBNWJ6whP8qtVmT.jpg",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/wUQv1q47s6dtc49lj36uGydjlHBNWJ6whP8qtVmT.jpg",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kahina Art-deco","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kahina-art-deco","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/qwyk7YJ3RXAscnTP7a0x7oytZu46Xovie9r4R3pY.png"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21600000?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Tableau+de+chats+brod%C3%A9s+%C3%A0+la+main+avec+des+d%C3%A9tails+d%C3%A9licats+et+une+touche+pleine+de+douceur",
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\/wUQv1q47s6dtc49lj36uGydjlHBNWJ6whP8qtVmT.jpg";
} 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: "Tableau de chats brod\u00e9s \u00e0 la main avec des d\u00e9tails d\u00e9licats et une touche pleine de douceur",
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
Tableau de chats brodés à la main avec des détails délicats et une touche pleine de douceur
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-IBHNUFEM";
},
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: "Tournesols brod\u00e9s \u00e0 la main sur toile"
});
}
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\/tournesols-brodes-a-la-main-sur-toile-6a1469da9e420",
name: "Tournesols brod\u00e9s \u00e0 la main sur toile",
summary: "Une d\u00e9coration unique qui apporte une touche chaleureuse et \u00e9l\u00e9gante \u00e0 votre int\u00e9rieur.",
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\/i6W40wn8OwfumQHDPTio7rIu5tBETP8EWRXbDgzi.png",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/i6W40wn8OwfumQHDPTio7rIu5tBETP8EWRXbDgzi.png",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kahina Art-deco","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kahina-art-deco","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/qwyk7YJ3RXAscnTP7a0x7oytZu46Xovie9r4R3pY.png"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21600000?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Tournesols+brod%C3%A9s+%C3%A0+la+main+sur+toile",
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\/i6W40wn8OwfumQHDPTio7rIu5tBETP8EWRXbDgzi.png";
} 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: "Tournesols brod\u00e9s \u00e0 la main sur toile",
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
Tournesols brodés à la main sur toile
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-M3ZMCH8L";
},
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: "Mini tableau en broderie artisanale fait main"
});
}
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\/mini-tableau-en-broderie-artisanale-fait-main-6a146624be73c",
name: "Mini tableau en broderie artisanale fait main",
summary: "",
type: this.isService ? 'service' : 'product',
is_service: this.isService,
is_quote_mode: this.isQuoteMode,
should_force_quote: this.shouldForceQuote,
manage_stock: this.productManageStock,
allow_backorder: this.allowBackorder,
stock: this.currentStock,
sku: this.displaySku,
unit: "pi\u00e8ce",
currency: "TND",
image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/hxKcQxqNbKEwgOj2XOToYIfROs2X7PjAPSNPJY72.png",
active_image: this.activeImage || "https:\/\/tamssmall.tn\/storage\/products\/hxKcQxqNbKEwgOj2XOToYIfROs2X7PjAPSNPJY72.png",
gallery: activeGallery,
price: this.currentPrice,
price_formatted: this.formatPrice(this.currentPrice),
compare_price_formatted: "0,000",
seller: {"name":"Kahina Art-deco","url":"https:\/\/tamssmall.tn\/catalogue\/boutique\/kahina-art-deco","logo":"https:\/\/tamssmall.tn\/storage\/sellers\/logos\/qwyk7YJ3RXAscnTP7a0x7oytZu46Xovie9r4R3pY.png"},
category: "Cadeaux",
wa_link: "https:\/\/wa.me\/21600000?text=Bonjour%2C+je+suis+int%C3%A9ress%C3%A9+par+%3A+Mini+tableau+en+broderie+artisanale+fait+main",
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\/hxKcQxqNbKEwgOj2XOToYIfROs2X7PjAPSNPJY72.png";
} 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: "Mini tableau en broderie artisanale fait main",
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
Mini tableau en broderie artisanale fait main
Sur Devis
0,000
TND
/ pièce
FR
EN
AR