|
|
@@ -169,106 +169,6 @@ const onMenuUpdate = (isOpen: boolean) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * A computed property that generates a flattened and organized list of items
|
|
|
- * from a hierarchical structure, based on the current search text and
|
|
|
- * expanded categories/subcategories.
|
|
|
- *
|
|
|
- * Logic:
|
|
|
- * - If there is a search text:
|
|
|
- * - Filters items to include only level 2 items matching the search text.
|
|
|
- * - Ensures parent categories and subcategories are added to the result.
|
|
|
- * - Expands categories and subcategories relevant to search results.
|
|
|
- * - Without a search text:
|
|
|
- * - Recursively processes items to include all relevant categories,
|
|
|
- * subcategories, and individual items based on the expanded states.
|
|
|
- *
|
|
|
- * @returns {SelectItem[]} Flattened and organized list of items.
|
|
|
- */
|
|
|
-const flattenedItems = computed(() => {
|
|
|
- const result: SelectItem[] = []
|
|
|
- const hasSearch = !!searchText.value.trim()
|
|
|
- // TODO: simplifier et découper
|
|
|
-
|
|
|
- // Si une recherche est active, afficher uniquement les éléments de niveau 2 qui correspondent
|
|
|
- if (hasSearch) {
|
|
|
- // Trouver tous les éléments de niveau 2 qui correspondent à la recherche
|
|
|
- const matchingItems = props.items.filter(item =>
|
|
|
- item.type === 'item' &&
|
|
|
- item.level === 2 &&
|
|
|
- itemMatchesSearch(item)
|
|
|
- )
|
|
|
-
|
|
|
- // Ensemble pour suivre les catégories et sous-catégories déjà ajoutées
|
|
|
- const addedCategoryIds = new Set<string>()
|
|
|
- const addedSubcategoryIds = new Set<string>()
|
|
|
-
|
|
|
- // Pour chaque élément correspondant, ajouter sa hiérarchie complète
|
|
|
- for (const item of matchingItems) {
|
|
|
- // Trouver la sous-catégorie parente
|
|
|
- const subcategory = props.items.find(i => i.id === item.parentId)
|
|
|
- if (!subcategory) continue
|
|
|
-
|
|
|
- // Trouver la catégorie parente
|
|
|
- const category = props.items.find(i => i.id === subcategory.parentId)
|
|
|
- if (!category) continue
|
|
|
-
|
|
|
- // Ajouter la catégorie si elle n'est pas déjà présente
|
|
|
- if (!addedCategoryIds.has(category.id)) {
|
|
|
- result.push(category)
|
|
|
- addedCategoryIds.add(category.id)
|
|
|
- // S'assurer que la catégorie est considérée comme "expanded" pendant la recherche
|
|
|
- expandedCategories.value.add(category.id)
|
|
|
- }
|
|
|
-
|
|
|
- // Ajouter la sous-catégorie si elle n'est pas déjà présente
|
|
|
- if (!addedSubcategoryIds.has(subcategory.id)) {
|
|
|
- result.push(subcategory)
|
|
|
- addedSubcategoryIds.add(subcategory.id)
|
|
|
- // S'assurer que la sous-catégorie est considérée comme "expanded" pendant la recherche
|
|
|
- expandedSubcategories.value.add(subcategory.id)
|
|
|
- }
|
|
|
-
|
|
|
- // Ajouter l'élément
|
|
|
- result.push(item)
|
|
|
- }
|
|
|
-
|
|
|
- return result
|
|
|
- }
|
|
|
-
|
|
|
- // Comportement normal sans recherche
|
|
|
- const processItems = (items: SelectItem[], parentExpanded = true) => {
|
|
|
- for (const item of items) {
|
|
|
- if (item.type === 'category') {
|
|
|
- result.push(item)
|
|
|
- if (expandedCategories.value.has(item.id)) {
|
|
|
- const subcategories = props.items.filter(i =>
|
|
|
- i.parentId === item.id && i.type === 'subcategory'
|
|
|
- )
|
|
|
- processItems(subcategories, true)
|
|
|
- }
|
|
|
- } else if (item.type === 'subcategory') {
|
|
|
- if (parentExpanded) {
|
|
|
- result.push(item)
|
|
|
- if (expandedSubcategories.value.has(item.id)) {
|
|
|
- const subItems = props.items.filter(i =>
|
|
|
- i.parentId === item.id && i.type === 'item'
|
|
|
- )
|
|
|
- processItems(subItems, true)
|
|
|
- }
|
|
|
- }
|
|
|
- } else if (item.type === 'item' && parentExpanded) {
|
|
|
- result.push(item)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const topLevelItems = props.items.filter(item => !item.parentId)
|
|
|
- processItems(topLevelItems)
|
|
|
-
|
|
|
- return result
|
|
|
-})
|
|
|
-
|
|
|
/**
|
|
|
* Toggles the expanded state of a given category. If the category is currently
|
|
|
* expanded, it will collapse the category and also collapse its subcategories.
|
|
|
@@ -410,6 +310,129 @@ const itemMatchesSearch = (item: SelectItem): boolean => {
|
|
|
// Pour les autres types d'éléments, vérifier simplement leur label
|
|
|
return StringUtils.normalize(item.label).includes(normalizedSearch)
|
|
|
}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Filtre les éléments de niveau 2 qui correspondent au texte de recherche.
|
|
|
+ *
|
|
|
+ * @returns {SelectItem[]} Les éléments de niveau 2 qui correspondent à la recherche.
|
|
|
+ */
|
|
|
+const findMatchingLevel2Items = (): SelectItem[] => {
|
|
|
+ return props.items.filter(item =>
|
|
|
+ item.type === 'item' &&
|
|
|
+ item.level === 2 &&
|
|
|
+ itemMatchesSearch(item)
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Construit une liste hiérarchique d'éléments basée sur les résultats de recherche.
|
|
|
+ * Pour chaque élément correspondant, ajoute sa hiérarchie complète (catégorie et sous-catégorie).
|
|
|
+ *
|
|
|
+ * @param {SelectItem[]} matchingItems - Les éléments correspondant à la recherche.
|
|
|
+ * @returns {SelectItem[]} Liste hiérarchique incluant les éléments et leurs parents.
|
|
|
+ */
|
|
|
+const buildSearchResultsList = (matchingItems: SelectItem[]): SelectItem[] => {
|
|
|
+ const result: SelectItem[] = []
|
|
|
+ const addedCategoryIds = new Set<string>()
|
|
|
+ const addedSubcategoryIds = new Set<string>()
|
|
|
+
|
|
|
+ for (const item of matchingItems) {
|
|
|
+ // Trouver la sous-catégorie parente
|
|
|
+ const subcategory = props.items.find(i => i.id === item.parentId)
|
|
|
+ if (!subcategory) continue
|
|
|
+
|
|
|
+ // Trouver la catégorie parente
|
|
|
+ const category = props.items.find(i => i.id === subcategory.parentId)
|
|
|
+ if (!category) continue
|
|
|
+
|
|
|
+ // Ajouter la catégorie si elle n'est pas déjà présente
|
|
|
+ if (!addedCategoryIds.has(category.id)) {
|
|
|
+ result.push(category)
|
|
|
+ addedCategoryIds.add(category.id)
|
|
|
+ expandedCategories.value.add(category.id)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Ajouter la sous-catégorie si elle n'est pas déjà présente
|
|
|
+ if (!addedSubcategoryIds.has(subcategory.id)) {
|
|
|
+ result.push(subcategory)
|
|
|
+ addedSubcategoryIds.add(subcategory.id)
|
|
|
+ expandedSubcategories.value.add(subcategory.id)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Ajouter l'élément
|
|
|
+ result.push(item)
|
|
|
+ }
|
|
|
+
|
|
|
+ return result
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Traite récursivement les éléments pour construire une liste hiérarchique
|
|
|
+ * basée sur l'état d'expansion des catégories et sous-catégories.
|
|
|
+ *
|
|
|
+ * @param {SelectItem[]} items - Les éléments à traiter.
|
|
|
+ * @param {SelectItem[]} result - Le tableau résultat à remplir.
|
|
|
+ * @param {boolean} parentExpanded - Indique si le parent est développé.
|
|
|
+ */
|
|
|
+const processItemsRecursively = (
|
|
|
+ items: SelectItem[],
|
|
|
+ result: SelectItem[],
|
|
|
+ parentExpanded = true
|
|
|
+): void => {
|
|
|
+ for (const item of items) {
|
|
|
+ if (item.type === 'category') {
|
|
|
+ result.push(item)
|
|
|
+ if (expandedCategories.value.has(item.id)) {
|
|
|
+ const subcategories = props.items.filter(i =>
|
|
|
+ i.parentId === item.id && i.type === 'subcategory'
|
|
|
+ )
|
|
|
+ processItemsRecursively(subcategories, result, true)
|
|
|
+ }
|
|
|
+ } else if (item.type === 'subcategory') {
|
|
|
+ if (parentExpanded) {
|
|
|
+ result.push(item)
|
|
|
+ if (expandedSubcategories.value.has(item.id)) {
|
|
|
+ const subItems = props.items.filter(i =>
|
|
|
+ i.parentId === item.id && i.type === 'item'
|
|
|
+ )
|
|
|
+ processItemsRecursively(subItems, result, true)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (item.type === 'item' && parentExpanded) {
|
|
|
+ result.push(item)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Construit une liste hiérarchique d'éléments en mode normal (sans recherche).
|
|
|
+ *
|
|
|
+ * @returns {SelectItem[]} Liste hiérarchique basée sur l'état d'expansion.
|
|
|
+ */
|
|
|
+const buildNormalModeList = (): SelectItem[] => {
|
|
|
+ const result: SelectItem[] = []
|
|
|
+ const topLevelItems = props.items.filter(item => !item.parentId)
|
|
|
+ processItemsRecursively(topLevelItems, result)
|
|
|
+ return result
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * A computed property that generates a flattened and organized list of items
|
|
|
+ * from a hierarchical structure, based on the current search text and
|
|
|
+ * expanded categories/subcategories.
|
|
|
+ *
|
|
|
+ * @returns {SelectItem[]} Flattened and organized list of items.
|
|
|
+ */
|
|
|
+const flattenedItems = computed(() => {
|
|
|
+ const hasSearch = !!searchText.value.trim()
|
|
|
+
|
|
|
+ if (hasSearch) {
|
|
|
+ const matchingItems = findMatchingLevel2Items()
|
|
|
+ return buildSearchResultsList(matchingItems)
|
|
|
+ }
|
|
|
+
|
|
|
+ return buildNormalModeList()
|
|
|
+})
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|