1- import type { ComparisonFacet } from '#shared/types'
2- import { ALL_FACETS , DEFAULT_FACETS , FACET_INFO } from '#shared/types/comparison'
1+ import type { ComparisonFacet , FacetInfo } from '#shared/types'
2+ import {
3+ ALL_FACETS ,
4+ CATEGORY_ORDER ,
5+ DEFAULT_FACETS ,
6+ FACET_INFO ,
7+ FACETS_BY_CATEGORY ,
8+ } from '#shared/types/comparison'
39import { useRouteQuery } from '@vueuse/router'
410
11+ /** Facet info enriched with i18n labels */
12+ export interface FacetInfoWithLabels extends Omit < FacetInfo , 'id' > {
13+ id : ComparisonFacet
14+ label : string
15+ description : string
16+ }
17+
518/**
619 * Composable for managing comparison facet selection with URL sync.
720 *
821 * @param queryParam - The URL query parameter name to use (default: 'facets')
922 */
1023export function useFacetSelection ( queryParam = 'facets' ) {
24+ const { t } = useI18n ( )
25+
26+ // Helper to build facet info with i18n labels
27+ function buildFacetInfo ( facet : ComparisonFacet ) : FacetInfoWithLabels {
28+ return {
29+ id : facet ,
30+ ...FACET_INFO [ facet ] ,
31+ label : t ( `compare.facets.items.${ facet } .label` ) ,
32+ description : t ( `compare.facets.items.${ facet } .description` ) ,
33+ }
34+ }
35+
1136 // Sync with URL query param (stable ref - doesn't change on other query changes)
1237 const facetsParam = useRouteQuery < string > ( queryParam , '' , { mode : 'replace' } )
1338
14- // Parse facets from URL or use defaults
15- const selectedFacets = computed < ComparisonFacet [ ] > ( {
39+ // Parse facet IDs from URL or use defaults
40+ const selectedFacetIds = computed < ComparisonFacet [ ] > ( {
1641 get ( ) {
1742 if ( ! facetsParam . value ) {
1843 return DEFAULT_FACETS
@@ -40,21 +65,26 @@ export function useFacetSelection(queryParam = 'facets') {
4065 } ,
4166 } )
4267
68+ // Selected facets with full info and i18n labels
69+ const selectedFacets = computed < FacetInfoWithLabels [ ] > ( ( ) =>
70+ selectedFacetIds . value . map ( buildFacetInfo ) ,
71+ )
72+
4373 // Check if a facet is selected
4474 function isFacetSelected ( facet : ComparisonFacet ) : boolean {
45- return selectedFacets . value . includes ( facet )
75+ return selectedFacetIds . value . includes ( facet )
4676 }
4777
4878 // Toggle a single facet
4979 function toggleFacet ( facet : ComparisonFacet ) : void {
50- const current = selectedFacets . value
80+ const current = selectedFacetIds . value
5181 if ( current . includes ( facet ) ) {
5282 // Don't allow deselecting all facets
5383 if ( current . length > 1 ) {
54- selectedFacets . value = current . filter ( f => f !== facet )
84+ selectedFacetIds . value = current . filter ( f => f !== facet )
5585 }
5686 } else {
57- selectedFacets . value = [ ...current , facet ]
87+ selectedFacetIds . value = [ ...current , facet ]
5888 }
5989 }
6090
@@ -69,36 +99,50 @@ export function useFacetSelection(queryParam = 'facets') {
6999 // Select all facets in a category
70100 function selectCategory ( category : string ) : void {
71101 const categoryFacets = getFacetsInCategory ( category )
72- const current = selectedFacets . value
102+ const current = selectedFacetIds . value
73103 const newFacets = [ ...new Set ( [ ...current , ...categoryFacets ] ) ]
74- selectedFacets . value = newFacets
104+ selectedFacetIds . value = newFacets
75105 }
76106
77107 // Deselect all facets in a category
78108 function deselectCategory ( category : string ) : void {
79109 const categoryFacets = getFacetsInCategory ( category )
80- const remaining = selectedFacets . value . filter ( f => ! categoryFacets . includes ( f ) )
110+ const remaining = selectedFacetIds . value . filter ( f => ! categoryFacets . includes ( f ) )
81111 // Don't allow deselecting all facets
82112 if ( remaining . length > 0 ) {
83- selectedFacets . value = remaining
113+ selectedFacetIds . value = remaining
84114 }
85115 }
86116
87117 // Select all facets globally
88118 function selectAll ( ) : void {
89- selectedFacets . value = DEFAULT_FACETS
119+ selectedFacetIds . value = DEFAULT_FACETS
90120 }
91121
92122 // Deselect all facets globally (keeps first facet to ensure at least one)
93123 function deselectAll ( ) : void {
94- selectedFacets . value = [ DEFAULT_FACETS [ 0 ] as ComparisonFacet ]
124+ selectedFacetIds . value = [ DEFAULT_FACETS [ 0 ] as ComparisonFacet ]
95125 }
96126
97127 // Check if all facets are selected
98- const isAllSelected = computed ( ( ) => selectedFacets . value . length === DEFAULT_FACETS . length )
128+ const isAllSelected = computed ( ( ) => selectedFacetIds . value . length === DEFAULT_FACETS . length )
99129
100130 // Check if only one facet is selected (minimum)
101- const isNoneSelected = computed ( ( ) => selectedFacets . value . length === 1 )
131+ const isNoneSelected = computed ( ( ) => selectedFacetIds . value . length === 1 )
132+
133+ // Get translated category name
134+ function getCategoryLabel ( category : FacetInfo [ 'category' ] ) : string {
135+ return t ( `compare.facets.categories.${ category } ` )
136+ }
137+
138+ // All facets with their info and i18n labels, grouped by category
139+ const facetsByCategory = computed ( ( ) => {
140+ const result : Record < string , FacetInfoWithLabels [ ] > = { }
141+ for ( const category of CATEGORY_ORDER ) {
142+ result [ category ] = FACETS_BY_CATEGORY [ category ] . map ( buildFacetInfo )
143+ }
144+ return result
145+ } )
102146
103147 return {
104148 selectedFacets,
@@ -111,6 +155,10 @@ export function useFacetSelection(queryParam = 'facets') {
111155 isAllSelected,
112156 isNoneSelected,
113157 allFacets : ALL_FACETS ,
158+ // Facet info with i18n
159+ getCategoryLabel,
160+ facetsByCategory,
161+ categoryOrder : CATEGORY_ORDER ,
114162 }
115163}
116164
0 commit comments