When a search is initiated, fetch all categories to keep the tab counts up to date.
The necessary filtering to display data to the current screen will be performed on the frontend.
This commit is contained in:
parent
43024547a1
commit
44c29dd2f3
|
@ -8,7 +8,7 @@ import { useQuery } from '@woocommerce/navigation';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import './content.scss';
|
||||
import { Product, ProductType, SearchResultType } from '../product-list/types';
|
||||
import { Product, ProductType } from '../product-list/types';
|
||||
import { getAdminSetting } from '~/utils/admin-settings';
|
||||
import Discover from '../discover/discover';
|
||||
import Products from '../products/products';
|
||||
|
@ -30,7 +30,10 @@ import SubscriptionsExpiredExpiringNotice from '~/marketplace/components/my-subs
|
|||
|
||||
export default function Content(): JSX.Element {
|
||||
const marketplaceContextValue = useContext( MarketplaceContext );
|
||||
const [ products, setProducts ] = useState< Product[] >( [] );
|
||||
const [ allProducts, setAllProducts ] = useState< Product[] >( [] );
|
||||
const [ filteredProducts, setFilteredProducts ] = useState< Product[] >(
|
||||
[]
|
||||
);
|
||||
const {
|
||||
setIsLoading,
|
||||
selectedTab,
|
||||
|
@ -39,21 +42,40 @@ export default function Content(): JSX.Element {
|
|||
} = marketplaceContextValue;
|
||||
const query = useQuery();
|
||||
|
||||
// On initial load of the in-app marketplace, fetch extensions, themes and business services
|
||||
// and check if there are any business services available on WCCOM
|
||||
// Function to tag products with their type
|
||||
const tagProductsWithType = (
|
||||
products: Product[],
|
||||
type: ProductType
|
||||
): Product[] => {
|
||||
return products.map( ( product ) => ( {
|
||||
...product,
|
||||
type, // Adding the product type to each product
|
||||
} ) );
|
||||
};
|
||||
|
||||
// Fetch all categories when query.term or query.category changes
|
||||
useEffect( () => {
|
||||
const categories: Array< keyof SearchResultsCountType > = [
|
||||
'extensions',
|
||||
'themes',
|
||||
'business-services',
|
||||
const categories: Array< {
|
||||
key: keyof SearchResultsCountType;
|
||||
type: ProductType;
|
||||
} > = [
|
||||
{ key: 'extensions', type: ProductType.extension },
|
||||
{ key: 'themes', type: ProductType.theme },
|
||||
{ key: 'business-services', type: ProductType.businessService },
|
||||
];
|
||||
const abortControllers = categories.map( () => new AbortController() );
|
||||
|
||||
categories.forEach(
|
||||
( category: keyof SearchResultsCountType, index ) => {
|
||||
setIsLoading( true );
|
||||
setAllProducts( [] );
|
||||
|
||||
Promise.all(
|
||||
categories.map( ( { key, type }, index ) => {
|
||||
const params = new URLSearchParams();
|
||||
if ( category !== 'extensions' ) {
|
||||
params.append( 'category', category );
|
||||
if ( key !== 'extensions' ) {
|
||||
params.append( 'category', key );
|
||||
}
|
||||
if ( query.term ) {
|
||||
params.append( 'term', query.term );
|
||||
}
|
||||
|
||||
const wccomSettings = getAdminSetting( 'wccomHelper', false );
|
||||
|
@ -61,114 +83,96 @@ export default function Content(): JSX.Element {
|
|||
params.append( 'country', wccomSettings.storeCountry );
|
||||
}
|
||||
|
||||
fetchSearchResults(
|
||||
return fetchSearchResults(
|
||||
params,
|
||||
abortControllers[ index ].signal
|
||||
).then( ( productList ) => {
|
||||
if ( category === 'business-services' ) {
|
||||
setHasBusinessServices( productList.length > 0 );
|
||||
// Tag the products with their type (extension, theme, or business-service)
|
||||
const typedProducts = tagProductsWithType(
|
||||
productList,
|
||||
type
|
||||
);
|
||||
if ( key === 'business-services' ) {
|
||||
setHasBusinessServices( typedProducts.length > 0 );
|
||||
}
|
||||
return typedProducts;
|
||||
} );
|
||||
} )
|
||||
)
|
||||
.then( ( results ) => {
|
||||
const combinedProducts = results.flat();
|
||||
setAllProducts( combinedProducts );
|
||||
|
||||
// Set the search results count based on product types
|
||||
setSearchResultsCount( {
|
||||
extensions: combinedProducts.filter(
|
||||
( p ) => p.type === ProductType.extension
|
||||
).length,
|
||||
themes: combinedProducts.filter(
|
||||
( p ) => p.type === ProductType.theme
|
||||
).length,
|
||||
'business-services': combinedProducts.filter(
|
||||
( p ) => p.type === ProductType.businessService
|
||||
).length,
|
||||
} );
|
||||
} )
|
||||
.catch( () => {
|
||||
setAllProducts( [] );
|
||||
} )
|
||||
.finally( () => {
|
||||
setIsLoading( false );
|
||||
} );
|
||||
|
||||
return () => {
|
||||
abortControllers.forEach( ( controller ) => {
|
||||
controller.abort();
|
||||
} );
|
||||
};
|
||||
}
|
||||
);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [] );
|
||||
}, [ query.term, query.category ] ); // Depend on term and category
|
||||
|
||||
// Get the content for this screen
|
||||
// Filter the products based on the selected tab
|
||||
useEffect( () => {
|
||||
const abortController = new AbortController();
|
||||
|
||||
if (
|
||||
query.tab === undefined ||
|
||||
( query.tab && [ '', 'discover' ].includes( query.tab ) )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading( true );
|
||||
setProducts( [] );
|
||||
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if ( query.term ) {
|
||||
params.append( 'term', query.term );
|
||||
}
|
||||
|
||||
if ( query.category ) {
|
||||
params.append(
|
||||
'category',
|
||||
query.category === '_all' ? '' : query.category
|
||||
let filtered: Product[] | null;
|
||||
switch ( selectedTab ) {
|
||||
case 'extensions':
|
||||
filtered = allProducts.filter(
|
||||
( p ) => p.type === ProductType.extension
|
||||
);
|
||||
} else if ( query?.tab === 'themes' ) {
|
||||
params.append( 'category', 'themes' );
|
||||
} else if ( query?.tab === 'business-services' ) {
|
||||
params.append( 'category', 'business-services' );
|
||||
break;
|
||||
case 'themes':
|
||||
filtered = allProducts.filter(
|
||||
( p ) => p.type === ProductType.theme
|
||||
);
|
||||
break;
|
||||
case 'business-services':
|
||||
filtered = allProducts.filter(
|
||||
( p ) => p.type === ProductType.businessService
|
||||
);
|
||||
break;
|
||||
default:
|
||||
filtered = [];
|
||||
}
|
||||
setFilteredProducts( filtered );
|
||||
}, [ selectedTab, allProducts ] );
|
||||
|
||||
const wccomSettings = getAdminSetting( 'wccomHelper', false );
|
||||
if ( wccomSettings.storeCountry ) {
|
||||
params.append( 'country', wccomSettings.storeCountry );
|
||||
}
|
||||
|
||||
fetchSearchResults( params, abortController.signal )
|
||||
.then( ( productList ) => {
|
||||
setProducts( productList );
|
||||
|
||||
if ( query.term ) {
|
||||
setSearchResultsCount( {
|
||||
extensions: productList.filter(
|
||||
( p ) => p.type === 'extension'
|
||||
).length,
|
||||
themes: productList.filter(
|
||||
( p ) => p.type === 'theme'
|
||||
).length,
|
||||
'business-services': productList.filter(
|
||||
( p ) => p.type === 'business-service'
|
||||
).length,
|
||||
} );
|
||||
}
|
||||
} )
|
||||
.catch( () => {
|
||||
setProducts( [] );
|
||||
} )
|
||||
.finally( () => {
|
||||
// we are recording both the new and legacy events here for now
|
||||
// they're separate methods to make it easier to remove the legacy one later
|
||||
// Record tab view events when the query changes
|
||||
useEffect( () => {
|
||||
const marketplaceViewProps = {
|
||||
view: query?.tab,
|
||||
search_term: query?.term,
|
||||
product_type: query?.section,
|
||||
category: query?.category,
|
||||
};
|
||||
|
||||
recordMarketplaceView( marketplaceViewProps );
|
||||
recordLegacyTabView( marketplaceViewProps );
|
||||
setIsLoading( false );
|
||||
} );
|
||||
return () => {
|
||||
abortController.abort();
|
||||
};
|
||||
}, [
|
||||
query.term,
|
||||
query.category,
|
||||
query?.tab,
|
||||
setIsLoading,
|
||||
query?.section,
|
||||
] );
|
||||
}, [ query?.tab, query?.term, query?.section, query?.category ] );
|
||||
|
||||
const renderContent = (): JSX.Element => {
|
||||
switch ( selectedTab ) {
|
||||
case 'extensions':
|
||||
return (
|
||||
<Products
|
||||
products={ products.filter(
|
||||
( p ) => p.type === 'extension'
|
||||
) }
|
||||
products={ filteredProducts }
|
||||
categorySelector={ true }
|
||||
type={ ProductType.extension }
|
||||
/>
|
||||
|
@ -176,9 +180,7 @@ export default function Content(): JSX.Element {
|
|||
case 'themes':
|
||||
return (
|
||||
<Products
|
||||
products={ products.filter(
|
||||
( p ) => p.type === 'theme'
|
||||
) }
|
||||
products={ filteredProducts }
|
||||
categorySelector={ true }
|
||||
type={ ProductType.theme }
|
||||
/>
|
||||
|
@ -186,9 +188,7 @@ export default function Content(): JSX.Element {
|
|||
case 'business-services':
|
||||
return (
|
||||
<Products
|
||||
products={ products.filter(
|
||||
( p ) => p.type === 'business-service'
|
||||
) }
|
||||
products={ filteredProducts }
|
||||
categorySelector={ true }
|
||||
type={ ProductType.businessService }
|
||||
/>
|
||||
|
@ -209,7 +209,7 @@ export default function Content(): JSX.Element {
|
|||
return (
|
||||
<div className="woocommerce-marketplace__content">
|
||||
<Promotions />
|
||||
<InstallNewProductModal products={ products } />
|
||||
<InstallNewProductModal products={ filteredProducts } />
|
||||
{ selectedTab !== 'business-services' &&
|
||||
selectedTab !== 'my-subscriptions' && <ConnectNotice /> }
|
||||
{ selectedTab !== 'business-services' && <PluginInstallNotice /> }
|
||||
|
|
Loading…
Reference in New Issue