Migrate product data from Kirby to Shopify Storefront API
- Add product loaders (product-loader.js, products-list-loader.js) to fetch data from Shopify - Extend Shopify API client with getProductByHandle() and getAllProducts() methods - Integrate Shopify metafields for multilingual support (custom.title_en, custom.description_en) - Refactor product.php and home.php templates to load content dynamically - Simplify product blueprint to minimal routing configuration - Create generic buy-button.php snippet with variant selection - Update footer.php with conditional script loading - Refactor _section--product.scss for better Sass structure - Add translations for loading states and product errors - Clean up old Kirby product content files Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
957cf79e45
commit
ad699f0365
22 changed files with 649 additions and 579 deletions
|
|
@ -1,109 +1,46 @@
|
|||
/**
|
||||
* 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]');
|
||||
|
||||
// Get translated texts
|
||||
const texts = {
|
||||
add: addToCartBtn.dataset.textAdd || 'Add to cart',
|
||||
adding: addToCartBtn.dataset.textAdding || 'Adding...',
|
||||
added: addToCartBtn.dataset.textAdded || 'Added! ✓',
|
||||
error: addToCartBtn.dataset.textError || 'Error - Try again',
|
||||
outOfStock: addToCartBtn.dataset.textOutOfStock || 'Out of stock',
|
||||
inStock: addToCartBtn.dataset.textInStock || 'In stock'
|
||||
error: addToCartBtn.dataset.textError || 'Error - Try again'
|
||||
};
|
||||
|
||||
// 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 = texts.outOfStock;
|
||||
addToCartBtn.classList.add('out-of-stock');
|
||||
if (stockDisplay) {
|
||||
stockDisplay.textContent = texts.outOfStock;
|
||||
stockDisplay.classList.add('out-of-stock');
|
||||
}
|
||||
} else {
|
||||
// Show in stock
|
||||
if (stockDisplay) {
|
||||
stockDisplay.textContent = texts.inStock;
|
||||
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
|
||||
const variantId = this.dataset.variantId;
|
||||
|
||||
if (!variantId) {
|
||||
console.error('No variant ID found');
|
||||
return;
|
||||
}
|
||||
|
||||
addToCartBtn.disabled = true;
|
||||
const originalText = addToCartBtn.textContent;
|
||||
addToCartBtn.textContent = texts.adding;
|
||||
|
||||
try {
|
||||
const variantId = this.dataset.variantId;
|
||||
const cartResult = await cart.addToCart(variantId, 1);
|
||||
|
||||
// Show success feedback
|
||||
addToCartBtn.textContent = texts.added;
|
||||
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;
|
||||
|
|
@ -113,11 +50,9 @@
|
|||
} catch (error) {
|
||||
console.error('Error adding to cart:', error);
|
||||
|
||||
// Show error feedback
|
||||
addToCartBtn.textContent = texts.error;
|
||||
addToCartBtn.classList.add('error');
|
||||
|
||||
// Re-enable button after delay
|
||||
setTimeout(() => {
|
||||
addToCartBtn.disabled = false;
|
||||
addToCartBtn.textContent = originalText;
|
||||
|
|
@ -125,7 +60,4 @@
|
|||
}, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
// Load product data on page load
|
||||
loadProductData();
|
||||
})();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue