index-shop/assets/js/cart-drawer.js

215 lines
6 KiB
JavaScript
Raw Normal View History

/**
* Cart Drawer Component
* Manages the cart sidebar with add/remove/update functionality
*/
(function() {
const drawer = document.getElementById('cart-drawer');
const emptyState = document.querySelector('[data-cart-empty]');
const itemsContainer = document.querySelector('[data-cart-items]');
const checkoutBtn = document.querySelector('[data-cart-checkout]');
const closeButtons = document.querySelectorAll('[data-cart-close]');
let currentCart = null;
let cartInstance = null;
// Wait for ShopifyCart to be available
function initCartDrawer() {
if (typeof ShopifyCart === 'undefined') {
setTimeout(initCartDrawer, 100);
return;
}
cartInstance = new ShopifyCart({
domain: 'nv7cqv-bu.myshopify.com',
storefrontAccessToken: 'dec3d35a2554384d149c72927d1cfd1b'
});
// Initialize event listeners
setupEventListeners();
}
function setupEventListeners() {
// Close drawer
closeButtons.forEach(btn => {
btn.addEventListener('click', closeDrawer);
});
// Checkout button
checkoutBtn.addEventListener('click', () => {
if (currentCart?.checkoutUrl) {
window.location.href = currentCart.checkoutUrl;
}
});
// Listen for custom cart update events
document.addEventListener('cart:updated', (e) => {
currentCart = e.detail.cart;
renderCart();
openDrawer();
});
}
function openDrawer() {
drawer.classList.add('is-open');
document.body.style.overflow = 'hidden';
}
function closeDrawer() {
drawer.classList.remove('is-open');
document.body.style.overflow = '';
}
function renderCart() {
if (!currentCart || !currentCart.lines || currentCart.lines.edges.length === 0) {
emptyState.classList.remove('hidden');
itemsContainer.classList.add('hidden');
checkoutBtn.disabled = true;
return;
}
emptyState.classList.add('hidden');
itemsContainer.classList.remove('hidden');
checkoutBtn.disabled = false;
// Render cart items
itemsContainer.innerHTML = currentCart.lines.edges.map(edge => {
const item = edge.node;
const merchandise = item.merchandise;
return `
<div class="cart-item" data-line-id="${item.id}">
<div class="cart-item__details">
<h4 class="cart-item__title">${merchandise.product.title}</h4>
${merchandise.title !== 'Default Title' ? `<p class="cart-item__variant">${merchandise.title}</p>` : ''}
<p class="cart-item__price">${merchandise.price.amount} ${merchandise.price.currencyCode}</p>
<div class="cart-item__quantity">
<button class="cart-item__qty-btn" data-action="decrease" data-line-id="${item.id}"></button>
<span class="cart-item__qty-value">${item.quantity}</span>
<button class="cart-item__qty-btn" data-action="increase" data-line-id="${item.id}">+</button>
</div>
<button class="cart-item__remove" data-action="remove" data-line-id="${item.id}">
Retirer
</button>
</div>
</div>
`;
}).join('');
// Attach event listeners to quantity buttons
attachQuantityListeners();
}
function attachQuantityListeners() {
const buttons = itemsContainer.querySelectorAll('[data-action]');
buttons.forEach(btn => {
btn.addEventListener('click', async (e) => {
const action = e.target.dataset.action;
const lineId = e.target.dataset.lineId;
await handleQuantityChange(action, lineId);
});
});
}
async function handleQuantityChange(action, lineId) {
if (!cartInstance || !currentCart) return;
// Find the line item
const line = currentCart.lines.edges.find(edge => edge.node.id === lineId);
if (!line) return;
const currentQty = line.node.quantity;
let newQty = currentQty;
if (action === 'increase') {
newQty = currentQty + 1;
} else if (action === 'decrease') {
newQty = Math.max(0, currentQty - 1);
} else if (action === 'remove') {
newQty = 0;
}
// Update cart via API
try {
itemsContainer.classList.add('is-loading');
const query = `
mutation cartLinesUpdate($cartId: ID!, $lines: [CartLineUpdateInput!]!) {
cartLinesUpdate(cartId: $cartId, lines: $lines) {
cart {
id
checkoutUrl
lines(first: 10) {
edges {
node {
id
quantity
merchandise {
... on ProductVariant {
id
title
price {
amount
currencyCode
}
product {
title
}
}
}
}
}
}
}
userErrors {
field
message
}
}
}
`;
const data = await cartInstance.query(query, {
cartId: currentCart.id,
lines: [{
id: lineId,
quantity: newQty
}]
});
if (data.cartLinesUpdate.userErrors.length > 0) {
throw new Error(data.cartLinesUpdate.userErrors[0].message);
}
currentCart = data.cartLinesUpdate.cart;
renderCart();
} catch (error) {
console.error('Error updating cart:', error);
alert('Erreur lors de la mise à jour du panier');
} finally {
itemsContainer.classList.remove('is-loading');
}
}
// Public API
window.CartDrawer = {
open: openDrawer,
close: closeDrawer,
updateCart: (cart) => {
currentCart = cart;
renderCart();
}
};
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initCartDrawer);
} else {
initCartDrawer();
}
})();