refactor: api select value (#69)

* feat: add file

* fix: wrong type

* feat: select customer component

* fixup! feat: select customer component

* fix: char case

* refactor: fn alias

* chore: add space

* feat: accept fetch parameter

* refactor: naming

* feat: add emit event create

* fix: add suffix to add text

* feat: add before options slot for select input comp

* fix: error when label not found

* fix: value type

* feat: add required param

* fix: wording

* refactor: fix customer

* feat: use new select component

* chore: add note

* feat: add decoration for select with creatable

* feat: emit event

* feat: close popup on click

* feat: adjust alignment

* feat: add readonly params

* feat: add select branch option

* feat: use new select component

* feat: add disabled params

* feat: adjust internal search and select

* refactor: props type

* feat: use new select component

* feat: add lib for select component

* refactor: use factory function instead

* refactor: merge two lines of code

* refactor: move watch inside

* refactor: fix value not in list check

* chore: cleanup

* fix: remove test page size

* chore: remove unused

* feat: use new select component

* fix: typo

* fix: error

* refactor: extract type

* refactor: change ref var to normal var

* refactor: force overwrite params to prevent error on render

* feat: add clearable parameter

* feat: make clearable
This commit is contained in:
Methapon Metanipat 2024-11-12 11:56:14 +07:00 committed by GitHub
parent a227744131
commit d414685fe7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 500 additions and 319 deletions

View file

@ -1,30 +1,12 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import useBranchStore from 'src/stores/branch';
import useCustomerStore from 'src/stores/customer';
import SelectInput from '../shared/SelectInput.vue';
import { QSelect } from 'quasar';
import { Branch } from 'src/stores/branch/types';
import { CustomerBranch } from 'src/stores/customer/types';
import useOptionStore from 'stores/options';
import SelectCustomer from '../shared/select/SelectCustomer.vue';
import SelectBranch from '../shared/select/SelectBranch.vue';
const { locale } = useI18n({ useScope: 'global' });
const branchStore = useBranchStore();
const customerStore = useCustomerStore();
const optionStore = useOptionStore();
const branchId = defineModel<string>('branchId');
const customerBranchId = defineModel<string>('customerBranchId');
const agentPrice = defineModel<boolean>('agentPrice');
const special = defineModel<boolean>('special');
const branchOption = ref<{ value: string; label: string; labelEN: string }[]>();
const customerOption =
ref<
{ value: string; label: string; labelEN: string; namePrefix: string }[]
>();
defineProps<{
outlined?: boolean;
readonly?: boolean;
@ -40,103 +22,6 @@ defineProps<{
defineEmits<{
(e: 'addCustomer'): void;
}>();
async function filter(
val: string,
update: (...args: unknown[]) => void,
type: 'branch' | 'customer',
) {
update(
async () => {
await init(val, type);
},
(ref: QSelect) => {
if (val !== '' && ref.options && ref.options?.length > 0) {
ref.setOptionIndex(-1);
ref.moveOptionSelection(1, true);
}
},
);
}
const currentSelectedBranchOption =
ref<NonNullable<typeof branchOption.value>[number]>();
const currentSelectedCustomerOption =
ref<NonNullable<typeof customerOption.value>[number]>();
async function init(val: string, type: 'branch' | 'customer') {
const res =
type === 'branch'
? await branchStore.fetchList({
query: val,
pageSize: 30,
})
: await customerStore.fetchListCustomerBranch({
query: val,
pageSize: 30,
company: true,
});
if (res) {
if (type === 'branch') {
const mapped = (res.result as Branch[]).map((v: Branch) => ({
value: v.id,
label: v.name,
labelEN: v.nameEN,
}));
if (!mapped.find((v) => v.value === branchId.value) && branchId.value) {
if (currentSelectedBranchOption.value?.value !== branchId.value) {
const v = await branchStore.fetchById(branchId.value);
if (v) {
mapped.unshift({
value: v.id,
label: v.name,
labelEN: v.nameEN,
});
currentSelectedBranchOption.value = mapped.at(0);
}
}
}
branchOption.value = mapped;
} else if (type === 'customer') {
const mapped = (res.result as CustomerBranch[]).map(
(v: CustomerBranch) => ({
value: v.id,
label: v.registerName || `${v.firstName} ${v.lastName}` || '-',
labelEN:
v.registerNameEN || `${v.firstNameEN} ${v.lastNameEN}` || '-',
namePrefix: v.namePrefix,
}),
);
if (
!mapped.find((v) => v.value === customerBranchId.value) &&
customerBranchId.value
) {
const v = await customerStore.fetchListCustomerBranchById(
customerBranchId.value,
);
if (v) {
mapped.unshift({
value: v.id,
label: v.registerName || `${v.firstName} ${v.lastName}` || '-',
labelEN:
v.registerNameEN || `${v.firstNameEN} ${v.lastNameEN}` || '-',
namePrefix: v.namePrefix,
});
}
}
customerOption.value = mapped;
}
}
}
onMounted(async () => {
await init('', 'branch');
await init('', 'customer');
});
</script>
<template>
<div class="row">
@ -170,62 +55,24 @@ onMounted(async () => {
</div>
</div>
<div class="col-12 row q-col-gutter-sm">
<SelectInput
:readonly
incremental
v-model="branchId"
id="quotation-branch"
class="col-md col-12"
:option="branchOption"
<SelectBranch
v-model:value="branchId"
:label="$t('quotation.branch')"
:option-label="locale === 'eng' ? 'labelEN' : 'label'"
:rules="[(val: string) => !!val || $t('form.error.required')]"
@filter="(val: string, update) => filter(val, update, 'branch')"
/>
<SelectInput
class="col-md-6 col-12"
simple
required
:readonly
incremental
v-model="customerBranchId"
class="col-md col-12"
id="quotation-customer"
:option="customerOption"
/>
<SelectCustomer
v-model:value="customerBranchId"
:label="$t('quotation.customer')"
:option-label="locale === 'eng' ? 'labelEN' : 'label'"
:rules="[(val: string) => !!val || $t('form.error.required')]"
@filter="(val: string, update) => filter(val, update, 'customer')"
>
<template #option="{ scope }">
<q-item
clickable
v-if="scope.index === 0 && !hideAdd"
@click.stop="$emit('addCustomer')"
>
<q-item-section>
{{ $t('general.add', { text: $t('quotation.newCustomer') }) }}
</q-item-section>
</q-item>
<q-separator v-if="scope.index === 0" />
<q-item clickable v-bind="scope.itemProps">
<q-item-section>
{{
optionStore.mapOption(scope.opt.namePrefix) ||
$t('general.company')
}}
{{ locale === 'eng' ? scope.opt.labelEN : scope.opt.label }}
</q-item-section>
</q-item>
</template>
<template #noOption>
<q-item clickable @click.stop="$emit('addCustomer')">
<q-item-section>
{{ $t('general.add', { text: $t('quotation.newCustomer') }) }}
</q-item-section>
</q-item>
</template>
</SelectInput>
@create="$emit('addCustomer')"
class="col-md-6 col-12"
creatable
simple
required
:readonly
/>
</div>
</div>
</template>