213 lines
5.7 KiB
Vue
213 lines
5.7 KiB
Vue
<script setup lang="ts">
|
|
import { ref, onMounted } from 'vue';
|
|
|
|
import { createSelect, SelectProps } from './select';
|
|
import SelectInput from '../SelectInput.vue';
|
|
|
|
import useOptionStore from 'src/stores/options';
|
|
|
|
import { Quotation, QuotationFull } from 'src/stores/quotations/types';
|
|
|
|
import { useQuotationStore as useStore } from 'src/stores/quotations';
|
|
|
|
type SelectOption = Quotation | QuotationFull;
|
|
|
|
const value = defineModel<string | null | undefined>('value', {
|
|
required: true,
|
|
});
|
|
const valueOption = defineModel<SelectOption>('valueOption', {
|
|
required: false,
|
|
});
|
|
|
|
const selectOptions = ref<SelectOption[]>([]);
|
|
|
|
const { getQuotationList: getList, getQuotation: getById } = useStore();
|
|
|
|
defineEmits<{
|
|
(e: 'create'): void;
|
|
}>();
|
|
|
|
type ExclusiveProps = {
|
|
codeOnly?: boolean;
|
|
selectFirstValue?: boolean;
|
|
branchVirtual?: boolean;
|
|
checkRole?: string[];
|
|
};
|
|
|
|
const props = defineProps<SelectProps<typeof getList> & ExclusiveProps>();
|
|
|
|
const { getOptions, setFirstValue, getSelectedOption, filter } =
|
|
createSelect<SelectOption>(
|
|
{
|
|
value,
|
|
valueOption,
|
|
selectOptions,
|
|
getList: async (query) => {
|
|
const ret = await getList({
|
|
query,
|
|
...props.params,
|
|
pageSize: 30,
|
|
includeRegisteredBranch: true,
|
|
});
|
|
if (ret) return ret.result;
|
|
},
|
|
getByValue: async (id) => {
|
|
const ret = await getById(id);
|
|
if (ret) return ret;
|
|
},
|
|
},
|
|
{ valueField: 'id' },
|
|
);
|
|
|
|
function getCustomerName(
|
|
record: Quotation,
|
|
opts?: {
|
|
locale?: string;
|
|
noCode?: boolean;
|
|
},
|
|
) {
|
|
const customer = record.customerBranch;
|
|
|
|
return (
|
|
{
|
|
['CORP']: {
|
|
['eng']: customer.registerNameEN,
|
|
['tha']: customer.registerName,
|
|
}[opts?.locale || 'eng'],
|
|
['PERS']:
|
|
{
|
|
['eng']: `${useOptionStore().mapOption(customer?.namePrefix || '')} ${customer?.firstNameEN} ${customer?.lastNameEN}`,
|
|
['tha']: `${useOptionStore().mapOption(customer?.namePrefix || '')} ${customer?.firstName} ${customer?.lastName}`,
|
|
}[opts?.locale || 'eng'] || '-',
|
|
}[customer.customer.customerType] +
|
|
(opts?.noCode ? '' : ' ' + `(${customer.code})`)
|
|
);
|
|
}
|
|
|
|
onMounted(async () => {
|
|
await getOptions();
|
|
|
|
if (props.autoSelectOnSingle && selectOptions.value.length === 1) {
|
|
setFirstValue();
|
|
}
|
|
|
|
if (props.selectFirstValue) {
|
|
setDefaultValue();
|
|
} else await getSelectedOption();
|
|
});
|
|
|
|
function setDefaultValue() {
|
|
setFirstValue();
|
|
}
|
|
</script>
|
|
<template>
|
|
<SelectInput
|
|
v-model="value"
|
|
option-value="id"
|
|
incremental
|
|
:label
|
|
:placeholder
|
|
:readonly
|
|
:disable="disabled"
|
|
:option="selectOptions"
|
|
:hide-selected="false"
|
|
:fill-input="false"
|
|
:rules="[
|
|
(v: string) => !props.required || !!v || $t('form.error.required'),
|
|
]"
|
|
@filter="filter"
|
|
>
|
|
<template #append v-if="clearable">
|
|
<q-icon
|
|
v-if="!readonly && value"
|
|
name="mdi-close-circle"
|
|
@click.stop="value = ''"
|
|
class="cursor-pointer clear-btn"
|
|
/>
|
|
</template>
|
|
|
|
<template #option="{ scope }">
|
|
<q-item
|
|
v-if="scope.opt"
|
|
v-bind="scope.itemProps"
|
|
class="row items-start col-12 no-padding"
|
|
>
|
|
<div class="q-mx-sm q-my-xs">
|
|
<q-icon name="mdi-file" style="color: var(--brand-1)" />
|
|
</div>
|
|
|
|
<div class="q-pt-xs">
|
|
<span class="row">
|
|
<span style="font-weight: 600">
|
|
{{ $t('productService.service.work') }}:
|
|
</span>
|
|
|
|
{{ scope.opt.workName }}
|
|
({{ scope.opt.code }})
|
|
|
|
<q-badge
|
|
dense
|
|
class="surface-3 q-ml-sm"
|
|
rounded
|
|
style="color: var(--foreground)"
|
|
v-if="props.params?.hasCancel"
|
|
>
|
|
{{ scope.opt._count.canceledWork || 0 }}
|
|
</q-badge>
|
|
</span>
|
|
|
|
<div class="text-caption app-text-muted-2 q-mb-xs">
|
|
<span class="col column">
|
|
<!-- TODO: register branch id -->
|
|
{{ $t(`creditNote.label.servicePoint`) }}
|
|
{{
|
|
$i18n.locale === 'eng'
|
|
? scope.opt.registeredBranch.nameEN
|
|
: scope.opt.registeredBranch.name
|
|
}}
|
|
({{ scope.opt.registeredBranch.code }})
|
|
</span>
|
|
<span class="col">
|
|
{{ $t('quotation.customer') }}
|
|
{{ getCustomerName(scope.opt, { locale: $i18n.locale }) }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</q-item>
|
|
<q-separator class="q-mx-sm" />
|
|
</template>
|
|
|
|
<template #selected-item="{ scope }">
|
|
<div v-if="scope.opt" class="row items-center no-wrap">
|
|
<div class="q-mr-sm">
|
|
<span style="font-weight: 600">
|
|
{{ $t('productService.service.work') }}:
|
|
</span>
|
|
|
|
{{ scope.opt.workName }}
|
|
({{ scope.opt.code }})
|
|
<q-badge
|
|
dense
|
|
class="surface-3 q-ml-xs"
|
|
rounded
|
|
style="color: var(--foreground)"
|
|
v-if="props.params?.hasCancel"
|
|
>
|
|
{{ scope.opt._count.canceledWork || 0 }}
|
|
</q-badge>
|
|
</div>
|
|
<div class="text-caption app-text-muted-2">
|
|
{{ $t(`creditNote.label.servicePoint`) }}
|
|
{{
|
|
$i18n.locale === 'eng'
|
|
? scope.opt.registeredBranch.nameEN
|
|
: scope.opt.registeredBranch.name
|
|
}}
|
|
({{ scope.opt.registeredBranch.code }}),
|
|
{{ $t('quotation.customer') }}
|
|
{{ getCustomerName(scope.opt, { locale: $i18n.locale }) }}
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</SelectInput>
|
|
</template>
|