Cherry pick 51499 into release/9.4 (#52035)

* Show correct decimals on product price and show the sale price of products (#51499)

* add regular price and sale price flag to product apis and types

* add sale price and screen reader text for prices on product cards

* fix typo on sale flag

* add regular price and sale price flag to product apis and types

* add sale price and screen reader text for prices on product cards

* fix typo on sale flag

* Changelog.

* address feedback on sale price VO text

---------

Co-authored-by: Herman <KokkieH@users.noreply.github.com>
Co-authored-by: And Finally <andfinally@users.noreply.github.com>

* Prep for cherry pick 51499

---------

Co-authored-by: Raja sekar <raja.sekar.manimaran@automattic.com>
Co-authored-by: Herman <KokkieH@users.noreply.github.com>
Co-authored-by: And Finally <andfinally@users.noreply.github.com>
Co-authored-by: WooCommerce Bot <no-reply@woocommerce.com>
This commit is contained in:
github-actions[bot] 2024-10-15 13:01:25 +01:00 committed by GitHub
parent 4298800971
commit 602642f38c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 68 additions and 2 deletions

View File

@ -144,6 +144,35 @@ function ProductCardFooter( props: { product: Product } ) {
return ''; return '';
} }
const getReaderPriceLabel = () => {
if ( product.isOnSale ) {
return sprintf(
//translators: %1$s is the sale price of the product, %2$s is the regular price of the product, %3$s is the billing period
__(
'Sale Price %1$s %3$s, regular price %2$s %3$s',
'woocommerce'
),
getPriceLabel(),
sprintf(
getCurrencyFormat( product.currency ),
product.regularPrice
),
getBillingText()
);
}
if ( product.price !== 0 && product.freemium_type !== 'primary' ) {
return sprintf(
//translators: %1$s is the price of the product, %2$s is the billing period
__( ' %1$s, %2$s ', 'woocommerce' ),
getPriceLabel(),
getBillingText()
);
}
return getPriceLabel();
};
if ( shouldShowAddToStore( product ) ) { if ( shouldShowAddToStore( product ) ) {
return ( return (
<> <>
@ -160,9 +189,28 @@ function ProductCardFooter( props: { product: Product } ) {
<> <>
<div className="woocommerce-marketplace__product-card__price"> <div className="woocommerce-marketplace__product-card__price">
<span className="woocommerce-marketplace__product-card__price-label"> <span className="woocommerce-marketplace__product-card__price-label">
{ getPriceLabel() } <span className="screen-reader-text">
{ getReaderPriceLabel() }
</span> </span>
<span className="woocommerce-marketplace__product-card__price-billing"> <span aria-hidden>{ getPriceLabel() }</span>
</span>
{ product.isOnSale && (
<span
className="woocommerce-marketplace__product-card__on-sale"
aria-hidden
>
{ sprintf(
getCurrencyFormat( product.currency ),
product.regularPrice
) }
</span>
) }
<span
className="woocommerce-marketplace__product-card__price-billing"
aria-hidden
>
{ getBillingText() } { getBillingText() }
</span> </span>
</div> </div>

View File

@ -217,6 +217,12 @@
line-height: $medium-gap; line-height: $medium-gap;
} }
&__on-sale {
color: $gray-600;
font-weight: 400;
text-decoration: line-through;
}
&__price-billing { &__price-billing {
color: $gray-600; color: $gray-600;
font-size: $default-font-size; font-size: $default-font-size;

View File

@ -51,6 +51,8 @@ function ProductCard( props: ProductCardProps ): JSX.Element {
billingPeriod: '', billingPeriod: '',
billingPeriodInterval: 0, billingPeriodInterval: 0,
currency: '', currency: '',
isOnSale: false,
regularPrice: 0,
}; };
function isSponsored(): boolean { function isSponsored(): boolean {

View File

@ -109,6 +109,8 @@ export default function ProductListContent( props: {
billingPeriodInterval: billingPeriodInterval:
product.billingPeriodInterval, product.billingPeriodInterval,
currency: product.currency, currency: product.currency,
isOnSale: product.isOnSale,
regularPrice: product.regularPrice,
} } } }
tracksData={ { tracksData={ {
position: index + 1, position: index + 1,

View File

@ -29,6 +29,8 @@ export type SearchAPIProductType = {
billing_period: string; billing_period: string;
billing_period_interval: number; billing_period_interval: number;
currency: string; currency: string;
is_on_sale: boolean;
regular_price: number;
}; };
export interface Product { export interface Product {
@ -60,6 +62,8 @@ export interface Product {
billingPeriod?: string; billingPeriod?: string;
billingPeriodInterval?: number; billingPeriodInterval?: number;
currency: string; currency: string;
isOnSale: boolean;
regularPrice: number;
} }
export interface ProductTracksData { export interface ProductTracksData {

View File

@ -142,6 +142,8 @@ async function fetchSearchResults(
url: product.link, url: product.link,
// Due to backwards compatibility, raw_price is from search API, price is from featured API // Due to backwards compatibility, raw_price is from search API, price is from featured API
price: product.raw_price ?? product.price, price: product.raw_price ?? product.price,
regularPrice: product.regular_price,
isOnSale: product.is_on_sale,
averageRating: product.rating ?? null, averageRating: product.rating ?? null,
reviewsCount: product.reviews_count ?? null, reviewsCount: product.reviews_count ?? null,
isInstallable: product.is_installable, isInstallable: product.is_installable,
@ -426,6 +428,8 @@ const subscriptionToProduct = ( subscription: Subscription ): Product => {
icon: subscription.product_icon, icon: subscription.product_icon,
url: subscription.product_url, url: subscription.product_url,
price: -1, price: -1,
regularPrice: -1,
isOnSale: false,
averageRating: null, averageRating: null,
reviewsCount: null, reviewsCount: null,
isInstallable: false, isInstallable: false,