74 lines
1.7 KiB
Vue
74 lines
1.7 KiB
Vue
<template>
|
|
<Multiselect
|
|
v-model="selectedProjects"
|
|
:search-results="foundProjects"
|
|
:loading="projectService.loading"
|
|
:multiple="true"
|
|
:placeholder="$t('project.search')"
|
|
label="title"
|
|
@search="findProjects"
|
|
/>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import {computed, ref, shallowReactive, watchEffect, type PropType} from 'vue'
|
|
|
|
import Multiselect from '@/components/input/Multiselect.vue'
|
|
|
|
import type {IProject} from '@/modelTypes/IProject'
|
|
|
|
import ProjectService from '@/services/project'
|
|
import {includesById} from '@/helpers/utils'
|
|
|
|
type ProjectFilterFunc = (p: IProject) => boolean
|
|
|
|
const props = defineProps({
|
|
modelValue: {
|
|
type: Array as PropType<IProject[]>,
|
|
default: () => [],
|
|
},
|
|
projectFilter: {
|
|
type: Function as PropType<ProjectFilterFunc>,
|
|
default: () => {
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
return (_: IProject) => true
|
|
},
|
|
},
|
|
})
|
|
const emit = defineEmits<{
|
|
(e: 'update:modelValue', value: IProject[]): void
|
|
}>()
|
|
|
|
const projects = ref<IProject[]>([])
|
|
|
|
watchEffect(() => {
|
|
projects.value = props.modelValue
|
|
})
|
|
|
|
const selectedProjects = computed({
|
|
get() {
|
|
return projects.value
|
|
},
|
|
set: (value) => {
|
|
projects.value = value
|
|
emit('update:modelValue', value)
|
|
},
|
|
})
|
|
|
|
const projectService = shallowReactive(new ProjectService())
|
|
const foundProjects = ref<IProject[]>([])
|
|
|
|
async function findProjects(query: string) {
|
|
if (query === '') {
|
|
foundProjects.value = []
|
|
return
|
|
}
|
|
|
|
const response = await projectService.getAll({}, {s: query}) as IProject[]
|
|
|
|
// Filter selected items from the results
|
|
foundProjects.value = response
|
|
.filter(({id}) => !includesById(projects.value, id))
|
|
.filter(props.projectFilter)
|
|
}
|
|
</script> |