feat(customer): creatable select business type
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 5s

This commit is contained in:
Methapon2001 2025-08-21 14:45:56 +07:00
parent ff94980b06
commit 77f66ca302
3 changed files with 150 additions and 45 deletions

View file

@ -0,0 +1,97 @@
<script lang="ts" setup generic="T extends Record<string, unknown>">
import { QSelect } from 'quasar';
const model = defineModel<string | string[] | Record<string, unknown> | null>();
const props = withDefaults(
defineProps<{
id?: string;
label?: string;
options: T[];
optionLabel?: keyof T | string;
optionValue?: keyof T | string;
placeholder?: string;
readonly?: boolean;
clearable?: boolean;
disable?: boolean;
multiple?: boolean;
hideInput?: boolean;
hideDropdownIcon?: boolean;
rules?: ((value: string) => string | true)[];
}>(),
{
option: () => [],
optionLabel: 'label',
optionValue: 'value',
disable: false,
},
);
defineEmits<{
(
e: 'filter',
val: string,
update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
): void;
}>();
</script>
<template>
<q-select
dense
outlined
emit-value
map-options
hide-bottom-space
autocomplete="off"
input-debounce="500"
:placeholder
:clearable
:disable
:multiple
:readonly
:label
:options
:rules
:use-input="!hideInput"
:use-chips="multiple"
:hide-dropdown-icon="readonly"
:option-value="
typeof props.optionValue === 'string' ? props.optionValue : 'value'
"
:option-label="
typeof props.optionLabel === 'string' ? props.optionLabel : 'label'
"
:for="id"
v-model="model"
@filter="(value, update) => $emit('filter', value, update)"
@clear="model = multiple ? [] : ''"
>
<template v-if="$slots['prepend']" v-slot:prepend>
<slot name="prepend"></slot>
</template>
<template v-if="$slots['append']" v-slot:append>
<slot name="append"></slot>
</template>
<template v-slot:no-option>
<slot name="no-option">
<q-item-section class="text-grey">
{{ $t('general.noData') }}
</q-item-section>
</slot>
</template>
<template v-if="$slots['selected-item']" v-slot:selected-item="scope">
<slot name="selected-item" :scope="scope" :opt="scope.opt as T"></slot>
</template>
<template v-if="$slots['option']" v-slot:option="scope">
<slot name="option" :scope="scope" :opt="scope.opt as T"></slot>
</template>
<template v-if="$slots['before-options']" #before-options>
<slot name="before-options"></slot>
</template>
</q-select>
</template>

View file

