feat(customer): creatable select business type
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 5s
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 5s
This commit is contained in:
parent
ff94980b06
commit
77f66ca302
3 changed files with 150 additions and 45 deletions
97
src/components/shared/select/SelectBase.vue
Normal file
97
src/components/shared/select/SelectBase.vue
Normal 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>
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue