Set in-app product card price meta dynamically (#51170)
* Set product card price currency and suffix dynamically based on endpoint data * Add changefile(s) from automation for the following project(s): woocommerce * Remove unnecessary comment * Update types to match data received from WCCOM after further changes to the API * Apply suggestions from code review Allow for future currencies that might switch the symbol/value order Co-authored-by: Dan Q <dan@danq.me> --------- Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Dan Q <dan@danq.me>
This commit is contained in:
parent
3b35e22c99
commit
904dfaa2ff
|
@ -2,7 +2,7 @@
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { Button, Icon } from '@wordpress/components';
|
import { Button, Icon } from '@wordpress/components';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
import { useContext } from '@wordpress/element';
|
import { useContext } from '@wordpress/element';
|
||||||
import { recordEvent } from '@woocommerce/tracks';
|
import { recordEvent } from '@woocommerce/tracks';
|
||||||
import { navigateTo, getNewPath } from '@woocommerce/navigation';
|
import { navigateTo, getNewPath } from '@woocommerce/navigation';
|
||||||
|
@ -64,8 +64,17 @@ function ProductCardFooter( props: { product: Product } ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We hardcode this for now while we only display prices in USD.
|
const currencyFormats: { [ key: string ]: string } = {
|
||||||
const currencySymbol = '$';
|
USD: '$%s',
|
||||||
|
AUD: 'A$%s',
|
||||||
|
CAD: 'C$%s',
|
||||||
|
EUR: '€%s',
|
||||||
|
GBP: '£%s',
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCurrencyFormat = ( currencyCode: string ) => {
|
||||||
|
return currencyFormats[ currencyCode ] || '%s';
|
||||||
|
};
|
||||||
|
|
||||||
function getPriceLabel(): string {
|
function getPriceLabel(): string {
|
||||||
if ( product.price === 0 ) {
|
if ( product.price === 0 ) {
|
||||||
|
@ -76,7 +85,51 @@ function ProductCardFooter( props: { product: Product } ) {
|
||||||
return __( 'Free plan available', 'woocommerce' );
|
return __( 'Free plan available', 'woocommerce' );
|
||||||
}
|
}
|
||||||
|
|
||||||
return currencySymbol + product.price;
|
return sprintf( getCurrencyFormat( product.currency ), product.price );
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPriceSuffix(): string {
|
||||||
|
// Paid simple products have a billing period of ''.
|
||||||
|
if (
|
||||||
|
product.billingPeriodInterval === 1 ||
|
||||||
|
product.billingPeriod === ''
|
||||||
|
) {
|
||||||
|
switch ( product.billingPeriod ) {
|
||||||
|
case 'day':
|
||||||
|
return __( 'daily', 'woocommerce' );
|
||||||
|
case 'week':
|
||||||
|
return __( 'weekly', 'woocommerce' );
|
||||||
|
case 'month':
|
||||||
|
return __( 'monthly', 'woocommerce' );
|
||||||
|
case 'year':
|
||||||
|
case '':
|
||||||
|
return __( 'annually', 'woocommerce' );
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let period;
|
||||||
|
switch ( product.billingPeriod ) {
|
||||||
|
case 'day':
|
||||||
|
period = __( 'days', 'woocommerce' );
|
||||||
|
break;
|
||||||
|
case 'week':
|
||||||
|
period = __( 'weeks', 'woocommerce' );
|
||||||
|
break;
|
||||||
|
case 'month':
|
||||||
|
period = __( 'months', 'woocommerce' );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
period = __( 'years', 'woocommerce' );
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(
|
||||||
|
// translators: %1$d: billing period interval, %2$s: billing period (e.g. days, weeks, months, years)
|
||||||
|
__( 'every %1$d %2$s', 'woocommerce' ),
|
||||||
|
product.billingPeriodInterval,
|
||||||
|
period
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBillingText(): string {
|
function getBillingText(): string {
|
||||||
|
@ -85,7 +138,7 @@ function ProductCardFooter( props: { product: Product } ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( product.price !== 0 ) {
|
if ( product.price !== 0 ) {
|
||||||
return __( ' annually', 'woocommerce' );
|
return getPriceSuffix();
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
|
|
|
@ -47,6 +47,9 @@ function ProductCard( props: ProductCardProps ): JSX.Element {
|
||||||
featuredImage: '',
|
featuredImage: '',
|
||||||
color: '',
|
color: '',
|
||||||
productCategory: '',
|
productCategory: '',
|
||||||
|
billingPeriod: '',
|
||||||
|
billingPeriodInterval: 0,
|
||||||
|
currency: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
function isSponsored(): boolean {
|
function isSponsored(): boolean {
|
||||||
|
|
|
@ -105,6 +105,10 @@ export default function ProductListContent( props: {
|
||||||
color: product.color,
|
color: product.color,
|
||||||
featuredImage: product.featuredImage,
|
featuredImage: product.featuredImage,
|
||||||
productCategory: product.productCategory,
|
productCategory: product.productCategory,
|
||||||
|
billingPeriod: product.billingPeriod,
|
||||||
|
billingPeriodInterval:
|
||||||
|
product.billingPeriodInterval,
|
||||||
|
currency: product.currency,
|
||||||
} }
|
} }
|
||||||
tracksData={ {
|
tracksData={ {
|
||||||
position: index + 1,
|
position: index + 1,
|
||||||
|
|
|
@ -24,6 +24,9 @@ export type SearchAPIProductType = {
|
||||||
featured_image: string;
|
featured_image: string;
|
||||||
product_category: string;
|
product_category: string;
|
||||||
color: string;
|
color: string;
|
||||||
|
billing_period: string;
|
||||||
|
billing_period_interval: number;
|
||||||
|
currency: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface Product {
|
export interface Product {
|
||||||
|
@ -52,6 +55,9 @@ export interface Product {
|
||||||
featuredImage?: string;
|
featuredImage?: string;
|
||||||
productCategory?: string;
|
productCategory?: string;
|
||||||
color?: string;
|
color?: string;
|
||||||
|
billingPeriod?: string;
|
||||||
|
billingPeriodInterval?: number;
|
||||||
|
currency: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProductTracksData {
|
export interface ProductTracksData {
|
||||||
|
|
|
@ -144,6 +144,10 @@ async function fetchSearchResults(
|
||||||
featuredImage: product.featured_image,
|
featuredImage: product.featured_image,
|
||||||
productCategory: product.product_category,
|
productCategory: product.product_category,
|
||||||
color: product.color,
|
color: product.color,
|
||||||
|
billingPeriod: product.billing_period,
|
||||||
|
billingPeriodInterval:
|
||||||
|
product.billing_period_interval,
|
||||||
|
currency: product.currency,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -407,6 +411,7 @@ const subscriptionToProduct = ( subscription: Subscription ): Product => {
|
||||||
averageRating: null,
|
averageRating: null,
|
||||||
reviewsCount: null,
|
reviewsCount: null,
|
||||||
isInstallable: false,
|
isInstallable: false,
|
||||||
|
currency: '',
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: update
|
||||||
|
|
||||||
|
Product cards in the in-app marketplace show currency and billing period data dynamically, based on data received from WooCommerce.com
|
Loading…
Reference in New Issue