@ -2,11 +2,11 @@
import { ref, onMounted } from 'vue';
import { createSelect, SelectProps } from './select';
import SelectInput from '../SelectInput.vue';
import { BusinessType } from 'src/stores/business-type/types';
import useStore from 'src/stores/business-type';
import SelectBase from './SelectBase.vue';
type SelectOption = BusinessType;
@ -74,17 +74,15 @@ function setDefaultValue() {
}
</script>
<template>
<SelectInput
<SelectBase
v-model="value"
incremental
clearable
option-value="id"
:label="label || $t('menu.manage.businessType')"
:placeholder
:readonly
:disable="disabled"
:option="selectOptions"
:hide-selected="false"
:fill-input="false"
:options="selectOptions"
:rules="[
(v: string) => !props.required || !!v || $t('form.error.required'),
]"
@ -167,14 +165,5 @@ function setDefaultValue() {
<q-separator class="q-mx-sm" />
</template>
<template #append v-if="clearable">
<q-icon
v-if="!readonly && value"
name="mdi-close-circle"
@click.stop="value = ''"
class="cursor-pointer clear-btn"
/>
</template>
</SelectInput>
</SelectBase>
</template>

View file

@ -4,11 +4,12 @@ import {
commaInput,
formatNumberWithCommas,
} from 'stores/utils';
import { onMounted, watch } from 'vue';
import { ref } from 'vue';
import { onMounted, watch, reactive, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import ThaiBahtText from 'thai-baht-text';
import SelectBusinessType from 'src/components/shared/select/SelectBusinessType.vue';
import BusinessTypeDialog from 'src/pages/16_business-type-management/BusinessTypeDialog.vue';
import useBusinessTypeStore, { BusinessType } from 'src/stores/business-type';
const { locale } = useI18n({ useScope: 'global' });
@ -24,8 +25,12 @@ const wageRateText = defineModel<string>('wageRateText', { default: '0' });
const rate = ref<string>(commaInput(wageRate.value?.toString() || '0'));
const typeBusinessOption = ref([]);
const typeBusinessENOption = ref([]);
const businessTypeDialog = ref(false);
const businessTypeForm = reactive({
name: '',
nameEN: '',
});
const jobPositionOption = ref([]);
const jobPositionENOption = ref([]);
@ -40,15 +45,12 @@ defineProps<{
onMounted(async () => {
const resultOption = await fetch('/option/option.json');
rawOption.value = await resultOption.json();
jobPositionENOption.value = rawOption.value.eng.position;
if (locale.value === 'eng') {
jobPositionOption.value = rawOption.value.eng.position;
}
if (locale.value === 'tha') {
jobPositionOption.value = rawOption.value.tha.position;
}
rawOption.value = await resultOption.json();
jobPositionOption.value =
rawOption.value[locale.value === 'tha' ? 'tha' : 'eng'].position;
jobPositionENOption.value = rawOption.value.eng.position;
});
watch(
@ -75,13 +77,6 @@ watch([jobPositionOption, jobPositionENOption], () => {
);
});
const typeBusinessOptions = ref<Record<string, unknown>[]>([]);
let typeBusinessFilter = selectFilterOptionRefMod(
typeBusinessOption,
typeBusinessOptions,
'label',
);
const jobPositionOptions = ref<Record<string, unknown>[]>([]);
let jobPositionFilter = selectFilterOptionRefMod(
jobPositionOption,
@ -89,19 +84,29 @@ let jobPositionFilter = selectFilterOptionRefMod(
'label',
);
const typeBusinessENOptions = ref<Record<string, unknown>[]>([]);
let typeBusinessENFilter = selectFilterOptionRefMod(
typeBusinessENOption,
typeBusinessENOptions,
'label',
);
const jobPositionENOptions = ref<Record<string, unknown>[]>([]);
let jobPositionENFilter = selectFilterOptionRefMod(
jobPositionENOption,
jobPositionENOptions,
'label',
);
// NOTE: ~ BUSINESS TYPE SECTION
const businessType = useBusinessTypeStore();
async function createBusinessType() {
const created = await businessType.create(businessTypeForm);
if (created) {
businessTypeId.value = created.id;
businessTypeDialog.value = false;
}
businessTypeForm.name = businessTypeForm.nameEN = '';
}
// NOTE: ~ BUSINESS TYPE SECTION END
</script>
<template>
<div class="col-12 row q-col-gutter-sm">
@ -121,16 +126,24 @@ let jobPositionENFilter = selectFilterOptionRefMod(
</div>
<SelectBusinessType
class="col-md-6 col-12"
v-model:value="businessTypeId"
:readonly
class="col-md-6 col-12"
lang="tha"
clearable
:readonly
:creatable="!readonly"
:creatable-disabled-text="`(${$t('form.error.selectField')})`"
@create="businessTypeDialog = true"
/>
<SelectBusinessType
class="col-md-6 col-12"
v-model:value="businessTypeId"
class="col-md-6 col-12"
lang="eng"
clearable
:readonly
:creatable="!readonly"
:creatable-disabled-text="`(${$t('form.error.selectField')})`"
@create="createBusinessType"
/>
<q-select
@ -282,4 +295,10 @@ let jobPositionENFilter = selectFilterOptionRefMod(
"
/>
</div>
<BusinessTypeDialog
v-model="businessTypeDialog"
v-bind:data="businessTypeForm"
@submit="createBusinessType"
/>
</template>