/** * External dependencies */ import { __, sprintf } from '@wordpress/i18n'; import classNames from 'classnames'; import ReadMore from '@woocommerce/base-components/read-more'; import type { BlockAttributes } from '@wordpress/blocks'; /** * Internal dependencies */ import './style.scss'; import type { Review } from '../types'; function getReviewImage( review: Review, imageType: string, isLoading: boolean ): JSX.Element { if ( isLoading || ! review ) { return (
); } return (
{ imageType === 'product' ? ( ) : ( // The alt text is left empty on purpose, as it's considered a decorative image. // More can be found here: https://www.w3.org/WAI/tutorials/images/decorative/. // Github discussion for a context: https://github.com/woocommerce/woocommerce-blocks/pull/7651#discussion_r1019560494. ) } { review.verified && (
{ __( 'Verified buyer', 'woo-gutenberg-products-block' ) }
) }
); } function getReviewContent( review: Review ): JSX.Element { return (
); } function getReviewProductName( review: Review ): JSX.Element { return (
); } function getReviewerName( review: Review ): JSX.Element { const { reviewer = '' } = review; return (
{ reviewer }
); } function getReviewDate( review: Review ): JSX.Element { const { date_created: dateCreated, formatted_date_created: formattedDateCreated, } = review; return ( ); } function getReviewRating( review: Review ): JSX.Element { const { rating } = review; const starStyle = { width: ( rating / 5 ) * 100 + '%' /* stylelint-disable-line */, }; const ratingText = sprintf( /* translators: %f is referring to the average rating value */ __( 'Rated %f out of 5', 'woo-gutenberg-products-block' ), rating ); const ratingHTML = { __html: sprintf( /* translators: %s is referring to the average rating value */ __( 'Rated %s out of 5', 'woo-gutenberg-products-block' ), sprintf( '%f', rating ) ), }; return (
); } interface ReviewListItemProps { attributes: BlockAttributes; review?: Review; } const ReviewListItem = ( { attributes, review = {} }: ReviewListItemProps ) => { const { imageType, showReviewDate, showReviewerName, showReviewImage, showReviewRating: showReviewRatingAttr, showReviewContent, showProductName, } = attributes; const { rating } = review; const isLoading = ! ( Object.keys( review ).length > 0 ); const showReviewRating = Number.isFinite( rating ) && showReviewRatingAttr; return (
  • { ( showProductName || showReviewDate || showReviewerName || showReviewImage || showReviewRating ) && (
    { showReviewImage && getReviewImage( review, imageType, isLoading ) } { ( showProductName || showReviewerName || showReviewRating || showReviewDate ) && (
    { showReviewRating && getReviewRating( review ) } { showProductName && getReviewProductName( review ) } { showReviewerName && getReviewerName( review ) } { showReviewDate && getReviewDate( review ) }
    ) }
    ) } { showReviewContent && getReviewContent( review ) }
  • ); }; /** * BE AWARE. ReviewListItem expects product data that is equivalent to what is * made available for output in a public view. Thus content that may contain * html data is not sanitized further. * * Currently the following data is trusted (assumed to already be sanitized): * - `review.review` (review content) * - `review.product_name` (the product title) */ export default ReviewListItem;