finnow/web-app/src/components/VendorSelect.vue

80 lines
2.3 KiB
Vue

<script setup lang="ts">
import { getSelectedProfile } from '@/api/profile'
import { TransactionApiClient, type TransactionVendor } from '@/api/transaction'
import { onMounted, ref, watch, type Ref } from 'vue'
import { useRoute } from 'vue-router'
import VueSelect, { type Option } from 'vue3-select-component'
const model = defineModel<TransactionVendor | null>({ required: true })
const route = useRoute()
const options: Ref<Option<string>[]> = ref([])
const existingVendors: Ref<TransactionVendor[]> = ref([])
const selectedVendorName: Ref<string | null> = ref(null)
watch(model, (newValue) => {
if (newValue === null) {
selectedVendorName.value = null
} else {
selectedVendorName.value = newValue.name
}
})
onMounted(() => {
const api = new TransactionApiClient(getSelectedProfile(route))
if (model.value !== null) {
selectedVendorName.value = model.value?.name
}
api.getVendors().then((vendors) => {
existingVendors.value = vendors
options.value = vendors.map((v) => {
return { label: v.name, value: v.name }
})
})
})
function onOptionCreated(value: string) {
const existingVendor = existingVendors.value.find((obj) => obj.name === value)
if (existingVendor) {
selectedVendorName.value = existingVendor.name
model.value = existingVendor
return
}
// Clear out any previously-added custom value from the list of options.
options.value = options.value.filter((opt) =>
existingVendors.value.some((v) => v.name === opt.value),
)
// Then add the new custom value, select it, and set the model.
options.value.push({ label: value, value: value })
selectedVendorName.value = value
model.value = { id: -1, name: value, description: null }
}
function onOptionSelected() {
model.value = existingVendors.value.find((v) => v.name === selectedVendorName.value) ?? null
}
function onOptionDeselected() {
model.value = null
}
</script>
<template>
<VueSelect
class="vendor-select"
v-model="selectedVendorName"
:options="options"
placeholder="Select a vendor"
is-taggable
@option-created="onOptionCreated"
@option-selected="onOptionSelected"
@option-deselected="onOptionDeselected"
>
<template #taggable-no-options> Add a new vendor. </template>
</VueSelect>
</template>
<style lang="css">
.vendor-select {
--vs-line-height: 1;
}
</style>