/** =========================================
* Wishlist Handler (Persistent Heart State)
* ========================================= */
(function () {
'use strict';
const STORAGE_KEY = 'odoo_wishlist_products';
/* -----------------------------
Helpers
----------------------------- */
function getStoredWishlist() {
try {
return JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
} catch (e) {
return [];
}
}
function storeWishlist(list) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(list));
}
function isInWishlist(productId) {
return getStoredWishlist().includes(productId);
}
function addToWishlist(productId) {
const list = getStoredWishlist();
if (!list.includes(productId)) {
list.push(productId);
storeWishlist(list);
}
}
function removeFromWishlist(productId) {
const list = getStoredWishlist().filter(id => id !== productId);
storeWishlist(list);
}
function updateHeartUI(productId, active) {
document.querySelectorAll(
`.js-wishlist-toggle[data-product-id="${productId}"]`
).forEach(btn => {
btn.classList.toggle('is-active', active);
});
}
/* -----------------------------
Sync UI on page load
----------------------------- */
function syncWishlistUI() {
const list = getStoredWishlist();
list.forEach(productId => {
updateHeartUI(productId, true);
});
}
/* -----------------------------
Wishlist Toggle
----------------------------- */
async function toggleWishlist(btn) {
const productId = parseInt(btn.dataset.productId, 10);
if (!productId) return;
const active = btn.classList.contains('is-active');
try {
if (active) {
await fetch('/shop/wishlist/remove', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
body: JSON.stringify({ product_id: productId }),
});
removeFromWishlist(productId);
updateHeartUI(productId, false);
} else {
await fetch('/shop/wishlist/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
body: JSON.stringify({ product_id: productId }),
});
addToWishlist(productId);
updateHeartUI(productId, true);
}
} catch (err) {
console.error('Wishlist error:', err);
}
}
/* -----------------------------
Event Binding
----------------------------- */
function bindWishlistEvents() {
document.body.addEventListener('click', function (e) {
const btn = e.target.closest('.js-wishlist-toggle');
if (!btn) return;
e.preventDefault();
toggleWishlist(btn);
});
}
/* -----------------------------
Init
----------------------------- */
document.addEventListener('DOMContentLoaded', function () {
syncWishlistUI();
bindWishlistEvents();
});
})();