refactor: rework TagsSelectizeItem with multiple choices types

This commit is contained in:
axolotle 2024-08-12 23:54:07 +02:00
parent cba781d809
commit 837e92789a
2 changed files with 44 additions and 30 deletions

View file

@ -3,17 +3,14 @@ import type { BDropdown, BFormInput } from 'bootstrap-vue-next'
import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { fromEntries } from '@/helpers/commons'
import type {
BaseItemComputedProps,
Choice,
TagUpdateArgs,
TagsSelectizeItemProps,
} from '@/types/form'
type TagUpdateArgs = {
action: 'add' | 'remove'
option: string
applyFn: (tag: string) => void
}
defineOptions({
inheritAttrs: false,
})
@ -55,19 +52,26 @@ const criteria = computed(() => {
return search.value.trim().toLowerCase()
})
const availableOptions = computed(() => {
const options = props.options.filter((opt) => {
return (
props.modelValue?.indexOf(opt) === -1 &&
props.disabledItems?.includes(opt)
)
})
if (criteria.value) {
return options.filter(
(opt) => opt.toLowerCase().indexOf(criteria.value) > -1,
)
return props.options.filter((opt) => {
const tag = typeof opt === 'string' ? opt : opt.value
let filterIn =
model.value?.indexOf(tag) === -1 &&
!(props.disabledItems?.includes(tag) ?? false)
if (filterIn && criteria.value) {
filterIn = tag.toLowerCase().indexOf(criteria.value) > -1
}
return options
return filterIn
})
})
const texts = computed(() =>
fromEntries(
props.options.map((opt) => {
const tag = typeof opt === 'string' ? opt : opt.value
const text = typeof opt === 'string' ? opt : opt.text
return [tag, text]
}),
),
)
const searchI18n = computed(() => {
const params = { items: t('items.' + props.itemsName, 0) }
return {
@ -80,18 +84,20 @@ const searchState = computed(() => {
return criteria.value && availableOptions.value.length === 0 ? false : null
})
function onAddTag(option: string, applyFn: TagUpdateArgs['applyFn']) {
emit('tag-update', { action: 'add', option, applyFn })
function onAddTag(option: Choice, applyFn: TagUpdateArgs['applyFn']) {
const tag = typeof option === 'string' ? option : option.value
emit('tag-update', { action: 'add', tag, applyFn })
search.value = ''
if (props.auto) {
applyFn(option)
applyFn(tag)
}
}
function onRemoveTag(option: string, applyFn: TagUpdateArgs['applyFn']) {
emit('tag-update', { action: 'remove', option, applyFn })
function onRemoveTag(option: Choice, applyFn: TagUpdateArgs['applyFn']) {
const tag = typeof option === 'string' ? option : option.value
emit('tag-update', { action: 'remove', tag, applyFn })
if (props.auto) {
applyFn(option)
applyFn(tag)
}
}
@ -134,11 +140,11 @@ function onDropdownKeydown(e: KeyboardEvent) {
>
<BFormTag
:title="tag"
:disabled="disabled || disabledItems?.includes(tag)"
:disabled="disabled || (disabledItems?.includes(tag) ?? false)"
class="border border-dark mb-2"
@remove="onRemoveTag(tag, removeTag)"
>
<YIcon v-if="tagIcon" :iname="tagIcon" /> {{ tag }}
<YIcon v-if="tagIcon" :iname="tagIcon" /> {{ texts[tag] }}
</BFormTag>
</li>
</ul>
@ -173,6 +179,7 @@ function onDropdownKeydown(e: KeyboardEvent) {
autocomplete="off"
size="sm"
type="search"
@click.stop
/>
</BFormGroup>
</BDropdownForm>
@ -180,11 +187,11 @@ function onDropdownKeydown(e: KeyboardEvent) {
</BDropdownGroup>
<BDropdownItemButton
v-for="option in availableOptions"
:key="option"
v-for="(option, i) in availableOptions"
:key="i"
@click="onAddTag(option, addTag)"
>
{{ option }}
{{ typeof option === 'string' ? option : option.text }}
</BDropdownItemButton>
<BDropdownText v-if="!criteria && availableOptions.length === 0">
<YIcon iname="exclamation-triangle" />

View file

@ -10,7 +10,14 @@ import { isObjectLiteral } from '@/helpers/commons'
import type { ArrInnerType, Cols, Obj, StateVariant } from '@/types/commons'
type StateValidation = false | null
type Choices = string[] | { text: string; value: string }[]
export type Choice = string | { text: string; value: string }
type Choices = Choice[]
export type TagUpdateArgs = {
action: 'add' | 'remove'
tag: string
applyFn: (tag: string) => void
}
// DISPLAY
@ -121,7 +128,7 @@ export type TagsItemProps = BaseWritableItemProps & {
export type TagsSelectizeItemProps = BaseWritableItemProps & {
itemsName: string
options: string[]
options: Choices
auto?: boolean
disabledItems?: string[]
label: string