소스 검색

Adds Event Categories Tree Select Component

Introduces a new component for selecting event categories using a hierarchical tree select.

This allows users to easily select categories and subcategories by representing event categories in a structured tree format, improving the user experience for category selection.
It also adds EventCategory model
Olivier Massot 4 달 전
부모
커밋
3a5f12f0f1
4개의 변경된 파일162개의 추가작업 그리고 2개의 파일을 삭제
  1. 1 1
      components/Ui/Input/TreeSelect.vue
  2. 117 0
      components/Ui/Input/TreeSelect/EventCategories.vue
  3. 26 0
      models/Core/EventCategory.ts
  4. 18 1
      pages/dev/poc_tree_select_input.vue

+ 1 - 1
components/Ui/Input/TreeSelect.vue

@@ -22,7 +22,7 @@ et sélectionner des éléments organisés en catégories et sous-catégories.
     multiple
     chips
     closable-chips
-    :menu-props="{ maxHeight: 500 }"
+    :menu-props="{ maxHeight: 400 }"
     @update:menu="onMenuUpdate"
     @update:model-value="$emit('update:modelValue', $event)"
   >

+ 117 - 0
components/Ui/Input/TreeSelect/EventCategories.vue

@@ -0,0 +1,117 @@
+<template>
+  <UiInputTreeSelect
+    :model-value="modelValue"
+    :items="hierarchicalItems"
+    v-bind="$attrs"
+    :loading="pending"
+    @update:model-value="$emit('update:modelValue', $event)"
+  />
+</template>
+
+<script setup lang="ts">
+import { useEntityFetch } from '~/composables/data/useEntityFetch'
+import EventCategory from '~/models/Core/EventCategory'
+
+const props = defineProps({
+  modelValue: {
+    type: Array as PropType<string[]>,
+    required: true
+  }
+})
+
+const i18n = useI18n()
+
+const { fetchCollection } = useEntityFetch()
+
+const { data: categories, pending } = fetchCollection(EventCategory)
+
+// Transform event categories into hierarchical items for TreeSelect
+const hierarchicalItems = computed(() => {
+  if (!categories.value || categories.value.length === 0) {
+    return []
+  }
+
+  const result = []
+  const familiesMap = new Map()
+  const subFamiliesMap = new Map()
+
+  // First pass: collect all unique families and subfamilies
+  categories.value.items.forEach(category => {
+    if (!category.famillyLabel || !category.subfamillyLabel || !category.genderLabel) return
+
+    // Create unique keys for families and subfamilies
+    const familyKey = category.famillyLabel
+    const subfamilyKey = `${category.famillyLabel}-${category.subfamillyLabel}`
+
+    // Add family if not already added
+    if (!familiesMap.has(familyKey)) {
+      familiesMap.set(familyKey, {
+        id: `family-${familyKey}`,
+        label: i18n.t(category.famillyLabel),
+        type: 'category',
+        level: 0
+      })
+    }
+
+    // Add subfamily if not already added
+    if (!subFamiliesMap.has(subfamilyKey)) {
+      subFamiliesMap.set(subfamilyKey, {
+        id: `subfamily-${subfamilyKey}`,
+        label: i18n.t(category.subfamillyLabel),
+        type: 'subcategory',
+        parentId: `family-${familyKey}`,
+        level: 1
+      })
+    }
+  })
+
+  // Convert families map to array and sort alphabetically by label
+  const sortedFamilies = Array.from(familiesMap.values()).sort((a, b) =>
+    a.label.localeCompare(b.label)
+  )
+
+  // Add sorted families to result
+  sortedFamilies.forEach(family => {
+    result.push(family)
+  })
+
+  // Convert subfamilies map to array and sort alphabetically by label
+  const sortedSubfamilies = Array.from(subFamiliesMap.values()).sort((a, b) =>
+    a.label.localeCompare(b.label)
+  )
+
+  // Add sorted subfamilies to result
+  sortedSubfamilies.forEach(subfamily => {
+    result.push(subfamily)
+  })
+
+  // Collect all genders first, then sort and add to result
+  const genders = []
+  categories.value.items.forEach(category => {
+    if (!category.famillyLabel || !category.subfamillyLabel || !category.genderLabel) return
+
+    const familyKey = category.famillyLabel
+    const subfamilyKey = `${category.famillyLabel}-${category.subfamillyLabel}`
+
+    genders.push({
+      id: `gender-${category.id}`,
+      label: i18n.t(category.genderLabel),
+      value: category.id.toString(),
+      type: 'item',
+      parentId: `subfamily-${subfamilyKey}`,
+      level: 2
+    })
+  })
+
+  // Sort genders alphabetically by label and add to result
+  genders.sort((a, b) => a.label.localeCompare(b.label)).forEach(gender => {
+    result.push(gender)
+  })
+
+  return result
+})
+</script>
+
+<style scoped lang="scss">
+/* No specific styles needed */
+</style>

+ 26 - 0
models/Core/EventCategory.ts

@@ -0,0 +1,26 @@
+import { Num, Str, Uid } from 'pinia-orm/dist/decorators'
+import ApiResource from '~/models/ApiResource'
+
+/**
+ * Event Category model
+ *
+ * Represents a category for events with family, subfamily, and gender information
+ */
+export default class EventCategory extends ApiResource {
+  static entity = 'event-categories'
+
+  @Uid()
+  declare id: number | string | null
+
+  @Str('')
+  declare label: string
+
+  @Str('')
+  declare famillyLabel: string
+
+  @Str('')
+  declare subfamillyLabel: string
+
+  @Str('')
+  declare genderLabel: string
+}

+ 18 - 1
pages/dev/poc_tree_select_input.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="pa-4">
-    <h2>Select Hiérarchique</h2>
+    <h2>Select Hiérarchique - Exemple de base</h2>
 
     <UiInputTreeSelect
       v-model="selectedValues"
@@ -15,11 +15,28 @@
       <h3>Valeurs sélectionnées :</h3>
       <pre>{{ selectedValues }}</pre>
     </div>
+
+    <v-divider class="my-6"></v-divider>
+
+    <h2>Select Hiérarchique - Catégories d'événements</h2>
+
+    <UiInputTreeSelectEventCategories
+      v-model="selectedCategories"
+      label="Choisissez des catégories"
+      placeholder="Sélectionnez des catégories..."
+      :max-visible-chips="3"
+    />
+
+    <div class="mt-4">
+      <h3>Catégories sélectionnées :</h3>
+      <pre>{{ selectedCategories }}</pre>
+    </div>
   </div>
 </template>
 
 <script setup lang="ts">
 const selectedValues = ref<string[]>([])
+const selectedCategories = ref<string[]>([])
 
 const hierarchicalItems = ref([
   // Catégories principales