2020-07-22 12:20:54 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
2022-09-01 13:13:19 +00:00
|
|
|
import { useStoreProducts } from '@woocommerce/base-context/hooks';
|
2020-07-22 12:20:54 +00:00
|
|
|
import {
|
|
|
|
ProductDataContextProvider,
|
|
|
|
useProductDataContext,
|
|
|
|
} from '@woocommerce/shared-context';
|
|
|
|
|
2023-04-19 07:52:16 +00:00
|
|
|
const getProductById = ( products, id ) =>
|
|
|
|
products.find( ( product ) => product.id === id );
|
|
|
|
|
2020-07-22 12:20:54 +00:00
|
|
|
/**
|
|
|
|
* Loads the product from the API and adds to the context provider.
|
|
|
|
*
|
|
|
|
* @param {Object} props Component props.
|
|
|
|
*/
|
|
|
|
const OriginalComponentWithContext = ( props ) => {
|
2022-09-01 13:13:19 +00:00
|
|
|
const { productId, OriginalComponent, postId, product } = props;
|
2020-07-22 12:20:54 +00:00
|
|
|
|
2022-09-01 13:13:19 +00:00
|
|
|
const id = props?.isDescendentOfQueryLoop ? postId : productId;
|
2020-07-22 12:20:54 +00:00
|
|
|
|
2022-09-01 13:13:19 +00:00
|
|
|
const { products, productsLoading } = useStoreProducts( {
|
|
|
|
include: id,
|
|
|
|
} );
|
|
|
|
|
|
|
|
const productFromAPI = {
|
2023-04-19 07:52:16 +00:00
|
|
|
product:
|
|
|
|
id > 0 && products.length > 0
|
|
|
|
? getProductById( products, id )
|
|
|
|
: null,
|
2022-09-01 13:13:19 +00:00
|
|
|
isLoading: productsLoading,
|
|
|
|
};
|
2020-07-22 12:20:54 +00:00
|
|
|
|
2022-09-01 13:13:19 +00:00
|
|
|
if ( product ) {
|
|
|
|
return (
|
|
|
|
<ProductDataContextProvider product={ product } isLoading={ false }>
|
|
|
|
<OriginalComponent { ...props } />
|
|
|
|
</ProductDataContextProvider>
|
|
|
|
);
|
2020-07-22 12:20:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
2022-09-01 13:13:19 +00:00
|
|
|
<ProductDataContextProvider
|
|
|
|
product={ productFromAPI.product }
|
|
|
|
isLoading={ productFromAPI.isLoading }
|
|
|
|
>
|
2020-07-22 12:20:54 +00:00
|
|
|
<OriginalComponent { ...props } />
|
|
|
|
</ProductDataContextProvider>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This HOC sees if the Block is wrapped in Product Data Context, and if not, wraps it with context
|
|
|
|
* based on the productId attribute, if set.
|
|
|
|
*
|
|
|
|
* @param {Function} OriginalComponent Component being wrapped.
|
|
|
|
*/
|
|
|
|
export const withProductDataContext = ( OriginalComponent ) => {
|
|
|
|
return ( props ) => {
|
|
|
|
const productDataContext = useProductDataContext();
|
|
|
|
|
|
|
|
// If a product prop was provided, use this as the context for the tree.
|
|
|
|
if ( !! props.product || ! productDataContext.hasContext ) {
|
|
|
|
return (
|
|
|
|
<OriginalComponentWithContext
|
|
|
|
{ ...props }
|
|
|
|
OriginalComponent={ OriginalComponent }
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return <OriginalComponent { ...props } />;
|
|
|
|
};
|
|
|
|
};
|