/**
* External dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
import FormattedMonetaryAmount from '@woocommerce/base-components/formatted-monetary-amount';
import classNames from 'classnames';
import { formatPrice } from '@woocommerce/price-format';
import { createInterpolateElement } from '@wordpress/element';
import type { Currency } from '@woocommerce/types';
/**
* Internal dependencies
*/
import './style.scss';
interface PriceRangeProps {
/**
* Currency configuration object
*/
currency: Currency | Record< string, never >;
/**
* The maximum price for the range
*/
maxPrice: string | number;
/**
* The minimum price for the range
*/
minPrice: string | number;
/**
* CSS class applied to each of the elements containing the prices
*
* **Note:** this excludes the dash in between the elements
*/
priceClassName?: string;
/**
* Any custom style to be applied to each of the elements containing the prices
*
* **Note:** this excludes the dash in between the elements
*/
priceStyle?: React.CSSProperties;
}
const PriceRange = ( {
currency,
maxPrice,
minPrice,
priceClassName,
priceStyle = {},
}: PriceRangeProps ) => {
return (
<>
{ sprintf(
/* translators: %1$s min price, %2$s max price */
__(
'Price between %1$s and %2$s',
'woo-gutenberg-products-block'
),
formatPrice( minPrice ),
formatPrice( maxPrice )
) }
—
>
);
};
interface SalePriceProps {
/**
* Currency configuration object
*/
currency: Currency | Record< string, never >;
/**
* CSS class to be applied to the regular price container
*
* i.e. `` element
*/
regularPriceClassName?: string;
/**
* Custom style to be applied to the regular price container
*
* i.e. `` element
*/
regularPriceStyle?: React.CSSProperties;
/**
* The regular price before the sale
*/
regularPrice: number | string;
/**
* CSS class to be applied to the sale price container
*
* i.e. `` element
*/
priceClassName?: string;
/**
* Custom style to be applied to the regular price container
*
* i.e. `` element
*/
priceStyle?: React.CSSProperties;
/**
* The new price during the sale
*/
price: number | string;
}
const SalePrice = ( {
currency,
regularPriceClassName,
regularPriceStyle,
regularPrice,
priceClassName,
priceStyle,
price,
}: SalePriceProps ) => {
return (
<>
{ __( 'Previous price:', 'woo-gutenberg-products-block' ) }
(
{ value }
) }
value={ regularPrice }
/>
{ __( 'Discounted price:', 'woo-gutenberg-products-block' ) }
(
{ value }
) }
value={ price }
/>
>
);
};
export interface ProductPriceProps {
/**
* Where to align the wrapper
*
* Applies the `wc-block-components-product-price--align-${ align }` utility
* class to the wrapper.
*/
align?: 'left' | 'center' | 'right';
/**
* CSS class for the wrapper
*/
className?: string;
/**
* Currency configuration object
*/
currency: Currency | Record< string, never >;
/**
* The string version of the element to use for the price interpolation
*
* **Note:** It should contain `` (which is also the default value)
*/
format: string;
/**
* The current price
*/
price: number | string;
/**
* CSS class for the current price wrapper
*/
priceClassName?: string;
/**
* Custom style for the current price
*/
priceStyle?: React.CSSProperties;
/**
* The maximum price in a range
*
* If both `maxPrice` and `minPrice` are set, the component will be rendered
* as a `PriceRange` component, otherwise, this value will be ignored.
*/
maxPrice?: number | string;
/**
* The minimum price in a range
*
* If both `maxPrice` and `minPrice` are set, the component will be rendered
* as a `PriceRange` component, otherwise, this value will be ignored.
*/
minPrice?: number | string;
/**
* The regular price if the item is currently on sale
*
* If this property exists and is different from the current price, then the
* component will be rendered as a `SalePrice` component.
*/
regularPrice?: number | string;
/**
* CSS class to apply to the regular price wrapper
*/
regularPriceClassName?: string;
/**
* Custom style to apply to the regular price wrapper.
*/
regularPriceStyle?: React.CSSProperties;
}
const ProductPrice = ( {
align,
className,
currency,
format = '',
maxPrice,
minPrice,
price,
priceClassName,
priceStyle,
regularPrice,
regularPriceClassName,
regularPriceStyle,
}: ProductPriceProps ): JSX.Element => {
const wrapperClassName = classNames(
className,
'price',
'wc-block-components-product-price',
{
[ `wc-block-components-product-price--align-${ align }` ]: align,
}
);
if ( ! format.includes( '' ) ) {
format = '';
// eslint-disable-next-line no-console
console.error( 'Price formats need to include the `` tag.' );
}
const isDiscounted = regularPrice && price !== regularPrice;
let priceComponent = (
);
if ( isDiscounted ) {
priceComponent = (
);
} else if ( minPrice !== undefined && maxPrice !== undefined ) {
priceComponent = (
);
} else if ( price ) {
priceComponent = (
);
}
return (
{ createInterpolateElement( format, {
price: priceComponent,
} ) }
);
};
export default ProductPrice;