From cb46b980681c7ddd4d06259c179e9c4dec4a7f03 Mon Sep 17 00:00:00 2001 From: jonkaric Date: Sat, 3 May 2025 16:29:46 +0100 Subject: [PATCH 1/4] Added site_currency tag --- docs/tags.md | 22 ++++++++-------------- src/Tags/Gaia.php | 11 +++++++++++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/docs/tags.md b/docs/tags.md index d3947a9..a800a93 100644 --- a/docs/tags.md +++ b/docs/tags.md @@ -1,19 +1,6 @@ # Tags -
- -- [currency](#currency) -- [customer:orders](#customer-orders) -- [customer:order](#customer-order) -- [id](#id) -- [product:single](#product-single) -- [product:configurable](#product-configurable) -- [product:price](#product-price) -- [product:options](#product-options) -- [store:countries](#store-countries) -- [wishlist:contains](#test) - -
+[TOC] ## Introduction @@ -55,6 +42,13 @@ Attach it to a variable to make it reusable: ``` +## siteCurrency +Returns the current currency that is being used by the site. This will either be the `default_currency` defined in `gaia.php` or the `currency` attribute set on the site if you're on a multisite setup. + +```twig +{{ gaia:site_currency }} +``` + ## product:single Returns `true` if the current product is a single product that has no variants, or `false` if it does. diff --git a/src/Tags/Gaia.php b/src/Tags/Gaia.php index 0456c94..b324ca6 100644 --- a/src/Tags/Gaia.php +++ b/src/Tags/Gaia.php @@ -57,6 +57,17 @@ public function id() { return Str::lower(Str::random(10)); } + + /** + * Retrieves the current site's currency. + * + * @return string The currency code for the current site. + * If not set, returns the default currency from configuration. + */ + public function siteCurrency(): string + { + return Site::current()->attribute('currency') ?? config('gaia.default_currency'); + } public function livewireStart(): string { From d305c7e14875dd1757910f4c25ac30b14e1b53e1 Mon Sep 17 00:00:00 2001 From: jonkaric Date: Sat, 3 May 2025 16:30:39 +0100 Subject: [PATCH 2/4] JS formatPrice now takes in locale & currency codes --- js/dist/gaia.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/js/dist/gaia.js b/js/dist/gaia.js index fa8d1d1..a34b791 100644 --- a/js/dist/gaia.js +++ b/js/dist/gaia.js @@ -30,8 +30,12 @@ window.gaia = { }); }, - formatPrice: (price, currency) => { - return price.toLocaleString("en-GB", { style: "currency", currency: "GBP" }); + formatPrice: (price, locale, currency) => { + // Since the code comes from Statamic it should be in POSIX format, we + // will attempt to convert to a valid BCP 47 locale. + locale = locale.replace('_', '-'); + + return price.toLocaleString(locale, { style: "currency", currency: currency }); }, getCSRF: () => { From d53937f15e80d64c4abb1289a598f9efb7c15b86 Mon Sep 17 00:00:00 2001 From: jonkaric Date: Sat, 3 May 2025 16:36:47 +0100 Subject: [PATCH 3/4] Price now supports configurable products --- .../shop/product/default/_price.antlers.html | 78 ++++++++++---- .../shop/product/default/index.antlers.html | 100 ++++++++++++++---- 2 files changed, 138 insertions(+), 40 deletions(-) diff --git a/stubs/resources/views/shop/product/default/_price.antlers.html b/stubs/resources/views/shop/product/default/_price.antlers.html index 6f71575..e365d3d 100644 --- a/stubs/resources/views/shop/product/default/_price.antlers.html +++ b/stubs/resources/views/shop/product/default/_price.antlers.html @@ -1,23 +1,61 @@ -
- {{ gaia:product:price }} - {{ if {gaia:product:single} }} - {{ if is_discounted }} - Now {{ gaia:currency :price="min_discounted_price" }} -
- Was {{ gaia:currency :price="min_regular_price" }} - {{ if (discount_percentage <= '5') }} - (-{{ gaia:currency :price="discount_amount" }}) - {{ else }} - (-{{ discount_percentage | floor }}%) - {{ /if }} -
- {{ /else }} - {{ gaia:currency :price="min_price" }} +
+ + {{ gaia:product:price }} + {{ if {gaia:product:single} }} + {{ if is_discounted }} + Now {{ gaia:currency :price="min_discounted_price" }} +
+ Was {{ gaia:currency :price="min_regular_price" }} + {{ if (discount_percentage <= '5') }} + (-{{ gaia:currency :price="discount_amount" }}) + {{ else }} + (-{{ discount_percentage | floor }}%) + {{ /if }} +
+ {{ /else }} + {{ gaia:currency :price="min_price" }} + {{ /if }} + {{ /if }} + + {{ if {gaia:product:configurable} }} + From {{ gaia:currency :price="min_price" }} {{ /if }} - {{ /if }} + {{ /gaia:product:price }} +
- {{ if {gaia:product:configurable} }} - From {{ gaia:currency :price="min_price" }} - {{ /if }} - {{ /gaia:product:price }} + {{ if {gaia:product:configurable} }} + + + + + + From + + {{ /if }}
+ + diff --git a/stubs/resources/views/shop/product/default/index.antlers.html b/stubs/resources/views/shop/product/default/index.antlers.html index c942252..68d57e2 100644 --- a/stubs/resources/views/shop/product/default/index.antlers.html +++ b/stubs/resources/views/shop/product/default/index.antlers.html @@ -48,9 +48,9 @@

Alpine.store('product', { title: '{{ title }}', - price: '{{ gaia:product:price }}{{min_price}}{{ /gaia:product:price}}', - variants: JSON.parse(` {{ { collection:variants :product_slug:is="slug" :site="site" } | pluck_with_keys('option1', 'option2', 'option3', 'inventory_quantity', 'slug', 'price', 'image') | to_json }} `), - currentVariants: JSON.parse(` {{ { collection:variants :product_slug:is="slug" :site="site" } | pluck_with_keys('option1', 'option2', 'option3', 'inventory_quantity', 'slug', 'price', 'image') | to_json }} `), + priceTable: {}, + variants: JSON.parse(` {{ { collection:variants :product_slug:is="slug" :site="site" } | pluck_with_keys('option1', 'option2', 'option3', 'inventory_quantity', 'slug', 'price', 'compare_at_price', 'image') | to_json }} `), + currentVariants: JSON.parse(` {{ { collection:variants :product_slug:is="slug" :site="site" } | pluck_with_keys('option1', 'option2', 'option3', 'inventory_quantity', 'slug', 'price', 'compare_at_price', 'image') | to_json }} `), currentProduct: null, selectedOptions: null, stockStatus: 'inStock', @@ -91,39 +91,95 @@

0, inStock: variant.inventory_quantity > 0, - formattedPrice: gaia.formatPrice(variant.price), productId: '{{ product_id }}' } }, + updateDisplayedPrice() { - if (this.variants.length === 1) { - this.price = this.currentProduct.formattedPrice; - return; + const formatPrice = (price) => { + if (price === null || price === undefined) { + return false; + } + + return gaia.formatPrice(parseFloat(price), '{{ site:locale }}', '{{ gaia:site_currency }}'); } - function calculateMinMaxPrices(variants) { - return variants.reduce((acc, variant) => { + const calculateMinMaxPrices = () => { + return this.currentVariants.reduce((acc, variant) => { return { - smallestPrice: Math.min(acc.smallestPrice, variant.price), - largestPrice: Math.max(acc.largestPrice, variant.price) + smallestPrice: Math.min(acc.smallestPrice, variant.price), + largestPrice: Math.max(acc.largestPrice, variant.price) }; }, { smallestPrice: Infinity, largestPrice: -Infinity }); } - const { smallestPrice, largestPrice } = calculateMinMaxPrices(this.currentVariants); + const minPrice = () => { + if (this.areAllOptionsSelected) { + return this.currentProduct.compare_at_price || this.currentProduct.price; + } - if (smallestPrice === Infinity || largestPrice === Infinity) { - let { smallestPrice, largestPrice } = calculateMinMaxPrices(this.variants); - this.price = `${gaia.formatPrice(smallestPrice)} - ${gaia.formatPrice(largestPrice)}`; - return; + const { smallestPrice, largestPrice } = calculateMinMaxPrices(); + + return smallestPrice; } - if (smallestPrice === largestPrice) { - this.price = gaia.formatPrice(largestPrice); - return; + const maxPrice = () => { + if (this.areAllOptionsSelected) { + return this.currentProduct.price; + } + + const { smallestPrice, largestPrice } = calculateMinMaxPrices(); + + return largestPrice; } - this.price = `${gaia.formatPrice(smallestPrice)} - ${gaia.formatPrice(largestPrice)}`; + const compareAtPrice = () => { + // If the product doesn't exist yet, return false + if (! this.currentProduct) { + return false; + } + + return this.currentProduct.compare_at_price + } + + const discountAmount = () => { + // If the product doesn't exist yet, return false + if (! this.currentProduct) { + return false; + } + + if (! this.currentProduct.compare_at_price) { + return false; + } + + return this.currentProduct.price - this.currentProduct.compare_at_price; + } + + const discountPercentage = () => { + // If the product doesn't exist yet, return false + if (! this.currentProduct) { + return false; + } + + // If the product doesn't have a compare at price, it's + // not discounted so return false + if (! this.currentProduct.compare_at_price) { + return false; + } + + return Math.floor((discountAmount() / this.currentProduct.price) * 100); + } + + this.priceTable = { + minPrice: minPrice(), + formattedMinPrice: formatPrice(minPrice()), + maxPrice: maxPrice(), + formattedMaxPrice: formatPrice(maxPrice()), + isDiscounted: discountAmount() ? true : false, + discountPercentage: discountPercentage(), + discountAmount: discountAmount(), + formattedDiscountAmount: formatPrice(discountAmount()), + } }, updateCurrentVariants() { if (!this.selectedOptions) { @@ -197,6 +253,10 @@

Date: Sat, 3 May 2025 16:37:16 +0100 Subject: [PATCH 4/4] Pint --- src/Tags/Gaia.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Tags/Gaia.php b/src/Tags/Gaia.php index b324ca6..3710a9e 100644 --- a/src/Tags/Gaia.php +++ b/src/Tags/Gaia.php @@ -57,14 +57,14 @@ public function id() { return Str::lower(Str::random(10)); } - + /** * Retrieves the current site's currency. * - * @return string The currency code for the current site. + * @return string The currency code for the current site. * If not set, returns the default currency from configuration. */ - public function siteCurrency(): string + public function siteCurrency(): string { return Site::current()->attribute('currency') ?? config('gaia.default_currency'); }