|
|
@@ -52,9 +52,9 @@ et sélectionner des éléments organisés en catégories et sous-catégories.
|
|
|
v-if="maxVisibleChips && index < maxVisibleChips"
|
|
|
:key="item.raw.value"
|
|
|
closable
|
|
|
- @click:close="removeItem(item.raw.value!)"
|
|
|
+ @click:close="removeItem(String(item.raw.value!))"
|
|
|
>
|
|
|
- {{ selectedItemsMap[item.raw] || selectedItemsMap[item.raw.value] }}
|
|
|
+ {{ selectedItemsMap[item.raw.value] }}
|
|
|
</v-chip>
|
|
|
<span
|
|
|
v-if="
|
|
|
@@ -122,20 +122,20 @@ et sélectionner des éléments organisés en catégories et sous-catégories.
|
|
|
|
|
|
<template v-else>
|
|
|
<v-list-item
|
|
|
- :active="modelValue.includes(item.raw.value!)"
|
|
|
+ :active="modelValue.includes(String(item.raw.value!))"
|
|
|
:class="{
|
|
|
'd-flex': true,
|
|
|
'pl-12': item.raw.level === 2,
|
|
|
'pl-8': item.raw.level === 1,
|
|
|
}"
|
|
|
- @click="toggleItem(item.raw.value!)"
|
|
|
+ @click="toggleItem(String(item.raw.value!))"
|
|
|
>
|
|
|
<template #prepend>
|
|
|
<v-checkbox
|
|
|
- :model-value="modelValue.includes(item.raw.value!)"
|
|
|
+ :model-value="modelValue.includes(String(item.raw.value!))"
|
|
|
color="primary"
|
|
|
:hide-details="true"
|
|
|
- @click.stop="toggleItem(item.raw.value!)"
|
|
|
+ @click.stop="toggleItem(String(item.raw.value!))"
|
|
|
/>
|
|
|
</template>
|
|
|
<v-list-item-title>
|
|
|
@@ -150,7 +150,8 @@ et sélectionner des éléments organisés en catégories et sous-catégories.
|
|
|
<script setup lang="ts">
|
|
|
import StringUtils from '~/services/utils/stringUtils'
|
|
|
import _ from 'lodash'
|
|
|
-import type { PropType } from 'vue'
|
|
|
+import { ref, computed, nextTick, type PropType, type Ref } from 'vue'
|
|
|
+import type { TreeSelectItem } from '~/types/layout'
|
|
|
|
|
|
interface SelectItem {
|
|
|
id: string
|
|
|
@@ -162,13 +163,14 @@ interface SelectItem {
|
|
|
level: number
|
|
|
}
|
|
|
|
|
|
+
|
|
|
const props = defineProps({
|
|
|
modelValue: {
|
|
|
type: Array as PropType<string[]>,
|
|
|
required: true,
|
|
|
},
|
|
|
items: {
|
|
|
- type: Array as PropType<SelectItem[]>,
|
|
|
+ type: Array as PropType<TreeSelectItem[]>,
|
|
|
required: true,
|
|
|
},
|
|
|
maxVisibleChips: {
|
|
|
@@ -275,7 +277,7 @@ const expandParentsOfSelectedItems = () => {
|
|
|
expandedSubcategories.value.clear()
|
|
|
|
|
|
for (const selectedId of props.modelValue) {
|
|
|
- const item = normalizedItems.value.find((i) => i.value === selectedId)
|
|
|
+ const item = normalizedItems.value.find((i) => i.value === Number(selectedId))
|
|
|
if (!item) continue
|
|
|
|
|
|
let parentId = null
|
|
|
@@ -472,10 +474,10 @@ const anyWordStartsWith = (
|
|
|
*
|
|
|
* The matching is done by checking if any word in the normalized label starts with the normalized search text.
|
|
|
*
|
|
|
- * @param {SelectItem} item - The item to evaluate against the search text.
|
|
|
+ * @param {TreeSelectItem} item - The item to evaluate against the search text.
|
|
|
* @returns {boolean} `true` if the item or its relevant parent(s) match the search text; otherwise, `false`.
|
|
|
*/
|
|
|
-const itemMatchesSearch = (item: SelectItem): boolean => {
|
|
|
+const itemMatchesSearch = (item: TreeSelectItem): boolean => {
|
|
|
if (!searchText.value) return true
|
|
|
|
|
|
const normalizedSearch = StringUtils.normalize(searchText.value)
|
|
|
@@ -534,9 +536,9 @@ const itemMatchesSearch = (item: SelectItem): boolean => {
|
|
|
/**
|
|
|
* 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.
|
|
|
+ * @returns {TreeSelectItem[]} Les éléments de niveau 2 qui correspondent à la recherche.
|
|
|
*/
|
|
|
-const findMatchingLevel2Items = (): SelectItem[] => {
|
|
|
+const findMatchingLevel2Items = (): TreeSelectItem[] => {
|
|
|
return normalizedItems.value.filter(
|
|
|
(item) =>
|
|
|
item.type === 'item' &&
|
|
|
@@ -549,11 +551,13 @@ const findMatchingLevel2Items = (): SelectItem[] => {
|
|
|
* 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.
|
|
|
+ * @param {TreeSelectItem[]} matchingItems - Les éléments correspondant à la recherche.
|
|
|
+ * @returns {TreeSelectItem[]} Liste hiérarchique incluant les éléments et leurs parents.
|
|
|
*/
|
|
|
-const buildSearchResultsList = (matchingItems: SelectItem[]): SelectItem[] => {
|
|
|
- const result: SelectItem[] = []
|
|
|
+const buildSearchResultsList = (
|
|
|
+ matchingItems: TreeSelectItem[],
|
|
|
+): TreeSelectItem[] => {
|
|
|
+ const result: TreeSelectItem[] = []
|
|
|
const addedCategoryIds = new Set<string>()
|
|
|
const addedSubcategoryIds = new Set<string>()
|
|
|
|
|
|
@@ -595,13 +599,13 @@ const buildSearchResultsList = (matchingItems: SelectItem[]): SelectItem[] => {
|
|
|
* 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 {TreeSelectItem[]} items - Les éléments à traiter.
|
|
|
+ * @param {TreeSelectItem[]} result - Le tableau résultat à remplir.
|
|
|
* @param {boolean} parentExpanded - Indique si le parent est développé.
|
|
|
*/
|
|
|
const processItemsRecursively = (
|
|
|
- items: SelectItem[],
|
|
|
- result: SelectItem[],
|
|
|
+ items: TreeSelectItem[],
|
|
|
+ result: TreeSelectItem[],
|
|
|
parentExpanded = true,
|
|
|
): void => {
|
|
|
for (const item of items) {
|
|
|
@@ -635,10 +639,10 @@ const processItemsRecursively = (
|
|
|
/**
|
|
|
* 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.
|
|
|
+ * @returns {TreeSelectItem[]} Liste hiérarchique basée sur l'état d'expansion.
|
|
|
*/
|
|
|
-const buildNormalModeList = (): SelectItem[] => {
|
|
|
- const result: SelectItem[] = []
|
|
|
+const buildNormalModeList = (): TreeSelectItem[] => {
|
|
|
+ const result: TreeSelectItem[] = []
|
|
|
const topLevelItems = normalizedItems.value.filter((item) => !item.parentId)
|
|
|
processItemsRecursively(topLevelItems, result)
|
|
|
return result
|
|
|
@@ -649,7 +653,7 @@ const buildNormalModeList = (): SelectItem[] => {
|
|
|
* from a hierarchical structure, based on the current search text and
|
|
|
* expanded categories/subcategories.
|
|
|
*
|
|
|
- * @returns {SelectItem[]} Flattened and organized list of items.
|
|
|
+ * @returns {TreeSelectItem[]} Flattened and organized list of items.
|
|
|
*/
|
|
|
const flattenedItems = computed(() => {
|
|
|
const hasSearch = !!searchText.value.trim()
|