+ ${productTitle} +
+${price}€
+ +diff --git a/assets/css/template/shop/_section--product.scss b/assets/css/template/shop/_section--product.scss index 82790ac..972dae8 100644 --- a/assets/css/template/shop/_section--product.scss +++ b/assets/css/template/shop/_section--product.scss @@ -1,12 +1,3 @@ -.section__product, -.store__nav{ - max-width: 1200px; - margin-left: auto; - margin-right: auto; -} - - - .section__product, .store__nav { max-width: 1200px; @@ -14,10 +5,6 @@ margin-right: auto; } - - - - .store__nav { padding-top: calc(var(--spacing) * 1); padding-bottom: calc(var(--spacing) * 0.5); @@ -27,174 +14,35 @@ a { text-decoration: none; + &::before { + content: "← "; + } + &:hover { text-decoration: underline; } } - a::before { - content: "← "; - } -} - - - -.section__product .details { - // margin-bottom: calc(var(--spacing) * 2); - - ul{ - margin-left: 2ch; - li{ - padding-bottom: 0.2em; + @media #{$small} { + a { + padding-top: 0; + font-size: var(--fs-small); } } } +.section__product { + .details { + ul { + margin-left: 2ch; -.product-options__list { - list-style: none; - display: flex; - gap: 2ch; - li { - position: relative; - - input[type="radio"] { - position: fixed; - opacity: 0; - pointer-events: none; - } - - label { - font-family: var(--title); - font-size: var(--fs-normal); - height: 4ch; - width: 4ch; - border-radius: 50%; - border: var(--border); - border-color: transparent; - display: flex; - align-items: center; - justify-content: center; - padding-top: 0px; - cursor: pointer; - } - - input[type="radio"]:checked + label { - border-color: var(--color-txt); - } - - input[type="radio"]:not(:checked) + label:hover { - border-color: var(--grey-600); - background-color: var(--grey-800); - } - } - } - - - - - - - - - -.product-gallery { - position: relative; - aspect-ratio: 4 / 3; - - .swiper-slide { - width: 100%; - - figure { - - aspect-ratio: 4 / 3; - width: 100%; - height: 100%; - - img { - width: 100%; - height: 100%; - object-fit: contain; + padding-bottom: 0.2em; } } } - // Swiper navigation arrows - .swiper-button-prev, - .swiper-button-next { - color: var(--color-txt); - width: 20px; - height: 20px; - - &:after { - font-size: 20px; - font-weight: bold; - } - - &:hover { - opacity: 0.7; - } - } - - // Swiper pagination dots - .swiper-pagination { - position: relative; - margin-top: calc(var(--spacing) * 0.5); - bottom: 0; - - .swiper-pagination-bullet { - width: 8px; - height: 8px; - background: var(--grey-600); - opacity: 0.5; - transition: opacity 0.3s; - - &:hover { - opacity: 0.7; - } - } - - .swiper-pagination-bullet-active { - background: var(--color-txt); - opacity: 1; - } - } -} - - - .hero { - margin-bottom: calc(var(--spacing) * 1); - padding: calc(var(--spacing) * 0.5) 0; - border-top: var(--border-light); - border-bottom: var(--border-light); - - .p__baseline-big { - margin: 0; - text-align: left; - } - } - - .add-to-cart { - margin: 0; - border-bottom: var(--border-light); - padding: calc(var(--spacing) * 0.5) 0; - } - - .product-options { - border-bottom: var(--border-light); - padding: calc(var(--spacing) * 0.25) 0; - } - - - -@media #{$small} { - .store__nav a { - padding-top: 0; - font-size: var(--fs-small); - } - - .section__product { + @media #{$small} { display: flex; flex-direction: column; margin-bottom: 10vh; @@ -207,6 +55,7 @@ margin-top: calc(var(--spacing) * 0.5); order: 1; } + figure { order: 2; margin-bottom: calc(var(--spacing) * 1); @@ -226,25 +75,25 @@ order: 5; } - .product-gallery{ + .product-gallery { width: 100vw; position: relative; - left: calc(var(--padding-body)*-1); + left: calc(var(--padding-body) * -1); .swiper-button-prev, - .swiper-button-next{ display: none; } + .swiper-button-next { + display: none; + } } } -} -@media #{$small-up} { - - - .section__product{ - display: grid; - grid-template-columns: 1fr 1fr; - gap: calc(var(--padding-body)*2); - margin-bottom: calc(var(--spacing)*3); + @media #{$small-up} { + .product-content { + display: grid; + grid-template-columns: 1fr 1fr; + gap: calc(var(--padding-body) * 2); + margin-bottom: calc(var(--spacing) * 3); + } .details { margin-bottom: calc(var(--spacing) * 2); @@ -255,17 +104,140 @@ border-top: var(--border-light); } - .col-left{ + .col-left { min-height: 100%; - padding-bottom: 40px; //dots - + padding-bottom: 40px; display: flex; flex-direction: column; } - - } - - .product-gallery .swiper-slide figure{ - width: calc(100% - 60px); } } + +.product-options { + border-bottom: var(--border-light); + padding: calc(var(--spacing) * 0.25) 0; +} + +.product-options__list { + list-style: none; + display: flex; + gap: 2ch; + + li { + position: relative; + + input[type="radio"] { + position: fixed; + opacity: 0; + pointer-events: none; + + &:checked + label { + border-color: var(--color-txt); + } + + &:not(:checked) + label:hover { + border-color: var(--grey-600); + background-color: var(--grey-800); + } + } + + label { + font-family: var(--title); + font-size: var(--fs-normal); + height: 4ch; + width: 4ch; + border-radius: 50%; + border: var(--border); + border-color: transparent; + display: flex; + align-items: center; + justify-content: center; + padding-top: 0px; + cursor: pointer; + } + } +} + +.product-gallery { + position: relative; + aspect-ratio: 4 / 3; + + .swiper-slide { + width: 100%; + + figure { + aspect-ratio: 4 / 3; + width: 100%; + height: 100%; + + img { + width: 100%; + height: 100%; + object-fit: contain; + } + } + + @media #{$small-up} { + figure { + width: calc(100% - 60px); + } + } + } + + .swiper-button-prev, + .swiper-button-next { + color: var(--color-txt); + width: 20px; + height: 20px; + + &:after { + font-size: 20px; + font-weight: bold; + } + + &:hover { + opacity: 0.7; + } + } + + .swiper-pagination { + position: relative; + margin-top: calc(var(--spacing) * 0.5); + bottom: 0; + + .swiper-pagination-bullet { + width: 8px; + height: 8px; + background: var(--grey-600); + opacity: 0.5; + transition: opacity 0.3s; + + &:hover { + opacity: 0.7; + } + + &.swiper-pagination-bullet-active { + background: var(--color-txt); + opacity: 1; + } + } + } +} + +.hero { + margin-bottom: calc(var(--spacing) * 1); + padding: calc(var(--spacing) * 0.5) 0; + border-top: var(--border-light); + border-bottom: var(--border-light); + + .p__baseline-big { + margin: 0; + text-align: left; + } +} + +.add-to-cart { + margin: 0; + border-bottom: var(--border-light); + padding: calc(var(--spacing) * 0.5) 0; +} diff --git a/assets/js/product-add-to-cart.js b/assets/js/product-add-to-cart.js index 5c5d5d5..51ee83c 100644 --- a/assets/js/product-add-to-cart.js +++ b/assets/js/product-add-to-cart.js @@ -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(); })(); diff --git a/assets/js/product-loader.js b/assets/js/product-loader.js new file mode 100644 index 0000000..142e4ad --- /dev/null +++ b/assets/js/product-loader.js @@ -0,0 +1,188 @@ +(async function () { + const container = document.querySelector("[data-product-loader]"); + if (!container) return; + + const handle = container.dataset.shopifyHandle; + const language = container.dataset.language || 'fr'; + const isEnglish = language === 'en'; + const loadingState = container.querySelector(".product-loading"); + const contentState = container.querySelector(".product-content"); + const errorState = container.querySelector(".product-error"); + + try { + const cart = new ShopifyCart({ + domain: "nv7cqv-bu.myshopify.com", + storefrontAccessToken: "dec3d35a2554384d149c72927d1cfd1b", + }); + + const product = await cart.getProductByHandle(handle); + + if (!product) { + throw new Error("Product not found"); + } + + renderProduct(product, isEnglish); + + loadingState.style.display = "none"; + contentState.removeAttribute("style"); + + setTimeout(() => { + if (typeof Swiper !== "undefined" && product.images.edges.length > 0) { + new Swiper(".product-gallery", { + loop: product.images.edges.length > 1, + navigation: { + nextEl: ".swiper-button-next", + prevEl: ".swiper-button-prev", + }, + pagination: { + el: ".swiper-pagination", + clickable: true, + }, + keyboard: { + enabled: true, + }, + }); + } + }, 100); + } catch (error) { + console.error("Error loading product:", error); + loadingState.style.display = "none"; + errorState.style.display = "block"; + } + + function renderProduct(product, isEnglish) { + renderTitle(product, isEnglish); + renderPrice(product); + renderDetails(product, isEnglish); + renderImages(product, isEnglish); + renderVariants(product); + setupAddToCart(product); + renderStock(product); + } + + function renderTitle(product, isEnglish) { + const titleEl = document.querySelector("[data-product-title]"); + if (titleEl) { + const title = isEnglish && product.titleEn?.value + ? product.titleEn.value + : product.title; + titleEl.textContent = title; + } + } + + function renderPrice(product) { + const priceEl = document.querySelector("[data-product-price]"); + if (priceEl) { + const price = parseFloat(product.priceRange.minVariantPrice.amount); + priceEl.textContent = price.toFixed(2) + "€"; + } + } + + function renderDetails(product, isEnglish) { + const detailsEl = document.querySelector("[data-product-details]"); + if (detailsEl) { + const description = isEnglish && product.descriptionEn?.value + ? product.descriptionEn.value + : product.descriptionHtml || ""; + detailsEl.innerHTML = description; + } + } + + function renderImages(product, isEnglish) { + const imagesContainer = document.querySelector("[data-product-images]"); + + if (imagesContainer && product.images.edges.length > 0) { + const productTitle = isEnglish && product.titleEn?.value + ? product.titleEn.value + : product.title; + + imagesContainer.innerHTML = product.images.edges + .map((edge) => { + const img = edge.node; + return ` +
+ `; + }) + .join(""); + } + } + + function renderVariants(product) { + if (product.variants.edges.length <= 1) return; + + const variantsContainer = document.querySelector("[data-product-variants]"); + const variantSelector = document.querySelector("[data-variant-selector]"); + + if (!variantsContainer || !variantSelector) return; + + variantsContainer.style.display = "block"; + + variantSelector.innerHTML = product.variants.edges + .map((edge) => { + const variant = edge.node; + const variantId = variant.id.replace( + "gid://shopify/ProductVariant/", + "" + ); + const price = parseFloat(variant.price.amount).toFixed(2) + "€"; + const availability = variant.availableForSale + ? "" + : " (Rupture de stock)"; + + return ``; + }) + .join(""); + + variantSelector.addEventListener("change", (e) => { + const addToCartBtn = document.querySelector("[data-shopify-add-to-cart]"); + if (addToCartBtn) { + addToCartBtn.dataset.variantId = e.target.value; + } + }); + } + + function setupAddToCart(product) { + const addToCartBtn = document.querySelector("[data-shopify-add-to-cart]"); + if (!addToCartBtn) return; + + const productId = product.id.replace("gid://shopify/Product/", ""); + addToCartBtn.dataset.productId = productId; + + const firstAvailableVariant = product.variants.edges.find( + (e) => e.node.availableForSale + ); + if (firstAvailableVariant) { + const variantId = firstAvailableVariant.node.id.replace( + "gid://shopify/ProductVariant/", + "" + ); + addToCartBtn.dataset.variantId = variantId; + } + } + + function renderStock(product) { + const stockEl = document.querySelector("[data-product-stock]"); + if (!stockEl) return; + + const addToCartBtn = document.querySelector("[data-shopify-add-to-cart]"); + + if (product.availableForSale) { + stockEl.textContent = addToCartBtn?.dataset.textInStock || "En stock"; + stockEl.classList.add("in-stock"); + } else { + stockEl.textContent = + addToCartBtn?.dataset.textOutOfStock || "Rupture de stock"; + stockEl.classList.add("out-of-stock"); + } + } +})(); diff --git a/assets/js/products-list-loader.js b/assets/js/products-list-loader.js new file mode 100644 index 0000000..be32f4a --- /dev/null +++ b/assets/js/products-list-loader.js @@ -0,0 +1,47 @@ +(async function() { + const container = document.querySelector('[data-products-loader]'); + if (!container) return; + + const language = (container.dataset.language || 'FR').toLowerCase(); + const isEnglish = language === 'en'; + + try { + const cart = new ShopifyCart({ + domain: 'nv7cqv-bu.myshopify.com', + storefrontAccessToken: 'dec3d35a2554384d149c72927d1cfd1b' + }); + + const productsData = await cart.getAllProducts(); + const products = productsData.edges; + + const productsHtml = products.map(edge => { + const product = edge.node; + const image = product.images.edges[0]?.node; + const price = parseFloat(product.priceRange.minVariantPrice.amount).toFixed(2); + const slug = product.handle; + const productUrl = isEnglish ? `/en/${slug}` : `/${slug}`; + const productTitle = isEnglish && product.titleEn?.value + ? product.titleEn.value + : product.title; + + return ` ++ ${productTitle} +
+${price}€
+ +Erreur lors du chargement des produits
'; + } +})(); diff --git a/assets/js/shopify-cart.js b/assets/js/shopify-cart.js index faf88d7..18b1338 100644 --- a/assets/js/shopify-cart.js +++ b/assets/js/shopify-cart.js @@ -73,6 +73,117 @@ class ShopifyCart { return data.product; } + /** + * Get product by handle + * @param {string} handle - Product handle (slug) + */ + async getProductByHandle(handle) { + const query = ` + query getProductByHandle($handle: String!) { + product(handle: $handle) { + id + handle + title + description + descriptionHtml + availableForSale + tags + titleEn: metafield(namespace: "custom", key: "title_en") { + value + } + descriptionEn: metafield(namespace: "custom", key: "description_en") { + value + } + priceRange { + minVariantPrice { + amount + currencyCode + } + } + images(first: 10) { + edges { + node { + id + url + altText + width + height + } + } + } + variants(first: 20) { + edges { + node { + id + title + sku + availableForSale + price { + amount + currencyCode + } + selectedOptions { + name + value + } + } + } + } + } + } + `; + + const data = await this.query(query, { handle }); + return data.product || null; + } + + /** + * Get all products for listing page + * @param {number} first - Number of products to fetch + */ + async getAllProducts(first = 20) { + const query = ` + query getAllProducts($first: Int!) { + products(first: $first, sortKey: TITLE) { + edges { + node { + id + handle + title + description + availableForSale + titleEn: metafield(namespace: "custom", key: "title_en") { + value + } + priceRange { + minVariantPrice { + amount + currencyCode + } + } + images(first: 1) { + edges { + node { + id + url + altText + } + } + } + } + } + pageInfo { + hasNextPage + endCursor + } + } + } + `; + + const data = await this.query(query, { first }); + return data.products; + } + /** * Create a new cart */ diff --git a/content/1_eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat/product.en.txt b/content/1_eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat/product.en.txt new file mode 100644 index 0000000..6bbc828 --- /dev/null +++ b/content/1_eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat/product.en.txt @@ -0,0 +1,5 @@ +Title: Éclairages : 12 entretiens et analyses sur les violences d'État + +---- + +Uuid: gzshayl6xoefrnsz diff --git a/content/1_eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat/product.fr.txt b/content/1_eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat/product.fr.txt new file mode 100644 index 0000000..f26cd4f --- /dev/null +++ b/content/1_eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat/product.fr.txt @@ -0,0 +1,9 @@ +Title: Éclairages : 12 entretiens et analyses sur les violences d’État + +---- + +Shopifyhandle: eclairages-12-entretiens-et-analyses-sur-les-violences-d-etat + +---- + +Uuid: gzshayl6xoefrnsz \ No newline at end of file diff --git a/content/1_tshirt-index-01/product.en.txt b/content/1_tshirt-index-01/product.en.txt deleted file mode 100644 index 7dec4a5..0000000 --- a/content/1_tshirt-index-01/product.en.txt +++ /dev/null @@ -1,33 +0,0 @@ -Title: T-shirt Index 01 - ----- - -Price: 35 - ----- - -Description:T-shirt de soutien à Index, 100% coton
- ----- - -Details:Organic cotton t-shirt with screen printing.
Print on the front: "INDEX" logo, 10 cm wide.
100% organic cotton
Weight: 180 g/m²
Single jersey with very soft feel
Excellent durability over time
Internal neckband
Double stitching on sleeves and bottom hem
Shipping only via Mondial Relay to France, Belgium and Switzerland.
- ----- - -Options: - -- - label: Size - values: XS, S, M, L, XL - ----- - -Snipcartid: tshirt-01 - ----- - -Backgroundcolor: #ffffff - ----- - -Template: product \ No newline at end of file diff --git a/content/1_tshirt-index-01/product.fr.txt b/content/1_tshirt-index-01/product.fr.txt deleted file mode 100644 index 2226ab3..0000000 --- a/content/1_tshirt-index-01/product.fr.txt +++ /dev/null @@ -1,56 +0,0 @@ -Title: T-shirt Index 01 - ----- - -Price: 35 - ----- - -Stock: 10 - ----- - -Description: T-shirt de soutien à Index, 100% coton - ----- - -Details:T-shirt en coton organique avec impression sérigraphique.
Marquage sur la face avant : logo « INDEX » de 10 cm de large.
100 % coton biologique
Grammage : 180 g/m²
Jersey simple au toucher très doux
Excellente tenue dans le temps
Bande de propreté intérieure au col
Surpiqûres doubles en bas de manches et en bas de corps
Envoi uniquement via Mondial Relay vers la France, la Belgique et la Suisse.
- ----- - -Hasoptions: true - ----- - -Optionlabel: Taille - ----- - -Optionvalues: XS, S, M, L, XL - ----- - -Options: - -- - label: Taille - values: XS, S, M, L, XL -- - label: Couleur - values: Rouge, Vert - ----- - -Snipcartid: tshirt-01 - ----- - -Backgroundcolor: #ffffff - ----- - -Template: product - ----- - -Uuid: udrrfizhayqixfoo \ No newline at end of file diff --git a/content/1_tshirt-index-01/test.png b/content/1_tshirt-index-01/test.png deleted file mode 100644 index f05f4a3..0000000 Binary files a/content/1_tshirt-index-01/test.png and /dev/null differ diff --git a/content/1_tshirt-index-01/test.png.fr.txt b/content/1_tshirt-index-01/test.png.fr.txt deleted file mode 100644 index cd5255a..0000000 --- a/content/1_tshirt-index-01/test.png.fr.txt +++ /dev/null @@ -1,9 +0,0 @@ -Sort: 1 - ----- - -Uuid: elxkhcta8dkjhr60 - ----- - -Template: image \ No newline at end of file diff --git a/content/1_tshirt-index-01/tshirt-01.png b/content/1_tshirt-index-01/tshirt-01.png deleted file mode 100644 index 99899b8..0000000 Binary files a/content/1_tshirt-index-01/tshirt-01.png and /dev/null differ diff --git a/content/1_tshirt-index-01/tshirt-01.png.fr.txt b/content/1_tshirt-index-01/tshirt-01.png.fr.txt deleted file mode 100644 index c9a1f27..0000000 --- a/content/1_tshirt-index-01/tshirt-01.png.fr.txt +++ /dev/null @@ -1,9 +0,0 @@ -Sort: 2 - ----- - -Uuid: deupkqq83jvloz0r - ----- - -Template: image \ No newline at end of file diff --git a/content/2_t-shirt-index/product.en.txt b/content/2_t-shirt-index/product.en.txt new file mode 100644 index 0000000..7aa8f14 --- /dev/null +++ b/content/2_t-shirt-index/product.en.txt @@ -0,0 +1,5 @@ +Title: T-shirt Index + +---- + +Uuid: qq27mjjpethsvnwp diff --git a/content/2_t-shirt-index/product.fr.txt b/content/2_t-shirt-index/product.fr.txt new file mode 100644 index 0000000..395184c --- /dev/null +++ b/content/2_t-shirt-index/product.fr.txt @@ -0,0 +1,9 @@ +Title: T-shirt Index + +---- + +Shopifyhandle: t-shirt-index-01 + +---- + +Uuid: qq27mjjpethsvnwp \ No newline at end of file diff --git a/site/blueprints/pages/product.yml b/site/blueprints/pages/product.yml index 52fde12..978bcde 100644 --- a/site/blueprints/pages/product.yml +++ b/site/blueprints/pages/product.yml @@ -1,134 +1,21 @@ -title: - en: Product - fr: Produit +title: Product icon: cart -tabs: - content: - label: - en: Content - fr: Contenu - columns: - - width: 2/3 - sections: - main: - type: fields - fields: - price: - label: - en: Price (€) - fr: Prix (€) - type: number - min: 0 - step: 0.01 - required: true - translate: false - width: 1/4 - stock: - label: Stock - type: number - min: 0 - default: 0 - help: - en: Edit through french version - fr: Partagé entre les versions FR et EN - translate: false - width: 1/4 - space: - type: gap - width: 2/4 - weight: - label: - en: Weight (g) - fr: Poids (g) - type: number - min: 0 - default: 0 - help: - en: Weight in grams for shipping calculation - fr: Poids en grammes pour le calcul de la livraison - translate: false - width: 1/4 - length: - label: - en: Length (cm) - fr: Longueur (cm) - type: number - min: 0 - default: 0 - help: - en: Package length in centimeters - fr: Longueur du colis en centimètres - translate: false - width: 1/4 - width: - label: - en: Width (cm) - fr: Largeur (cm) - type: number - min: 0 - default: 0 - help: - en: Package width in centimeters - fr: Largeur du colis en centimètres - translate: false - width: 1/4 - height: - label: - en: Height (cm) - fr: Hauteur (cm) - type: number - min: 0 - default: 0 - help: - en: Package height in centimeters - fr: Hauteur du colis en centimètres - translate: false - width: 1/4 - description: - label: Description panier - type: writer - help: Visible dans le panier seulement. - details: - label: - en: Details - fr: Détails - type: writer - hasOptions: - label: - en: Options - fr: Options - type: toggle - default: false - translate: false - width: 1/7 - optionLabel: - label: - en: Option label - fr: Libellé de l'option - type: text - width: 3/7 - when: - hasOptions: true - optionValues: - label: - en: Option values - fr: Valeurs de l'option - type: tags - help: - en: "Comma-separated values (e.g.: XS, S, M, L, XL)" - fr: "Valeurs séparées par des virgules (ex: XS, S, M, L, XL)" - translate: false - when: - hasOptions: true - width: 3/7 +columns: + - width: 1/1 + fields: + info: + type: info + text: + en: "Product data (title, description, images, price) is managed in Shopify Admin. This Kirby page only serves for routing." + fr: "Les données produit (titre, description, images, prix) sont gérées dans Shopify Admin. Cette page Kirby sert uniquement au routing." - - width: 1/3 - sections: - images: - type: files - headline: - en: Product Images - fr: Images du produit - template: image - layout: cards + shopifyHandle: + label: + en: Shopify Handle + fr: Shopify Handle + type: text + help: + en: "Product handle from Shopify (e.g. tshirt-index-01). If empty, uses the page slug." + fr: "Handle du produit Shopify (ex: tshirt-index-01). Si vide, utilise le slug de la page Kirby." + placeholder: tshirt-index-01 diff --git a/site/languages/en.php b/site/languages/en.php index 613b944..19e9aec 100644 --- a/site/languages/en.php +++ b/site/languages/en.php @@ -27,6 +27,9 @@ return [ 'addedToCart' => 'Added! ✓', 'errorAddToCart' => 'Error - Try again', 'closeCart' => 'Close cart', + 'loading' => 'Loading...', + 'productNotFound' => 'Product not found', + 'selectVariant' => 'Select', // Blueprints - Home 'home.title' => 'Home', diff --git a/site/languages/fr.php b/site/languages/fr.php index 63ca317..249bb4d 100644 --- a/site/languages/fr.php +++ b/site/languages/fr.php @@ -27,6 +27,9 @@ return [ 'addedToCart' => 'Ajouté ! ✓', 'errorAddToCart' => 'Erreur - Réessayer', 'closeCart' => 'Fermer le panier', + 'loading' => 'Chargement...', + 'productNotFound' => 'Produit non trouvé', + 'selectVariant' => 'Choisir', // Blueprints - Home 'home.title' => 'Accueil', diff --git a/site/snippets/buy-button.php b/site/snippets/buy-button.php new file mode 100644 index 0000000..7769f2e --- /dev/null +++ b/site/snippets/buy-button.php @@ -0,0 +1,25 @@ +