From 546707763e13390dd31b1810fccd8d8fe247eeb7 Mon Sep 17 00:00:00 2001 From: arthur Date: Wed, 11 Dec 2024 17:26:10 +0800 Subject: [PATCH 1/5] Design Picker: Add the Recommended themes section --- .../design-setup/unified-design-picker.tsx | 2 ++ .../use-starter-designs-query.ts | 3 +++ .../src/components/unified-design-picker.tsx | 23 +++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/design-setup/unified-design-picker.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/design-setup/unified-design-picker.tsx index f0bdb5793dadf9..cf60570142553a 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/design-setup/unified-design-picker.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/design-setup/unified-design-picker.tsx @@ -213,6 +213,7 @@ const UnifiedDesignPickerStep: Step = ( { navigation, flow, stepName } ) => { const { data: allDesigns, isLoading: isLoadingDesigns } = useStarterDesignsQuery( { seed: siteSlugOrId ? String( siteSlugOrId ) : undefined, + goals: goals.length > 0 ? goals : [ 'none' ], _locale: locale, }, { @@ -968,6 +969,7 @@ const UnifiedDesignPickerStep: Step = ( { navigation, flow, stepName } ) => { isMultiFilterEnabled={ isGoalCentricFeature } onChangeTier={ handleChangeTier } isBigSkyEligible={ isBigSkyEligible } + recommendedDesignSlugs={ allDesigns.recommendation || [] } /> ); diff --git a/packages/data-stores/src/starter-designs-queries/use-starter-designs-query.ts b/packages/data-stores/src/starter-designs-queries/use-starter-designs-query.ts index 28486fc165b496..5a2259dd4b018a 100644 --- a/packages/data-stores/src/starter-designs-queries/use-starter-designs-query.ts +++ b/packages/data-stores/src/starter-designs-queries/use-starter-designs-query.ts @@ -14,6 +14,7 @@ import type { interface StarterDesignsQueryParams { seed?: string; + goals?: string[]; _locale: string; } @@ -25,6 +26,7 @@ interface Options extends QueryOptions< StarterDesignsResponse > { interface StarterDesignsResponse { filters: { subject: Record< string, Category > }; static: { designs: StarterDesign[] }; + recommendation: string[]; } export type ThemeTier = { @@ -63,6 +65,7 @@ export function useStarterDesignsQuery( subject: response.filters?.subject || {}, }, designs: response.static?.designs?.map( apiStarterDesignsToDesign ), + recommendation: response.recommendation, }; return select ? select( allDesigns ) : allDesigns; diff --git a/packages/design-picker/src/components/unified-design-picker.tsx b/packages/design-picker/src/components/unified-design-picker.tsx index cc6e3ba95359fb..572a9f0c4ca91c 100644 --- a/packages/design-picker/src/components/unified-design-picker.tsx +++ b/packages/design-picker/src/components/unified-design-picker.tsx @@ -279,6 +279,7 @@ interface DesignPickerProps { isMultiFilterEnabled?: boolean; onChangeTier?: ( value: boolean ) => void; isBigSkyEligible?: boolean; + recommendedDesignSlugs?: string[]; } const DesignPicker: React.FC< DesignPickerProps > = ( { @@ -298,6 +299,7 @@ const DesignPicker: React.FC< DesignPickerProps > = ( { isMultiFilterEnabled = false, onChangeTier, isBigSkyEligible = false, + recommendedDesignSlugs = [], } ) => { const translate = useTranslate(); const { all, best, ...designsByGroup } = useFilteredDesignsByGroup( designs ); @@ -314,6 +316,15 @@ const DesignPicker: React.FC< DesignPickerProps > = ( { [ categorization?.categories ] ); + const recommendedDesigns = useMemo( () => { + const recommendedDesignSlugsSet = new Set( recommendedDesignSlugs ); + + // The number should be a multiple of 3 but no more than 5 + return designs + .filter( ( design ) => recommendedDesignSlugsSet.has( design.recipe?.stylesheet || '' ) ) + .slice( 0, 3 ); + }, [ designs, recommendedDesignSlugs ] ); + const getCategoryName = ( value: string ) => categories.find( ( { slug } ) => slug === value )?.name || ''; @@ -373,6 +384,15 @@ const DesignPicker: React.FC< DesignPickerProps > = ( { + { isMultiFilterEnabled && recommendedDesigns.length === 3 && ( + + ) } + { isMultiFilterEnabled && categorization && categorization.selections.length > 1 && ( void; isBigSkyEligible?: boolean; + recommendedDesignSlugs?: string[]; } const UnifiedDesignPicker: React.FC< UnifiedDesignPickerProps > = ( { @@ -448,6 +469,7 @@ const UnifiedDesignPicker: React.FC< UnifiedDesignPickerProps > = ( { isMultiFilterEnabled = false, onChangeTier, isBigSkyEligible = false, + recommendedDesignSlugs = [], } ) => { const hasCategories = !! Object.keys( categorization?.categories || {} ).length; @@ -476,6 +498,7 @@ const UnifiedDesignPicker: React.FC< UnifiedDesignPickerProps > = ( { isMultiFilterEnabled={ isMultiFilterEnabled } onChangeTier={ onChangeTier } isBigSkyEligible={ isBigSkyEligible } + recommendedDesignSlugs={ recommendedDesignSlugs } /> inView && onViewAllDesigns() } /> From 6148aaa70b3271273f3071be38677b6bb6aec7c5 Mon Sep 17 00:00:00 2001 From: arthur Date: Wed, 11 Dec 2024 17:50:27 +0800 Subject: [PATCH 2/5] Design Picker: Don't show recommended themes if the selected categories have been changed --- .../src/components/unified-design-picker.tsx | 21 +++++++++++-------- .../src/hooks/use-categorization.ts | 19 +++++++++++++++-- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/packages/design-picker/src/components/unified-design-picker.tsx b/packages/design-picker/src/components/unified-design-picker.tsx index 572a9f0c4ca91c..e84e6cb1adf3e5 100644 --- a/packages/design-picker/src/components/unified-design-picker.tsx +++ b/packages/design-picker/src/components/unified-design-picker.tsx @@ -384,14 +384,17 @@ const DesignPicker: React.FC< DesignPickerProps > = ( { - { isMultiFilterEnabled && recommendedDesigns.length === 3 && ( - - ) } + { /* Show recommended themes only when the selected categories are never changed. */ } + { isMultiFilterEnabled && + ! categorization?.isSelectionsChanged && + recommendedDesigns.length === 3 && ( + + ) } { isMultiFilterEnabled && categorization && categorization.selections.length > 1 && ( = ( { isBigSkyEligible = false, recommendedDesignSlugs = [], } ) => { - const hasCategories = !! Object.keys( categorization?.categories || {} ).length; + const hasCategories = !! ( categorization?.categories || [] ).length; return (
void; } @@ -27,6 +28,7 @@ export function useCategorization( }: UseCategorizationOptions ): Categorization { const isInitRef = useRef( false ); + const [ isSelectionsChanged, setIsSelectionsChanged ] = useState( false ); const categories = useMemo( () => { const categoryMapKeys = Object.keys( categoryMap ) || []; const result = categoryMapKeys.map( ( slug ) => ( { @@ -47,6 +49,10 @@ export function useCategorization( return; } + if ( ! isSelectionsChanged ) { + setIsSelectionsChanged( true ); + } + const index = selectedCategories.findIndex( ( selection ) => selection === value ); if ( index === -1 ) { handleSelect?.( value ); @@ -59,7 +65,15 @@ export function useCategorization( ...selectedCategories.slice( index + 1 ), ] ); }, - [ selectedCategories, isMultiSelection, setSelectedCategories, handleSelect, handleDeselect ] + [ + selectedCategories, + isMultiSelection, + isSelectionsChanged, + setSelectedCategories, + handleSelect, + handleDeselect, + setIsSelectionsChanged, + ] ); useEffect( () => { @@ -72,6 +86,7 @@ export function useCategorization( return { categories, selections: selectedCategories, + isSelectionsChanged, onSelect, }; } From ffac8a0b81c035e390ca77db818487b070f2eeb0 Mon Sep 17 00:00:00 2001 From: arthur Date: Thu, 12 Dec 2024 10:39:13 +0800 Subject: [PATCH 3/5] Fix types --- .../design-setup/unified-design-picker.tsx | 2 +- .../src/starter-designs-queries/types.ts | 14 ++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/design-setup/unified-design-picker.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/design-setup/unified-design-picker.tsx index cf60570142553a..ed7f3fdaab31dc 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/design-setup/unified-design-picker.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/design-setup/unified-design-picker.tsx @@ -969,7 +969,7 @@ const UnifiedDesignPickerStep: Step = ( { navigation, flow, stepName } ) => { isMultiFilterEnabled={ isGoalCentricFeature } onChangeTier={ handleChangeTier } isBigSkyEligible={ isBigSkyEligible } - recommendedDesignSlugs={ allDesigns.recommendation || [] } + recommendedDesignSlugs={ allDesigns?.recommendation || [] } /> ); diff --git a/packages/data-stores/src/starter-designs-queries/types.ts b/packages/data-stores/src/starter-designs-queries/types.ts index 288e7e636d6701..3c0d4a1586a14a 100644 --- a/packages/data-stores/src/starter-designs-queries/types.ts +++ b/packages/data-stores/src/starter-designs-queries/types.ts @@ -1,17 +1,7 @@ -import type { Category, DesignRecipe, Design } from '@automattic/design-picker/src/types'; - -export interface StarterDesignsGeneratedQueryParams { - seed?: string; - _locale: string; -} - -export interface StarterDesignsGenerated { - slug: string; - title: string; - recipe: DesignRecipe; -} +import type { Category, Design } from '@automattic/design-picker/src/types'; export interface StarterDesigns { filters: { subject: Record< string, Category > }; designs: Design[]; + recommendation: string[]; } From 9b3ac06a65fcdf5d842350b6bcadd7a2f706caa4 Mon Sep 17 00:00:00 2001 From: arthur Date: Thu, 12 Dec 2024 11:02:55 +0800 Subject: [PATCH 4/5] Show no results only when the recommended designs section is hidden --- .../src/components/unified-design-picker.tsx | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/packages/design-picker/src/components/unified-design-picker.tsx b/packages/design-picker/src/components/unified-design-picker.tsx index e84e6cb1adf3e5..370e6606a13414 100644 --- a/packages/design-picker/src/components/unified-design-picker.tsx +++ b/packages/design-picker/src/components/unified-design-picker.tsx @@ -304,9 +304,7 @@ const DesignPicker: React.FC< DesignPickerProps > = ( { const translate = useTranslate(); const { all, best, ...designsByGroup } = useFilteredDesignsByGroup( designs ); const categories = categorization?.categories || []; - const isNoResults = Object.values( designsByGroup ).every( - ( categoryDesigns ) => categoryDesigns.length === 0 - ); + const categoryTypes = useMemo( () => categories.filter( ( { slug } ) => isFeatureCategory( slug ) ), [ categorization?.categories ] @@ -325,6 +323,17 @@ const DesignPicker: React.FC< DesignPickerProps > = ( { .slice( 0, 3 ); }, [ designs, recommendedDesignSlugs ] ); + // Show recommended themes only when the selected categories are never changed. + const showRecommendedDesigns = + isMultiFilterEnabled && + ! categorization?.isSelectionsChanged && + recommendedDesigns.length === 3; + + // Show no results only when the recommended themes is hidden and no design matches the selected categories and tiers. + const showNoResults = + ! showRecommendedDesigns && + Object.values( designsByGroup ).every( ( categoryDesigns ) => categoryDesigns.length === 0 ); + const getCategoryName = ( value: string ) => categories.find( ( { slug } ) => slug === value )?.name || ''; @@ -384,17 +393,14 @@ const DesignPicker: React.FC< DesignPickerProps > = ( {
- { /* Show recommended themes only when the selected categories are never changed. */ } - { isMultiFilterEnabled && - ! categorization?.isSelectionsChanged && - recommendedDesigns.length === 3 && ( - - ) } + { showRecommendedDesigns && ( + + ) } { isMultiFilterEnabled && categorization && categorization.selections.length > 1 && ( = ( { } category={ categorySlug } designs={ categoryDesigns } - showNoResults={ index === array.length - 1 && isNoResults } + showNoResults={ index === array.length - 1 && showNoResults } /> ) ) } From 43e8785c05bed9b93f1ab576a3eb0e1f45e1b85a Mon Sep 17 00:00:00 2001 From: arthur Date: Thu, 12 Dec 2024 11:04:39 +0800 Subject: [PATCH 5/5] Fix track property --- .../steps-repository/design-setup/hooks/use-track-filters.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/design-setup/hooks/use-track-filters.ts b/client/landing/stepper/declarative-flow/internals/steps-repository/design-setup/hooks/use-track-filters.ts index 4cd55a63aa9faa..d90199f6c57833 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/design-setup/hooks/use-track-filters.ts +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/design-setup/hooks/use-track-filters.ts @@ -21,7 +21,7 @@ const useTrackFilters = ( { preselectedFilters, isBigSkyEligible, isMultiSelecti ( result, filterSlug, index ) => ( { ...result, // The property cannot contain `-` character. - [ `filters_${ filterSlug.replace( '-', '_' ) }` ]: `${ getCategoryType( + [ `filters_${ filterSlug.replaceAll( '-', '_' ) }` ]: `${ getCategoryType( filterSlug ) }:${ index }`, } ),