diff --git a/assets/js/blocks/reviews/reviews-by-product/block.tsx b/assets/js/blocks/reviews/reviews-by-product/block.tsx
new file mode 100644
index 00000000000..60992c9eba7
--- /dev/null
+++ b/assets/js/blocks/reviews/reviews-by-product/block.tsx
@@ -0,0 +1,182 @@
+/**
+ * External dependencies
+ */
+import { __, _n, sprintf } from '@wordpress/i18n';
+import { InspectorControls } from '@wordpress/block-editor';
+import {
+ Button,
+ PanelBody,
+ Placeholder,
+ withSpokenMessages,
+} from '@wordpress/components';
+import { SearchListItem } from '@woocommerce/editor-components/search-list-control';
+import ProductControl from '@woocommerce/editor-components/product-control';
+import { commentContent, Icon } from '@wordpress/icons';
+
+/**
+ * Internal dependencies
+ */
+import EditorContainerBlock from '../editor-container-block.js';
+import NoReviewsPlaceholder from './no-reviews-placeholder';
+import {
+ getBlockControls,
+ getSharedReviewContentControls,
+ getSharedReviewListControls,
+} from '../edit-utils.js';
+import type { ReviewsByProductEditorProps, SearchListItemProps } from './types';
+
+const ReviewsByProductEditor = ( {
+ attributes,
+ debouncedSpeak,
+ setAttributes,
+}: ReviewsByProductEditorProps ) => {
+ const { editMode, productId } = attributes;
+
+ const renderProductControlItem = ( args: SearchListItemProps ) => {
+ return (
+
+ );
+ };
+
+ const getInspectorControls = () => {
+ return (
+
+
+ {
+ const id = value[ 0 ] ? value[ 0 ].id : 0;
+ setAttributes( { productId: id } );
+ } }
+ renderItem={ renderProductControlItem }
+ isCompact={ true }
+ />
+
+
+ { getSharedReviewContentControls(
+ attributes,
+ setAttributes
+ ) }
+
+
+ { getSharedReviewListControls( attributes, setAttributes ) }
+
+
+ );
+ };
+
+ const renderEditMode = () => {
+ const onDone = () => {
+ setAttributes( { editMode: false } );
+ debouncedSpeak(
+ __(
+ 'Showing Reviews by Product block preview.',
+ 'woo-gutenberg-products-block'
+ )
+ );
+ };
+
+ return (
+
+ }
+ label={ __(
+ 'Reviews by Product',
+ 'woo-gutenberg-products-block'
+ ) }
+ className="wc-block-reviews-by-product"
+ >
+ { __(
+ 'Show reviews of your product to build trust',
+ 'woo-gutenberg-products-block'
+ ) }
+
+
{
+ const id = value[ 0 ] ? value[ 0 ].id : 0;
+ setAttributes( { productId: id } );
+ } }
+ queryArgs={ {
+ orderby: 'comment_count',
+ order: 'desc',
+ } }
+ renderItem={ renderProductControlItem }
+ />
+
+
+
+ );
+ };
+
+ if ( ! productId || editMode ) {
+ return renderEditMode();
+ }
+
+ const buttonTitle = __(
+ 'Edit selected product',
+ 'woo-gutenberg-products-block'
+ );
+
+ return (
+ <>
+ { getBlockControls( editMode, setAttributes, buttonTitle ) }
+ { getInspectorControls() }
+
+ }
+ name={ __(
+ 'Reviews by Product',
+ 'woo-gutenberg-products-block'
+ ) }
+ noReviewsPlaceholder={ NoReviewsPlaceholder }
+ />
+ >
+ );
+};
+
+export default withSpokenMessages( ReviewsByProductEditor );
diff --git a/assets/js/blocks/reviews/reviews-by-product/edit.tsx b/assets/js/blocks/reviews/reviews-by-product/edit.tsx
index 3c9155a69a3..e241189c5f7 100644
--- a/assets/js/blocks/reviews/reviews-by-product/edit.tsx
+++ b/assets/js/blocks/reviews/reviews-by-product/edit.tsx
@@ -1,184 +1,22 @@
/**
* External dependencies
*/
-import { __, _n, sprintf } from '@wordpress/i18n';
-import { InspectorControls } from '@wordpress/block-editor';
-import {
- Button,
- PanelBody,
- Placeholder,
- withSpokenMessages,
-} from '@wordpress/components';
-import { SearchListItem } from '@woocommerce/editor-components/search-list-control';
-import ProductControl from '@woocommerce/editor-components/product-control';
-import { commentContent, Icon } from '@wordpress/icons';
+import { useBlockProps } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
-import EditorContainerBlock from '../editor-container-block.js';
-import NoReviewsPlaceholder from './no-reviews-placeholder.js';
-import {
- getBlockControls,
- getSharedReviewContentControls,
- getSharedReviewListControls,
-} from '../edit-utils.js';
-import { ReviewsByProductEditorProps } from './types';
+import Block from './block';
+import type { ReviewsByProductEditorProps } from './types';
-const ReviewsByProductEditor = ( {
- attributes,
- debouncedSpeak,
- setAttributes,
-}: ReviewsByProductEditorProps ) => {
- const { editMode, productId } = attributes;
-
- const renderProductControlItem = ( args ) => {
- const { item = 0 } = args;
-
- return (
-
- );
- };
-
- const getInspectorControls = () => {
- return (
-
-
- {
- const id = value[ 0 ] ? value[ 0 ].id : 0;
- setAttributes( { productId: id } );
- } }
- renderItem={ renderProductControlItem }
- isCompact={ true }
- />
-
-
- { getSharedReviewContentControls(
- attributes,
- setAttributes
- ) }
-
-
- { getSharedReviewListControls( attributes, setAttributes ) }
-
-
- );
- };
-
- const renderEditMode = () => {
- const onDone = () => {
- setAttributes( { editMode: false } );
- debouncedSpeak(
- __(
- 'Showing Reviews by Product block preview.',
- 'woo-gutenberg-products-block'
- )
- );
- };
-
- return (
-
- }
- label={ __(
- 'Reviews by Product',
- 'woo-gutenberg-products-block'
- ) }
- className="wc-block-reviews-by-product"
- >
- { __(
- 'Show reviews of your product to build trust',
- 'woo-gutenberg-products-block'
- ) }
-
-
{
- const id = value[ 0 ] ? value[ 0 ].id : 0;
- setAttributes( { productId: id } );
- } }
- queryArgs={ {
- orderby: 'comment_count',
- order: 'desc',
- } }
- renderItem={ renderProductControlItem }
- />
-
-
-
- );
- };
-
- if ( ! productId || editMode ) {
- return renderEditMode();
- }
-
- const buttonTitle = __(
- 'Edit selected product',
- 'woo-gutenberg-products-block'
- );
+export const Edit = (
+ props: unknown & ReviewsByProductEditorProps
+): JSX.Element => {
+ const blockProps = useBlockProps();
return (
- <>
- { getBlockControls( editMode, setAttributes, buttonTitle ) }
- { getInspectorControls() }
-
- }
- name={ __(
- 'Reviews by Product',
- 'woo-gutenberg-products-block'
- ) }
- noReviewsPlaceholder={ NoReviewsPlaceholder }
- />
- >
+
+
+
);
};
-
-export default withSpokenMessages( ReviewsByProductEditor );
diff --git a/assets/js/blocks/reviews/reviews-by-product/index.js b/assets/js/blocks/reviews/reviews-by-product/index.tsx
similarity index 94%
rename from assets/js/blocks/reviews/reviews-by-product/index.js
rename to assets/js/blocks/reviews/reviews-by-product/index.tsx
index ff6d152d41b..c9927088dc7 100644
--- a/assets/js/blocks/reviews/reviews-by-product/index.js
+++ b/assets/js/blocks/reviews/reviews-by-product/index.tsx
@@ -8,7 +8,7 @@ import { Icon, commentContent } from '@wordpress/icons';
* Internal dependencies
*/
import '../editor.scss';
-import Editor from './edit';
+import { Edit } from './edit';
import sharedAttributes from '../attributes';
import save from '../save.js';
import { example } from '../example';
@@ -64,9 +64,7 @@ registerBlockType( 'woocommerce/reviews-by-product', {
*
* @param {Object} props Props to pass to block.
*/
- edit( props ) {
- return ;
- },
+ edit: Edit,
/**
* Save the props to post content.
diff --git a/assets/js/blocks/reviews/reviews-by-product/no-reviews-placeholder.js b/assets/js/blocks/reviews/reviews-by-product/no-reviews-placeholder.tsx
similarity index 80%
rename from assets/js/blocks/reviews/reviews-by-product/no-reviews-placeholder.js
rename to assets/js/blocks/reviews/reviews-by-product/no-reviews-placeholder.tsx
index 9d17ee9e350..85301538094 100644
--- a/assets/js/blocks/reviews/reviews-by-product/no-reviews-placeholder.js
+++ b/assets/js/blocks/reviews/reviews-by-product/no-reviews-placeholder.tsx
@@ -3,13 +3,21 @@
*/
import { __, sprintf } from '@wordpress/i18n';
import { Placeholder, Spinner } from '@wordpress/components';
-import PropTypes from 'prop-types';
import ErrorPlaceholder from '@woocommerce/editor-components/error-placeholder';
import { Icon, commentContent } from '@wordpress/icons';
import { withProduct } from '@woocommerce/block-hocs';
import { decodeEntities } from '@wordpress/html-entities';
+/**
+ * Internal dependencies
+ */
+import type { NoReviewsPlaceholderProps } from './types';
-const NoReviewsPlaceholder = ( { error, getProduct, isLoading, product } ) => {
+const NoReviewsPlaceholder = ( {
+ error,
+ getProduct,
+ isLoading,
+ product,
+}: NoReviewsPlaceholderProps ) => {
const renderApiError = () => (
{
);
};
-NoReviewsPlaceholder.propTypes = {
- // from withProduct
- error: PropTypes.object,
- isLoading: PropTypes.bool,
- product: PropTypes.shape( {
- name: PropTypes.node,
- review_count: PropTypes.number,
- } ),
-};
-
export default withProduct( NoReviewsPlaceholder );
diff --git a/assets/js/blocks/reviews/reviews-by-product/types.ts b/assets/js/blocks/reviews/reviews-by-product/types.ts
index 297d7f62fbe..7fc268ca592 100644
--- a/assets/js/blocks/reviews/reviews-by-product/types.ts
+++ b/assets/js/blocks/reviews/reviews-by-product/types.ts
@@ -1,6 +1,8 @@
/**
* External dependencies
*/
+import { ErrorObject } from '@woocommerce/editor-components/error-placeholder';
+import { renderItemArgs } from '@woocommerce/editor-components/search-list-control/types';
import { BlockEditProps } from '@wordpress/blocks';
interface ReviewByProductAttributes {
@@ -13,3 +15,17 @@ export interface ReviewsByProductEditorProps
attributes: ReviewByProductAttributes;
debouncedSpeak: ( message: string ) => void;
}
+
+export interface NoReviewsPlaceholderProps {
+ error: ErrorObject;
+ getProduct: () => void;
+ isLoading: boolean;
+ product?: {
+ name: string;
+ };
+}
+
+export interface SearchListItemProps extends renderItemArgs {
+ name: string;
+ reviewCount: number;
+}