Extensibility: Format currency config so it can be consumed more easily (#48727)
* Export pre-formatted SITE_CURRENCY object from settings * Fallback to SITE_CURRENCY * Changelog * Fix typedef * Update mocks * Inject site currency into cart preview data * Update test * Add currency formatting to preview data * Mock currency in tests * More currency mocking
This commit is contained in:
parent
b9d6439b9d
commit
e0c62dce79
|
@ -46,6 +46,19 @@ const defaultUseStoreCartValue = {
|
|||
cartHasCalculatedShipping: mockPreviewCart.has_calculated_shipping,
|
||||
};
|
||||
|
||||
jest.mock( '@woocommerce/settings', () => ( {
|
||||
...jest.requireActual( '@woocommerce/settings' ),
|
||||
SITE_CURRENCY: {
|
||||
code: 'USD',
|
||||
symbol: '$',
|
||||
thousandSeparator: ',',
|
||||
decimalSeparator: '.',
|
||||
minorUnit: 2,
|
||||
prefix: '$',
|
||||
suffix: '',
|
||||
},
|
||||
} ) );
|
||||
|
||||
jest.mock( '@woocommerce/base-context/hooks', () => ( {
|
||||
...jest.requireActual( '@woocommerce/base-context/hooks' ),
|
||||
|
||||
|
@ -182,6 +195,15 @@ jest.mock( '@woocommerce/settings', () => {
|
|||
|
||||
return {
|
||||
...originalModule,
|
||||
SITE_CURRENCY: {
|
||||
code: 'USD',
|
||||
symbol: '$',
|
||||
thousandSeparator: ',',
|
||||
decimalSeparator: '.',
|
||||
minorUnit: 2,
|
||||
prefix: '$',
|
||||
suffix: '',
|
||||
},
|
||||
getSetting: jest.fn().mockImplementation( ( setting, ...rest ) => {
|
||||
if ( setting === 'couponsEnabled' ) {
|
||||
return true;
|
||||
|
|
|
@ -10,6 +10,7 @@ import { getSetting } from '@woocommerce/settings';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { previewShippingRates } from './shipping-rates';
|
||||
import { API_SITE_CURRENCY, displayForMinorUnit } from './utils';
|
||||
|
||||
/**
|
||||
* Prices from the API may change because of this display setting. This makes the response use either
|
||||
|
@ -81,16 +82,16 @@ export const previewCart: CartResponse = {
|
|||
},
|
||||
],
|
||||
prices: {
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
price: displayWithTax ? '12000' : '10000',
|
||||
regular_price: displayWithTax ? '12000' : '10000',
|
||||
sale_price: displayWithTax ? '12000' : '10000',
|
||||
...API_SITE_CURRENCY,
|
||||
price: displayForMinorUnit(
|
||||
displayWithTax ? '12000' : '10000'
|
||||
),
|
||||
regular_price: displayForMinorUnit(
|
||||
displayWithTax ? '120' : '100'
|
||||
),
|
||||
sale_price: displayForMinorUnit(
|
||||
displayWithTax ? '12000' : '10000'
|
||||
),
|
||||
price_range: null,
|
||||
raw_prices: {
|
||||
precision: 6,
|
||||
|
@ -100,17 +101,11 @@ export const previewCart: CartResponse = {
|
|||
},
|
||||
},
|
||||
totals: {
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
line_subtotal: '2000',
|
||||
line_subtotal_tax: '400',
|
||||
line_total: '2000',
|
||||
line_total_tax: '400',
|
||||
...API_SITE_CURRENCY,
|
||||
line_subtotal: displayForMinorUnit( '2000' ),
|
||||
line_subtotal_tax: displayForMinorUnit( '400' ),
|
||||
line_total: displayForMinorUnit( '2000' ),
|
||||
line_total_tax: displayForMinorUnit( '400' ),
|
||||
},
|
||||
extensions: {},
|
||||
item_data: [],
|
||||
|
@ -156,16 +151,14 @@ export const previewCart: CartResponse = {
|
|||
},
|
||||
],
|
||||
prices: {
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
price: displayWithTax ? '2400' : '2000',
|
||||
regular_price: displayWithTax ? '2400' : '2000',
|
||||
sale_price: displayWithTax ? '2400' : '2000',
|
||||
...API_SITE_CURRENCY,
|
||||
price: displayForMinorUnit( displayWithTax ? '2400' : '2000' ),
|
||||
regular_price: displayForMinorUnit(
|
||||
displayWithTax ? '2400' : '2000'
|
||||
),
|
||||
sale_price: displayForMinorUnit(
|
||||
displayWithTax ? '2400' : '2000'
|
||||
),
|
||||
price_range: null,
|
||||
raw_prices: {
|
||||
precision: 6,
|
||||
|
@ -175,17 +168,11 @@ export const previewCart: CartResponse = {
|
|||
},
|
||||
},
|
||||
totals: {
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
line_subtotal: '2000',
|
||||
line_subtotal_tax: '400',
|
||||
line_total: '2000',
|
||||
line_total_tax: '400',
|
||||
...API_SITE_CURRENCY,
|
||||
line_subtotal: displayForMinorUnit( '2000' ),
|
||||
line_subtotal_tax: displayForMinorUnit( '400' ),
|
||||
line_total: displayForMinorUnit( '2000' ),
|
||||
line_total_tax: displayForMinorUnit( '400' ),
|
||||
},
|
||||
extensions: {},
|
||||
item_data: [],
|
||||
|
@ -195,6 +182,7 @@ export const previewCart: CartResponse = {
|
|||
{
|
||||
id: 1,
|
||||
name: __( 'Polo', 'woocommerce' ),
|
||||
slug: 'polo',
|
||||
parent: 0,
|
||||
type: 'simple',
|
||||
variation: '',
|
||||
|
@ -204,16 +192,16 @@ export const previewCart: CartResponse = {
|
|||
description: __( 'Polo', 'woocommerce' ),
|
||||
on_sale: false,
|
||||
prices: {
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
price: displayWithTax ? '24000' : '20000',
|
||||
regular_price: displayWithTax ? '24000' : '20000',
|
||||
sale_price: displayWithTax ? '12000' : '10000',
|
||||
...API_SITE_CURRENCY,
|
||||
price: displayForMinorUnit(
|
||||
displayWithTax ? '24000' : '20000'
|
||||
),
|
||||
regular_price: displayForMinorUnit(
|
||||
displayWithTax ? '24000' : '20000'
|
||||
),
|
||||
sale_price: displayForMinorUnit(
|
||||
displayWithTax ? '12000' : '10000'
|
||||
),
|
||||
price_range: null,
|
||||
},
|
||||
price_html: '',
|
||||
|
@ -252,6 +240,7 @@ export const previewCart: CartResponse = {
|
|||
{
|
||||
id: 2,
|
||||
name: __( 'Long Sleeve Tee', 'woocommerce' ),
|
||||
slug: 'long-sleeve-tee',
|
||||
parent: 0,
|
||||
type: 'simple',
|
||||
variation: '',
|
||||
|
@ -261,16 +250,16 @@ export const previewCart: CartResponse = {
|
|||
description: __( 'Long Sleeve Tee', 'woocommerce' ),
|
||||
on_sale: false,
|
||||
prices: {
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
price: displayWithTax ? '30000' : '25000',
|
||||
regular_price: displayWithTax ? '30000' : '25000',
|
||||
sale_price: displayWithTax ? '30000' : '25000',
|
||||
...API_SITE_CURRENCY,
|
||||
price: displayForMinorUnit(
|
||||
displayWithTax ? '30000' : '25000'
|
||||
),
|
||||
regular_price: displayForMinorUnit(
|
||||
displayWithTax ? '30000' : '25000'
|
||||
),
|
||||
sale_price: displayForMinorUnit(
|
||||
displayWithTax ? '30000' : '25000'
|
||||
),
|
||||
price_range: null,
|
||||
},
|
||||
price_html: '',
|
||||
|
@ -310,6 +299,7 @@ export const previewCart: CartResponse = {
|
|||
{
|
||||
id: 3,
|
||||
name: __( 'Hoodie with Zipper', 'woocommerce' ),
|
||||
slug: 'hoodie-with-zipper',
|
||||
parent: 0,
|
||||
type: 'simple',
|
||||
variation: '',
|
||||
|
@ -319,16 +309,16 @@ export const previewCart: CartResponse = {
|
|||
description: __( 'Hoodie with Zipper', 'woocommerce' ),
|
||||
on_sale: true,
|
||||
prices: {
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
price: displayWithTax ? '15000' : '12500',
|
||||
regular_price: displayWithTax ? '30000' : '25000',
|
||||
sale_price: displayWithTax ? '15000' : '12500',
|
||||
...API_SITE_CURRENCY,
|
||||
price: displayForMinorUnit(
|
||||
displayWithTax ? '15000' : '12500'
|
||||
),
|
||||
regular_price: displayForMinorUnit(
|
||||
displayWithTax ? '30000' : '25000'
|
||||
),
|
||||
sale_price: displayForMinorUnit(
|
||||
displayWithTax ? '15000' : '12500'
|
||||
),
|
||||
price_range: null,
|
||||
},
|
||||
price_html: '',
|
||||
|
@ -369,6 +359,7 @@ export const previewCart: CartResponse = {
|
|||
{
|
||||
id: 4,
|
||||
name: __( 'Hoodie with Logo', 'woocommerce' ),
|
||||
slug: 'hoodie-with-logo',
|
||||
parent: 0,
|
||||
type: 'simple',
|
||||
variation: '',
|
||||
|
@ -378,16 +369,14 @@ export const previewCart: CartResponse = {
|
|||
description: __( 'Polo', 'woocommerce' ),
|
||||
on_sale: false,
|
||||
prices: {
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
price: displayWithTax ? '4500' : '4250',
|
||||
regular_price: displayWithTax ? '4500' : '4250',
|
||||
sale_price: displayWithTax ? '4500' : '4250',
|
||||
...API_SITE_CURRENCY,
|
||||
price: displayForMinorUnit( displayWithTax ? '4500' : '4250' ),
|
||||
regular_price: displayForMinorUnit(
|
||||
displayWithTax ? '4500' : '4250'
|
||||
),
|
||||
sale_price: displayForMinorUnit(
|
||||
displayWithTax ? '4500' : '4250'
|
||||
),
|
||||
price_range: null,
|
||||
},
|
||||
price_html: '',
|
||||
|
@ -427,6 +416,7 @@ export const previewCart: CartResponse = {
|
|||
{
|
||||
id: 5,
|
||||
name: __( 'Hoodie with Pocket', 'woocommerce' ),
|
||||
slug: 'hoodie-with-pocket',
|
||||
parent: 0,
|
||||
type: 'simple',
|
||||
variation: '',
|
||||
|
@ -436,16 +426,14 @@ export const previewCart: CartResponse = {
|
|||
description: __( 'Hoodie with Pocket', 'woocommerce' ),
|
||||
on_sale: true,
|
||||
prices: {
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
price: displayWithTax ? '3500' : '3250',
|
||||
regular_price: displayWithTax ? '4500' : '4250',
|
||||
sale_price: displayWithTax ? '3500' : '3250',
|
||||
...API_SITE_CURRENCY,
|
||||
price: displayForMinorUnit( displayWithTax ? '3500' : '3250' ),
|
||||
regular_price: displayForMinorUnit(
|
||||
displayWithTax ? '4500' : '4250'
|
||||
),
|
||||
sale_price: displayForMinorUnit(
|
||||
displayWithTax ? '3500' : '3250'
|
||||
),
|
||||
price_range: null,
|
||||
},
|
||||
price_html: '',
|
||||
|
@ -486,6 +474,7 @@ export const previewCart: CartResponse = {
|
|||
{
|
||||
id: 6,
|
||||
name: __( 'T-Shirt', 'woocommerce' ),
|
||||
slug: 't-shirt',
|
||||
parent: 0,
|
||||
type: 'simple',
|
||||
variation: '',
|
||||
|
@ -495,16 +484,14 @@ export const previewCart: CartResponse = {
|
|||
description: __( 'T-Shirt', 'woocommerce' ),
|
||||
on_sale: false,
|
||||
prices: {
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
price: displayWithTax ? '1800' : '1500',
|
||||
regular_price: displayWithTax ? '1800' : '1500',
|
||||
sale_price: displayWithTax ? '1800' : '1500',
|
||||
...API_SITE_CURRENCY,
|
||||
price: displayForMinorUnit( displayWithTax ? '1800' : '1500' ),
|
||||
regular_price: displayForMinorUnit(
|
||||
displayWithTax ? '1800' : '1500'
|
||||
),
|
||||
sale_price: displayForMinorUnit(
|
||||
displayWithTax ? '1800' : '1500'
|
||||
),
|
||||
price_range: null,
|
||||
},
|
||||
price_html: '',
|
||||
|
@ -546,15 +533,9 @@ export const previewCart: CartResponse = {
|
|||
id: 'fee',
|
||||
name: __( 'Fee', 'woocommerce' ),
|
||||
totals: {
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
total: '100',
|
||||
total_tax: '20',
|
||||
...API_SITE_CURRENCY,
|
||||
total: displayForMinorUnit( '100' ),
|
||||
total_tax: displayForMinorUnit( '20' ),
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -589,28 +570,22 @@ export const previewCart: CartResponse = {
|
|||
phone: '',
|
||||
},
|
||||
totals: {
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
total_items: '4000',
|
||||
total_items_tax: '800',
|
||||
total_fees: '100',
|
||||
total_fees_tax: '20',
|
||||
...API_SITE_CURRENCY,
|
||||
total_items: displayForMinorUnit( '4000' ),
|
||||
total_items_tax: displayForMinorUnit( '800' ),
|
||||
total_fees: displayForMinorUnit( '100' ),
|
||||
total_fees_tax: displayForMinorUnit( '20' ),
|
||||
total_discount: '0',
|
||||
total_discount_tax: '0',
|
||||
total_shipping: '0',
|
||||
total_shipping_tax: '0',
|
||||
total_tax: '820',
|
||||
total_price: '4920',
|
||||
total_tax: displayForMinorUnit( '820' ),
|
||||
total_price: displayForMinorUnit( '4920' ),
|
||||
tax_lines: [
|
||||
{
|
||||
name: __( 'Sales tax', 'woocommerce' ),
|
||||
rate: '20%',
|
||||
price: '820',
|
||||
price: displayForMinorUnit( '820' ),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
import { __, _x } from '@wordpress/i18n';
|
||||
import type { CartResponseShippingRate } from '@woocommerce/types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { API_SITE_CURRENCY, displayForMinorUnit } from './utils';
|
||||
|
||||
export const previewShippingRates: CartResponseShippingRate[] = [
|
||||
{
|
||||
destination: {
|
||||
|
@ -38,32 +43,20 @@ export const previewShippingRates: CartResponseShippingRate[] = [
|
|||
],
|
||||
shipping_rates: [
|
||||
{
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
...API_SITE_CURRENCY,
|
||||
name: __( 'Flat rate shipping', 'woocommerce' ),
|
||||
description: '',
|
||||
delivery_time: '',
|
||||
price: '500',
|
||||
price: displayForMinorUnit( '500' ),
|
||||
taxes: '0',
|
||||
rate_id: 'flat_rate:0',
|
||||
instance_id: 0,
|
||||
meta_data: [],
|
||||
method_id: 'flat_rate',
|
||||
selected: true,
|
||||
selected: false,
|
||||
},
|
||||
{
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
...API_SITE_CURRENCY,
|
||||
name: __( 'Free shipping', 'woocommerce' ),
|
||||
description: '',
|
||||
delivery_time: '',
|
||||
|
@ -73,16 +66,10 @@ export const previewShippingRates: CartResponseShippingRate[] = [
|
|||
instance_id: 0,
|
||||
meta_data: [],
|
||||
method_id: 'flat_rate',
|
||||
selected: false,
|
||||
selected: true,
|
||||
},
|
||||
{
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
...API_SITE_CURRENCY,
|
||||
name: __( 'Local pickup', 'woocommerce' ),
|
||||
description: '',
|
||||
delivery_time: '',
|
||||
|
@ -104,13 +91,7 @@ export const previewShippingRates: CartResponseShippingRate[] = [
|
|||
selected: false,
|
||||
},
|
||||
{
|
||||
currency_code: 'USD',
|
||||
currency_symbol: '$',
|
||||
currency_minor_unit: 2,
|
||||
currency_decimal_separator: '.',
|
||||
currency_thousand_separator: ',',
|
||||
currency_prefix: '$',
|
||||
currency_suffix: '',
|
||||
...API_SITE_CURRENCY,
|
||||
name: __( 'Local pickup', 'woocommerce' ),
|
||||
description: '',
|
||||
delivery_time: '',
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { SITE_CURRENCY } from '@woocommerce/settings';
|
||||
|
||||
/**
|
||||
* Put site currency back in API format for the responses.
|
||||
*/
|
||||
export const API_SITE_CURRENCY = {
|
||||
currency_code: SITE_CURRENCY.code,
|
||||
currency_symbol: SITE_CURRENCY.symbol,
|
||||
currency_minor_unit: SITE_CURRENCY.minorUnit,
|
||||
currency_decimal_separator: SITE_CURRENCY.decimalSeparator,
|
||||
currency_thousand_separator: SITE_CURRENCY.thousandSeparator,
|
||||
currency_prefix: SITE_CURRENCY.prefix,
|
||||
currency_suffix: SITE_CURRENCY.suffix,
|
||||
};
|
||||
|
||||
/**
|
||||
* Preview data is defined with 2dp. This converts to selected currency settings.
|
||||
*/
|
||||
export const displayForMinorUnit = ( value: string ): string => {
|
||||
const minorUnit = SITE_CURRENCY.minorUnit;
|
||||
|
||||
// Preview data is defined with 2 dp.
|
||||
if ( minorUnit === 2 ) {
|
||||
return value;
|
||||
}
|
||||
|
||||
const multiplier = Math.pow( 10, minorUnit );
|
||||
const intValue = Math.round( parseInt( value, 10 ) / Math.pow( 10, 2 ) );
|
||||
|
||||
return ( intValue * multiplier ).toString();
|
||||
};
|
|
@ -1,14 +1,19 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import type { Currency, SymbolPosition } from '@woocommerce/types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { allSettings } from './settings-init';
|
||||
import { getCurrencyPrefix, getCurrencySuffix } from './utils';
|
||||
|
||||
/**
|
||||
* This exports all default core settings as constants.
|
||||
*/
|
||||
export const ADMIN_URL = allSettings.adminUrl;
|
||||
export const COUNTRIES = allSettings.countries;
|
||||
export const CURRENCY = allSettings.currency;
|
||||
export const CURRENT_USER_IS_ADMIN = allSettings.currentUserIsAdmin as boolean;
|
||||
export const HOME_URL = allSettings.homeUrl as string | undefined;
|
||||
export const LOCALE = allSettings.locale;
|
||||
|
@ -27,3 +32,22 @@ export const WC_ASSET_URL = allSettings.wcAssetUrl;
|
|||
export const WC_VERSION = allSettings.wcVersion;
|
||||
export const WP_LOGIN_URL = allSettings.wpLoginUrl;
|
||||
export const WP_VERSION = allSettings.wpVersion;
|
||||
|
||||
// Settings from the server in WooCommerceSiteCurrency format.
|
||||
export const CURRENCY = allSettings.currency;
|
||||
// Convert WooCommerceSiteCurrency format to Currency format.
|
||||
export const SITE_CURRENCY: Currency = {
|
||||
code: CURRENCY.code,
|
||||
symbol: CURRENCY.symbol,
|
||||
thousandSeparator: CURRENCY.thousandSeparator,
|
||||
decimalSeparator: CURRENCY.decimalSeparator,
|
||||
minorUnit: CURRENCY.precision,
|
||||
prefix: getCurrencyPrefix(
|
||||
CURRENCY.symbol,
|
||||
CURRENCY.symbolPosition as SymbolPosition
|
||||
),
|
||||
suffix: getCurrencySuffix(
|
||||
CURRENCY.symbol,
|
||||
CURRENCY.symbolPosition as SymbolPosition
|
||||
),
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import compareVersions from 'compare-versions';
|
||||
import type { SymbolPosition } from '@woocommerce/types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -138,3 +139,35 @@ export const getPaymentMethodData = (
|
|||
>;
|
||||
return paymentMethodData[ paymentMethodId ] ?? defaultValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get currency prefix.
|
||||
*/
|
||||
export const getCurrencyPrefix = (
|
||||
symbol: string,
|
||||
symbolPosition: SymbolPosition
|
||||
): string => {
|
||||
const prefixes = {
|
||||
left: symbol,
|
||||
left_space: symbol + ' ',
|
||||
right: '',
|
||||
right_space: '',
|
||||
};
|
||||
return prefixes[ symbolPosition ] || '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Get currency suffix.
|
||||
*/
|
||||
export const getCurrencySuffix = (
|
||||
symbol: string,
|
||||
symbolPosition: SymbolPosition
|
||||
): string => {
|
||||
const suffixes = {
|
||||
left: '',
|
||||
left_space: '',
|
||||
right: symbol,
|
||||
right_space: ' ' + symbol,
|
||||
};
|
||||
return suffixes[ symbolPosition ] || '';
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@ import type {
|
|||
import clsx from 'clsx';
|
||||
import type { ReactElement } from 'react';
|
||||
import type { Currency } from '@woocommerce/types';
|
||||
import { SITE_CURRENCY } from '@woocommerce/settings';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -22,7 +23,7 @@ export interface FormattedMonetaryAmountProps
|
|||
allowNegative?: boolean;
|
||||
isAllowed?: ( formattedValue: NumberFormatValues ) => boolean;
|
||||
value: number | string; // Value of money amount.
|
||||
currency: Currency | Record< string, never >; // Currency configuration object.
|
||||
currency?: Currency | undefined; // Currency configuration object. Defaults to site currency.
|
||||
onValueChange?: ( unit: number ) => void; // Function to call when value changes.
|
||||
style?: React.CSSProperties | undefined;
|
||||
renderText?: ( value: string ) => JSX.Element;
|
||||
|
@ -31,36 +32,25 @@ export interface FormattedMonetaryAmountProps
|
|||
/**
|
||||
* Formats currency data into the expected format for NumberFormat.
|
||||
*/
|
||||
const currencyToNumberFormat = (
|
||||
currency: FormattedMonetaryAmountProps[ 'currency' ]
|
||||
) => {
|
||||
const hasSimiliarSeparators =
|
||||
currency?.thousandSeparator === currency?.decimalSeparator;
|
||||
if ( hasSimiliarSeparators ) {
|
||||
const currencyToNumberFormat = ( currency: Currency ) => {
|
||||
const { prefix, suffix, thousandSeparator, decimalSeparator } = currency;
|
||||
const hasDuplicateSeparator = thousandSeparator === decimalSeparator;
|
||||
if ( hasDuplicateSeparator ) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
'Thousand separator and decimal separator are the same. This may cause formatting issues.'
|
||||
);
|
||||
}
|
||||
return {
|
||||
thousandSeparator: hasSimiliarSeparators
|
||||
? ''
|
||||
: currency?.thousandSeparator,
|
||||
decimalSeparator: currency?.decimalSeparator,
|
||||
thousandSeparator: hasDuplicateSeparator ? '' : thousandSeparator,
|
||||
decimalSeparator,
|
||||
fixedDecimalScale: true,
|
||||
prefix: currency?.prefix,
|
||||
suffix: currency?.suffix,
|
||||
prefix,
|
||||
suffix,
|
||||
isNumericString: true,
|
||||
};
|
||||
};
|
||||
|
||||
type CustomFormattedMonetaryAmountProps = Omit<
|
||||
FormattedMonetaryAmountProps,
|
||||
'currency'
|
||||
> & {
|
||||
currency: Currency | Record< string, never >;
|
||||
};
|
||||
|
||||
/**
|
||||
* FormattedMonetaryAmount component.
|
||||
*
|
||||
|
@ -71,11 +61,18 @@ type CustomFormattedMonetaryAmountProps = Omit<
|
|||
const FormattedMonetaryAmount = ( {
|
||||
className,
|
||||
value: rawValue,
|
||||
currency,
|
||||
currency: rawCurrency = SITE_CURRENCY,
|
||||
onValueChange,
|
||||
displayType = 'text',
|
||||
...props
|
||||
}: CustomFormattedMonetaryAmountProps ): ReactElement | null => {
|
||||
}: FormattedMonetaryAmountProps ): ReactElement | null => {
|
||||
// Merge currency configuration with site currency.
|
||||
const currency = {
|
||||
...SITE_CURRENCY,
|
||||
...rawCurrency,
|
||||
};
|
||||
|
||||
// Convert values to int.
|
||||
const value =
|
||||
typeof rawValue === 'string' ? parseInt( rawValue, 10 ) : rawValue;
|
||||
|
||||
|
|
|
@ -8,8 +8,27 @@ import { render, screen } from '@testing-library/react';
|
|||
*/
|
||||
import FormattedMonetaryAmount from '../index';
|
||||
|
||||
jest.mock( '@woocommerce/settings', () => ( {
|
||||
...jest.requireActual( '@woocommerce/settings' ),
|
||||
SITE_CURRENCY: {
|
||||
code: 'EUR',
|
||||
symbol: 'TEST',
|
||||
thousandSeparator: '.',
|
||||
decimalSeparator: ',',
|
||||
minorUnit: 2,
|
||||
prefix: '',
|
||||
suffix: ' TEST',
|
||||
},
|
||||
} ) );
|
||||
|
||||
describe( 'FormattedMonetaryAmount', () => {
|
||||
describe( 'separators', () => {
|
||||
test( 'should default to store currency configuration', () => {
|
||||
render( <FormattedMonetaryAmount value="156345" /> );
|
||||
|
||||
expect( screen.getByText( '1.563,45 TEST' ) ).toBeInTheDocument();
|
||||
} );
|
||||
|
||||
test( 'should add the thousand separator', () => {
|
||||
render(
|
||||
<FormattedMonetaryAmount
|
||||
|
@ -37,6 +56,7 @@ describe( 'FormattedMonetaryAmount', () => {
|
|||
code: 'EUR',
|
||||
symbol: '€',
|
||||
decimalSeparator: ',',
|
||||
thousandSeparator: '',
|
||||
minorUnit: 2,
|
||||
prefix: '',
|
||||
suffix: ' €',
|
||||
|
@ -76,6 +96,7 @@ describe( 'FormattedMonetaryAmount', () => {
|
|||
thousandSeparator: '.',
|
||||
decimalSeparator: ',',
|
||||
minorUnit: 2,
|
||||
prefix: '',
|
||||
suffix: ' €',
|
||||
} }
|
||||
/>
|
||||
|
@ -94,6 +115,7 @@ describe( 'FormattedMonetaryAmount', () => {
|
|||
decimalSeparator: ',',
|
||||
minorUnit: 2,
|
||||
prefix: '€ ',
|
||||
suffix: '',
|
||||
} }
|
||||
/>
|
||||
);
|
||||
|
@ -112,6 +134,7 @@ describe( 'FormattedMonetaryAmount', () => {
|
|||
thousandSeparator: '.',
|
||||
decimalSeparator: ',',
|
||||
minorUnit: 0,
|
||||
prefix: '',
|
||||
suffix: ' €',
|
||||
} }
|
||||
/>
|
||||
|
@ -130,6 +153,7 @@ describe( 'FormattedMonetaryAmount', () => {
|
|||
decimalSeparator: ',',
|
||||
minorUnit: 0,
|
||||
prefix: '€ ',
|
||||
suffix: '',
|
||||
} }
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -1,69 +1,13 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { CURRENCY } from '@woocommerce/settings';
|
||||
import { SITE_CURRENCY } from '@woocommerce/settings';
|
||||
import type {
|
||||
Currency,
|
||||
CurrencyResponse,
|
||||
CartShippingPackageShippingRate,
|
||||
SymbolPosition,
|
||||
} from '@woocommerce/types';
|
||||
|
||||
/**
|
||||
* Get currency prefix.
|
||||
*/
|
||||
const getPrefix = (
|
||||
// Currency symbol.
|
||||
symbol: string,
|
||||
// Position of currency symbol from settings.
|
||||
symbolPosition: SymbolPosition
|
||||
): string => {
|
||||
const prefixes = {
|
||||
left: symbol,
|
||||
left_space: ' ' + symbol,
|
||||
right: '',
|
||||
right_space: '',
|
||||
};
|
||||
return prefixes[ symbolPosition ] || '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Get currency suffix.
|
||||
*/
|
||||
const getSuffix = (
|
||||
// Currency symbol.
|
||||
symbol: string,
|
||||
// Position of currency symbol from settings.
|
||||
symbolPosition: SymbolPosition
|
||||
): string => {
|
||||
const suffixes = {
|
||||
left: '',
|
||||
left_space: '',
|
||||
right: symbol,
|
||||
right_space: ' ' + symbol,
|
||||
};
|
||||
return suffixes[ symbolPosition ] || '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Currency information in normalized format from server settings.
|
||||
*/
|
||||
const siteCurrencySettings: Currency = {
|
||||
code: CURRENCY.code,
|
||||
symbol: CURRENCY.symbol,
|
||||
thousandSeparator: CURRENCY.thousandSeparator,
|
||||
decimalSeparator: CURRENCY.decimalSeparator,
|
||||
minorUnit: CURRENCY.precision,
|
||||
prefix: getPrefix(
|
||||
CURRENCY.symbol,
|
||||
CURRENCY.symbolPosition as SymbolPosition
|
||||
),
|
||||
suffix: getSuffix(
|
||||
CURRENCY.symbol,
|
||||
CURRENCY.symbolPosition as SymbolPosition
|
||||
),
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets currency information in normalized format from an API response or the server.
|
||||
*
|
||||
|
@ -77,7 +21,7 @@ export const getCurrencyFromPriceResponse = (
|
|||
| CartShippingPackageShippingRate
|
||||
): Currency => {
|
||||
if ( ! currencyData?.currency_code ) {
|
||||
return siteCurrencySettings;
|
||||
return SITE_CURRENCY;
|
||||
}
|
||||
|
||||
const {
|
||||
|
@ -91,15 +35,21 @@ export const getCurrencyFromPriceResponse = (
|
|||
} = currencyData;
|
||||
|
||||
return {
|
||||
code: code || 'USD',
|
||||
symbol: symbol || '$',
|
||||
code: code || SITE_CURRENCY.code,
|
||||
symbol: symbol || SITE_CURRENCY.symbol,
|
||||
thousandSeparator:
|
||||
typeof thousandSeparator === 'string' ? thousandSeparator : ',',
|
||||
typeof thousandSeparator === 'string'
|
||||
? thousandSeparator
|
||||
: SITE_CURRENCY.thousandSeparator,
|
||||
decimalSeparator:
|
||||
typeof decimalSeparator === 'string' ? decimalSeparator : '.',
|
||||
minorUnit: Number.isFinite( minorUnit ) ? minorUnit : 2,
|
||||
prefix: typeof prefix === 'string' ? prefix : '$',
|
||||
suffix: typeof suffix === 'string' ? suffix : '',
|
||||
typeof decimalSeparator === 'string'
|
||||
? decimalSeparator
|
||||
: SITE_CURRENCY.decimalSeparator,
|
||||
minorUnit: Number.isFinite( minorUnit )
|
||||
? minorUnit
|
||||
: SITE_CURRENCY.minorUnit,
|
||||
prefix: typeof prefix === 'string' ? prefix : SITE_CURRENCY.prefix,
|
||||
suffix: typeof suffix === 'string' ? suffix : SITE_CURRENCY.suffix,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -110,7 +60,7 @@ export const getCurrency = (
|
|||
currencyData: Partial< Currency > = {}
|
||||
): Currency => {
|
||||
return {
|
||||
...siteCurrencySettings,
|
||||
...SITE_CURRENCY,
|
||||
...currencyData,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: dev
|
||||
|
||||
In blocks codebase, export SITE_CURRENCY property with properties matching typescript definitions.
|
Loading…
Reference in New Issue