Separated multi and single category component
I also disabled secondary categories because they shouldn't be used right now, it adds too much complexity
This commit is contained in:
@@ -142,10 +142,18 @@ function handleCancel() {
|
|||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<PhTag size="18" weight="fill" />
|
<PhTag size="18" weight="fill" />
|
||||||
|
|
||||||
<CalendarInputEventCategories v-model="eventSkeleton.category" placeholder="Ajouter une catégorie principale" />
|
<CalendarInputEventCategory v-model="eventSkeleton.category" placeholder="Ajouter une catégorie principale" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- <div class="col-span-2">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<PhTag size="18" weight="fill" />
|
||||||
|
|
||||||
|
<CalendarInputEventCategories v-model="eventSkeleton.secondaryCategories" placeholder="Ajouter des catégories secondaires" />
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
<div class="col-span-2 mb-2">
|
<div class="col-span-2 mb-2">
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<PhMapPinArea size="18" weight="fill" />
|
<PhMapPinArea size="18" weight="fill" />
|
||||||
|
|||||||
@@ -133,10 +133,22 @@ function handleCancel() {
|
|||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<PhTag size="18" weight="fill" />
|
<PhTag size="18" weight="fill" />
|
||||||
|
|
||||||
<CalendarInputEventCategories v-model="eventSkeleton.category" placeholder="Ajouter une catégorie principale" />
|
<div class="w-1/2">
|
||||||
|
<CalendarInputEventCategory v-model="eventSkeleton.category" placeholder="Ajouter une catégorie principale" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- <div class="col-span-2">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<PhTag size="18" weight="fill" />
|
||||||
|
|
||||||
|
<div class="w-1/2">
|
||||||
|
<CalendarInputEventCategories v-model="eventSkeleton.secondaryCategories" placeholder="Ajouter des catégories secondaires" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
<div class="col-span-2 mb-2">
|
<div class="col-span-2 mb-2">
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<PhMapPinArea size="18" weight="fill" />
|
<PhMapPinArea size="18" weight="fill" />
|
||||||
|
|||||||
@@ -1,38 +1,26 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { PhCaretDown } from '@phosphor-icons/vue';
|
import { cn } from '@/lib/utils'
|
||||||
import type { Category } from '~/models/Category';
|
import type { Category } from '~/models/Category';
|
||||||
|
|
||||||
|
import { PhCaretDown, PhCheck } from '@phosphor-icons/vue';
|
||||||
|
|
||||||
const isPopoverOpen = ref<boolean>(false)
|
const isPopoverOpen = ref<boolean>(false)
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
multiple?: boolean
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const computedTextValue = computed(() => {
|
const model = defineModel<Category[]>({ default: [] })
|
||||||
if (model.value) {
|
const modelBuffer = ref<Category[]>([])
|
||||||
if ("name" in model.value) {
|
|
||||||
return model.value.name
|
|
||||||
} else {
|
|
||||||
return model.value[0].name
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return props.placeholder
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const model = defineModel<Category[] | Category>()
|
watch(modelBuffer.value, () => {
|
||||||
|
model.value = [ ...modelBuffer.value ]
|
||||||
|
})
|
||||||
|
|
||||||
const { categories: availableCategories } = useCalendarEvents()
|
const { categories: availableCategories } = useCalendarEvents()
|
||||||
|
|
||||||
const searchTerm = ref<string>('')
|
const searchTerm = ref<string>('')
|
||||||
|
|
||||||
function handleCatSelect() {
|
|
||||||
if (!props.multiple) {
|
|
||||||
isPopoverOpen.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const filteredCategories = computed(() =>
|
const filteredCategories = computed(() =>
|
||||||
searchTerm.value === ''
|
searchTerm.value === ''
|
||||||
? availableCategories
|
? availableCategories
|
||||||
@@ -48,9 +36,20 @@ const filteredCategories = computed(() =>
|
|||||||
<UiButton
|
<UiButton
|
||||||
variant="outline"
|
variant="outline"
|
||||||
role="combobox"
|
role="combobox"
|
||||||
class="w-fit max-w-full justify-between"
|
class="relative w-full max-w-full h-fit justify-between"
|
||||||
>
|
>
|
||||||
{{ computedTextValue }}
|
<template v-if="!model.length">
|
||||||
|
{{ props.placeholder }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<ul class="flex flex-wrap gap-1">
|
||||||
|
<li v-for="category in model" :key="`selected-cat-${category.id}`">
|
||||||
|
<UiBadge class="lowercase" variant="secondary">
|
||||||
|
{{ category.name }}
|
||||||
|
</UiBadge>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
|
||||||
<PhCaretDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
<PhCaretDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
</UiButton>
|
</UiButton>
|
||||||
@@ -61,7 +60,7 @@ const filteredCategories = computed(() =>
|
|||||||
:collision-padding="50"
|
:collision-padding="50"
|
||||||
class="w-fit h-[33vh] p-0"
|
class="w-fit h-[33vh] p-0"
|
||||||
>
|
>
|
||||||
<UiCommand v-model="model" v-model:searchTerm="searchTerm" :multiple>
|
<UiCommand v-model="modelBuffer" v-model:searchTerm="searchTerm" :multiple="true">
|
||||||
<UiCommandInput placeholder="Rechercher les catégories" />
|
<UiCommandInput placeholder="Rechercher les catégories" />
|
||||||
<UiCommandEmpty>Aucune catégorie trouvée.</UiCommandEmpty>
|
<UiCommandEmpty>Aucune catégorie trouvée.</UiCommandEmpty>
|
||||||
<UiCommandList>
|
<UiCommandList>
|
||||||
@@ -70,10 +69,16 @@ const filteredCategories = computed(() =>
|
|||||||
v-for="category in filteredCategories"
|
v-for="category in filteredCategories"
|
||||||
:key="category.id"
|
:key="category.id"
|
||||||
:value="category"
|
:value="category"
|
||||||
class="cursor-pointer"
|
class="cursor-pointer flex justify-between items-center"
|
||||||
@select="handleCatSelect"
|
:class="cn({
|
||||||
|
|
||||||
|
})"
|
||||||
>
|
>
|
||||||
{{ category.name }}
|
<span>
|
||||||
|
{{ category.name }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<PhCheck v-if="model.find(cat => cat.id === category.id)" />
|
||||||
</UiCommandItem>
|
</UiCommandItem>
|
||||||
</UiCommandGroup>
|
</UiCommandGroup>
|
||||||
</UiCommandList>
|
</UiCommandList>
|
||||||
|
|||||||
73
components/calendar/input/EventCategory.vue
Normal file
73
components/calendar/input/EventCategory.vue
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { PhCaretDown } from '@phosphor-icons/vue';
|
||||||
|
import type { Category } from '~/models/Category';
|
||||||
|
|
||||||
|
const isPopoverOpen = ref<boolean>(false)
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
placeholder?: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const model = defineModel<Category>()
|
||||||
|
|
||||||
|
const { categories: availableCategories } = useCalendarEvents()
|
||||||
|
|
||||||
|
const searchTerm = ref<string>('')
|
||||||
|
|
||||||
|
function handleCatSelect() {
|
||||||
|
isPopoverOpen.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const filteredCategories = computed(() =>
|
||||||
|
searchTerm.value === ''
|
||||||
|
? availableCategories
|
||||||
|
: availableCategories.filter((category) => {
|
||||||
|
return category.name.toLowerCase().includes(searchTerm.value.toLowerCase())
|
||||||
|
})
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UiPopover v-model:open="isPopoverOpen">
|
||||||
|
<UiPopoverTrigger as-child>
|
||||||
|
<UiButton
|
||||||
|
variant="outline"
|
||||||
|
role="combobox"
|
||||||
|
class="w-full max-w-full justify-between"
|
||||||
|
>
|
||||||
|
<template v-if="!model">
|
||||||
|
{{ props.placeholder }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ model.name }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<PhCaretDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</UiButton>
|
||||||
|
</UiPopoverTrigger>
|
||||||
|
<UiPopoverContent
|
||||||
|
align="start"
|
||||||
|
side="bottom"
|
||||||
|
:collision-padding="50"
|
||||||
|
class="w-fit h-[33vh] p-0"
|
||||||
|
>
|
||||||
|
<UiCommand v-model="model" v-model:searchTerm="searchTerm">
|
||||||
|
<UiCommandInput placeholder="Rechercher les catégories" />
|
||||||
|
<UiCommandEmpty>Aucune catégorie trouvée.</UiCommandEmpty>
|
||||||
|
<UiCommandList>
|
||||||
|
<UiCommandGroup>
|
||||||
|
<UiCommandItem
|
||||||
|
v-for="category in filteredCategories"
|
||||||
|
:key="category.id"
|
||||||
|
:value="category"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@select="handleCatSelect"
|
||||||
|
>
|
||||||
|
{{ category.name }}
|
||||||
|
</UiCommandItem>
|
||||||
|
</UiCommandGroup>
|
||||||
|
</UiCommandList>
|
||||||
|
</UiCommand>
|
||||||
|
</UiPopoverContent>
|
||||||
|
</UiPopover>
|
||||||
|
</template>
|
||||||
Reference in New Issue
Block a user