diff --git a/docs/plugins/index.md b/docs/plugins/index.md index 9308aab00..096145217 100644 --- a/docs/plugins/index.md +++ b/docs/plugins/index.md @@ -26,3 +26,24 @@ client and server side. ![i18n flow](./i18n-plugin-diagram.png) + +## Currency + +We expose `$fc` (format currency) function as a plugin to allow you to convert any number or string into a formatted currency string. Under the hood plugins uses Intl.NumberFormat class to handle formatting and therefore exposes the same options configuration. +Here are few examples of how you can use it in templates. +```javascript +$fc(productGetters.getPrice(product).regular) // by default vsf-currency cookie is used to define target currency +$fc(productGetters.getPrice(product).regular, { currency: 'USD' }) // you can easily override this behaviour by passing configuration object +``` + +Configuration object is an interface Intl.NumberFormatOptions, check it for all available options. + +--- +***NOTE*** + +Why we are not using built-in i18n package currency configuration and $n function to cover currency displaying? The answer is because we must be able to handle multiple currencies within one store but in i18n package, currency and locale are in 1:1 relation when in Magento one store can have multiple languages and currencies set. Currency and locale are necessarily disjointed which is not true for i18n plugin. + +You can still use all i18n native functions to perform any formatting though. + +--- + diff --git a/packages/theme/components/CartSidebar.vue b/packages/theme/components/CartSidebar.vue index 8f855e858..511069ca4 100644 --- a/packages/theme/components/CartSidebar.vue +++ b/packages/theme/components/CartSidebar.vue @@ -97,12 +97,12 @@ :image="cartGetters.getItemImage(product)" :title="cartGetters.getItemName(product)" :regular-price=" - $n(cartGetters.getItemPrice(product).regular, 'currency') + $fc(cartGetters.getItemPrice(product).regular) " :special-price=" cartGetters.productHasSpecialPrice(product) ? getItemPrice(product).special && - $n(cartGetters.getItemPrice(product).special, 'currency') + $fc(cartGetters.getItemPrice(product).special) : '' " :link=" @@ -196,11 +196,11 @@ > diff --git a/packages/theme/components/Checkout/CartPreview.vue b/packages/theme/components/Checkout/CartPreview.vue index f1a37f301..7dc34de8c 100644 --- a/packages/theme/components/Checkout/CartPreview.vue +++ b/packages/theme/components/Checkout/CartPreview.vue @@ -15,24 +15,25 @@ /> + diff --git a/packages/theme/components/Checkout/VsfShippingProvider.vue b/packages/theme/components/Checkout/VsfShippingProvider.vue index 39da57609..67ed99527 100644 --- a/packages/theme/components/Checkout/VsfShippingProvider.vue +++ b/packages/theme/components/Checkout/VsfShippingProvider.vue @@ -49,7 +49,7 @@
{{ method.carrier_title }}
- {{ $n(getShippingMethodPrice(method), 'currency') }} + {{ $fc(getShippingMethodPrice(method)) }}
diff --git a/packages/theme/components/Products/BundleProductSelector.vue b/packages/theme/components/Products/BundleProductSelector.vue index d6f716677..763fa2014 100644 --- a/packages/theme/components/Products/BundleProductSelector.vue +++ b/packages/theme/components/Products/BundleProductSelector.vue @@ -26,8 +26,8 @@ > {{ productGetters.getName(option.product) }}
diff --git a/packages/theme/helpers/__tests__/formatCurrency.spec.js b/packages/theme/helpers/__tests__/formatCurrency.spec.js new file mode 100644 index 000000000..2e0bfe2a2 --- /dev/null +++ b/packages/theme/helpers/__tests__/formatCurrency.spec.js @@ -0,0 +1,16 @@ +import formatCurrency from '~/helpers/formatCurrency'; + +describe('formatCurrency()', () => { + it('executed without required options should throw error', () => { + expect(() => { formatCurrency(100, 'en-US', {}); }).toThrowError(); + }); + + it('should return formatted currency string', () => { + const currency = 'EUR'; + jest.spyOn(Intl, 'NumberFormat').mockImplementation(() => ({ + format: (value) => `${value}${currency}`, + })); + const result = formatCurrency(123, 'de-DE', { currency }); + expect(result).toBe('123EUR'); + }); +}); diff --git a/packages/theme/helpers/formatCurrency.ts b/packages/theme/helpers/formatCurrency.ts new file mode 100644 index 000000000..65cbc24bd --- /dev/null +++ b/packages/theme/helpers/formatCurrency.ts @@ -0,0 +1,11 @@ +const formatCurrency = (value: number | string, locale: string, options: Intl.NumberFormatOptions): string => { + if (typeof value === 'string') { + // eslint-disable-next-line no-param-reassign + value = Number(value); + } + // eslint-disable-next-line no-param-reassign + + return new Intl.NumberFormat(locale, { style: 'currency', ...options }).format(value); +}; + +export default formatCurrency; diff --git a/packages/theme/nuxt.config.js b/packages/theme/nuxt.config.js index c9f0ad01c..08415c02f 100755 --- a/packages/theme/nuxt.config.js +++ b/packages/theme/nuxt.config.js @@ -230,6 +230,7 @@ export default { plugins: [ '~/plugins/token-expired', '~/plugins/i18n', + '~/plugins/fcPlugin', ], router: { extendRoutes(routes) { diff --git a/packages/theme/pages/Category.vue b/packages/theme/pages/Category.vue index 22bafada6..2dd407ccd 100644 --- a/packages/theme/pages/Category.vue +++ b/packages/theme/pages/Category.vue @@ -123,8 +123,8 @@ :style="{ '--index': i }" :title="productGetters.getName(product)" :image="productGetters.getProductThumbnailImage(product)" - :regular-price="$n(productGetters.getPrice(product).regular, 'currency')" - :special-price="productGetters.getPrice(product).special && $n(productGetters.getPrice(product).special, 'currency')" + :regular-price="$fc(productGetters.getPrice(product).regular)" + :special-price="productGetters.getPrice(product).special && $fc(productGetters.getPrice(product).special)" :score-rating="productGetters.getAverageRating(product)" :reviews-count="productGetters.getTotalReviews(product)" :show-add-to-cart-button="true" @@ -158,8 +158,8 @@ :title="productGetters.getName(product)" :description="productGetters.getDescription(product)" :image="productGetters.getProductThumbnailImage(product)" - :regular-price="$n(productGetters.getPrice(product).regular, 'currency')" - :special-price="productGetters.getPrice(product).special && $n(productGetters.getPrice(product).special, 'currency')" + :regular-price="$fc(productGetters.getPrice(product).regular)" + :special-price="productGetters.getPrice(product).special && $fc(productGetters.getPrice(product).special)" :score-rating="productGetters.getAverageRating(product)" :reviews-count="productGetters.getTotalReviews(product)" :is-in-wishlist="isInWishlist({product})" diff --git a/packages/theme/pages/Checkout/Payment.vue b/packages/theme/pages/Checkout/Payment.vue index 52e7a6c34..c7ed39b48 100644 --- a/packages/theme/pages/Checkout/Payment.vue +++ b/packages/theme/pages/Checkout/Payment.vue @@ -65,8 +65,8 @@ @@ -77,13 +77,13 @@
@@ -92,7 +92,7 @@ class="summary__total" >