Implement custom Shopify cart with drawer UI
Replace Shopify Buy Button iframe with custom implementation using Storefront API 2026-01. Create interactive cart drawer with full product management capabilities (add, remove, update quantities) and seamless checkout flow. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
c08662caf8
commit
28501fec7c
13 changed files with 1158 additions and 81 deletions
121
assets/js/product-add-to-cart.js
Normal file
121
assets/js/product-add-to-cart.js
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
* Product Add to Cart functionality
|
||||
* Handles the add to cart button interaction with Shopify
|
||||
*/
|
||||
(function() {
|
||||
// Initialize Shopify Cart
|
||||
const cart = new ShopifyCart({
|
||||
domain: 'nv7cqv-bu.myshopify.com',
|
||||
storefrontAccessToken: 'dec3d35a2554384d149c72927d1cfd1b'
|
||||
});
|
||||
|
||||
// Get product ID from data attribute
|
||||
const addToCartBtn = document.querySelector('[data-shopify-add-to-cart]');
|
||||
|
||||
if (!addToCartBtn) {
|
||||
console.warn('Add to cart button not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const productId = addToCartBtn.dataset.productId;
|
||||
const variantId = addToCartBtn.dataset.variantId;
|
||||
const stockDisplay = document.querySelector('[data-product-stock]');
|
||||
|
||||
// Load product data to check availability
|
||||
async function loadProductData() {
|
||||
try {
|
||||
const product = await cart.getProduct(productId);
|
||||
|
||||
if (!product) {
|
||||
console.error('Product not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the specific variant or use the first one
|
||||
let variant;
|
||||
if (variantId) {
|
||||
variant = product.variants.edges.find(
|
||||
edge => edge.node.id === `gid://shopify/ProductVariant/${variantId}`
|
||||
)?.node;
|
||||
} else {
|
||||
variant = product.variants.edges[0]?.node;
|
||||
}
|
||||
|
||||
if (!variant) {
|
||||
console.error('Variant not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Update button based on availability
|
||||
if (!variant.availableForSale) {
|
||||
addToCartBtn.disabled = true;
|
||||
addToCartBtn.textContent = 'Rupture de stock';
|
||||
addToCartBtn.classList.add('out-of-stock');
|
||||
if (stockDisplay) {
|
||||
stockDisplay.textContent = 'Rupture de stock';
|
||||
stockDisplay.classList.add('out-of-stock');
|
||||
}
|
||||
} else {
|
||||
// Show in stock
|
||||
if (stockDisplay) {
|
||||
stockDisplay.textContent = 'En stock';
|
||||
stockDisplay.classList.add('in-stock');
|
||||
}
|
||||
}
|
||||
|
||||
// Store variant ID for later use
|
||||
addToCartBtn.dataset.variantId = variant.id.replace('gid://shopify/ProductVariant/', '');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error loading product:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle add to cart click
|
||||
addToCartBtn.addEventListener('click', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Disable button during request
|
||||
addToCartBtn.disabled = true;
|
||||
const originalText = addToCartBtn.textContent;
|
||||
addToCartBtn.textContent = 'Ajout en cours...';
|
||||
|
||||
try {
|
||||
const variantId = this.dataset.variantId;
|
||||
const cartResult = await cart.addToCart(variantId, 1);
|
||||
|
||||
// Show success feedback
|
||||
addToCartBtn.textContent = 'Ajouté ! ✓';
|
||||
addToCartBtn.classList.add('success');
|
||||
|
||||
// Dispatch event to open cart drawer
|
||||
document.dispatchEvent(new CustomEvent('cart:updated', {
|
||||
detail: { cart: cartResult }
|
||||
}));
|
||||
|
||||
// Reset button after short delay
|
||||
setTimeout(() => {
|
||||
addToCartBtn.disabled = false;
|
||||
addToCartBtn.textContent = originalText;
|
||||
addToCartBtn.classList.remove('success');
|
||||
}, 1500);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error adding to cart:', error);
|
||||
|
||||
// Show error feedback
|
||||
addToCartBtn.textContent = 'Erreur - Réessayer';
|
||||
addToCartBtn.classList.add('error');
|
||||
|
||||
// Re-enable button after delay
|
||||
setTimeout(() => {
|
||||
addToCartBtn.disabled = false;
|
||||
addToCartBtn.textContent = originalText;
|
||||
addToCartBtn.classList.remove('error');
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
// Load product data on page load
|
||||
loadProductData();
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue