Merge branch 'feat/ocr' into develop
This commit is contained in:
commit
7a56f205ec
19 changed files with 1452 additions and 495 deletions
|
|
@ -32,6 +32,7 @@ defineProps<{
|
||||||
outlined?: boolean;
|
outlined?: boolean;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
separator?: boolean;
|
separator?: boolean;
|
||||||
|
ocr?: boolean;
|
||||||
|
|
||||||
prefixId: string;
|
prefixId: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
@ -84,7 +85,35 @@ watch(
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="row col-12">
|
<div class="row col-12" v-if="ocr">
|
||||||
|
<div class="col-12 row">
|
||||||
|
<div class="col-6 flex flex-center">
|
||||||
|
<q-img
|
||||||
|
src="/images/customer-CORP-avartar.png "
|
||||||
|
style="height: 100px; max-width: 50%"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col-6 column">
|
||||||
|
<q-input
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
:for="`${prefixId}-input-passport-no`"
|
||||||
|
:dense="dense"
|
||||||
|
outlined
|
||||||
|
:readonly="readonly"
|
||||||
|
hide-bottom-space
|
||||||
|
class="col-md-3 col-6"
|
||||||
|
:label="$t('customerEmployee.form.passportNo')"
|
||||||
|
v-model="passportNumber"
|
||||||
|
:rules="[
|
||||||
|
(val: string) =>
|
||||||
|
!!val || $t('inputValidate') + $t('formDialogInputPassportNo'),
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row col-12" v-else>
|
||||||
<div class="col-12 q-pb-sm text-weight-bold text-body1">
|
<div class="col-12 q-pb-sm text-weight-bold text-body1">
|
||||||
<q-icon
|
<q-icon
|
||||||
flat
|
flat
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import AppBox from './app/AppBox.vue';
|
import AppBox from './app/AppBox.vue';
|
||||||
import { CancelButton, SaveButton } from './button';
|
import { CancelButton, ClearButton, SaveButton } from './button';
|
||||||
|
|
||||||
defineExpose({ browse });
|
defineExpose({ browse });
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
|
@ -131,20 +131,15 @@ async function downloadImage(url: string) {
|
||||||
class="row items-center justify-end q-py-sm q-px-md bordered-t"
|
class="row items-center justify-end q-py-sm q-px-md bordered-t"
|
||||||
v-if="!hiddenFooter"
|
v-if="!hiddenFooter"
|
||||||
>
|
>
|
||||||
<q-btn
|
<ClearButton
|
||||||
dense
|
outlined
|
||||||
unelevated
|
|
||||||
flat
|
|
||||||
:color="$q.dark.isActive ? 'grey-9' : 'grey-4'"
|
|
||||||
:text-color="$q.dark.isActive ? 'grey-1' : 'grey-10'"
|
|
||||||
:label="$t('general.clear')"
|
|
||||||
@click="
|
@click="
|
||||||
inputFile && (inputFile.value = ''),
|
inputFile && (inputFile.value = ''),
|
||||||
(imageUrl = defaultUrl || fallbackUrl || ''),
|
(imageUrl = defaultUrl || fallbackUrl || ''),
|
||||||
(file = null)
|
(file = null)
|
||||||
"
|
"
|
||||||
class="q-px-md q-mr-auto"
|
class="q-px-md q-mr-auto"
|
||||||
:disable="
|
:disabled="
|
||||||
clearButtonDisabled ||
|
clearButtonDisabled ||
|
||||||
imageUrl === fallbackUrl ||
|
imageUrl === fallbackUrl ||
|
||||||
imageUrl === defaultUrl ||
|
imageUrl === defaultUrl ||
|
||||||
|
|
|
||||||
26
src/components/button/ClearButton.vue
Normal file
26
src/components/button/ClearButton.vue
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import MainButton from './MainButton.vue';
|
||||||
|
|
||||||
|
defineEmits<{
|
||||||
|
(e: 'click', v: MouseEvent): void;
|
||||||
|
}>();
|
||||||
|
defineProps<{
|
||||||
|
iconOnly?: boolean;
|
||||||
|
solid?: boolean;
|
||||||
|
outlined?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
dark?: boolean;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MainButton
|
||||||
|
@click="(e) => $emit('click', e)"
|
||||||
|
v-bind="{ ...$props, ...$attrs }"
|
||||||
|
icon="mdi-broom"
|
||||||
|
color="var(--gray-7-hsl)"
|
||||||
|
:title="iconOnly ? $t('general.clear') : undefined"
|
||||||
|
>
|
||||||
|
{{ $t('general.clear') }}
|
||||||
|
</MainButton>
|
||||||
|
</template>
|
||||||
26
src/components/button/CloseButton.vue
Normal file
26
src/components/button/CloseButton.vue
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import MainButton from './MainButton.vue';
|
||||||
|
|
||||||
|
defineEmits<{
|
||||||
|
(e: 'click', v: MouseEvent): void;
|
||||||
|
}>();
|
||||||
|
defineProps<{
|
||||||
|
iconOnly?: boolean;
|
||||||
|
solid?: boolean;
|
||||||
|
outlined?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
dark?: boolean;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MainButton
|
||||||
|
@click="(e) => $emit('click', e)"
|
||||||
|
v-bind="{ ...$props, ...$attrs }"
|
||||||
|
icon="mdi-close"
|
||||||
|
color="var(--gray-7-hsl)"
|
||||||
|
:title="iconOnly ? $t('general.clear') : undefined"
|
||||||
|
>
|
||||||
|
{{ $t('general.clear') }}
|
||||||
|
</MainButton>
|
||||||
|
</template>
|
||||||
|
|
@ -6,3 +6,5 @@ export { default as DeleteButton } from './DeleteButton.vue';
|
||||||
export { default as BackButton } from './BackButton.vue';
|
export { default as BackButton } from './BackButton.vue';
|
||||||
export { default as UndoButton } from './UndoButton.vue';
|
export { default as UndoButton } from './UndoButton.vue';
|
||||||
export { default as ToggleButton } from './ToggleButton.vue';
|
export { default as ToggleButton } from './ToggleButton.vue';
|
||||||
|
export { default as ClearButton } from './ClearButton.vue';
|
||||||
|
export { default as CloseButton } from './CloseButton.vue';
|
||||||
|
|
|
||||||
367
src/components/upload-file/FormCitizen.vue
Normal file
367
src/components/upload-file/FormCitizen.vue
Normal file
|
|
@ -0,0 +1,367 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import { QSelect } from 'quasar';
|
||||||
|
import { selectFilterOptionRefMod } from 'stores/utils';
|
||||||
|
import { getRole } from 'src/services/keycloak';
|
||||||
|
import useOptionStore from 'stores/options';
|
||||||
|
import { onMounted } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import DatePicker from '../shared/DatePicker.vue';
|
||||||
|
const { locale } = useI18n();
|
||||||
|
|
||||||
|
import {
|
||||||
|
dateFormat,
|
||||||
|
calculateAge,
|
||||||
|
parseAndFormatDate,
|
||||||
|
disabledAfterToday,
|
||||||
|
} from 'src/utils/datetime';
|
||||||
|
|
||||||
|
import {
|
||||||
|
SaveButton,
|
||||||
|
EditButton,
|
||||||
|
DeleteButton,
|
||||||
|
UndoButton,
|
||||||
|
} from 'components/button';
|
||||||
|
defineProps<{
|
||||||
|
prefixId?: string;
|
||||||
|
outlined?: boolean;
|
||||||
|
readonly?: boolean;
|
||||||
|
create?: boolean;
|
||||||
|
actionDisabled?: boolean;
|
||||||
|
customerType?: 'CORP' | 'PERS';
|
||||||
|
orc?: boolean;
|
||||||
|
}>();
|
||||||
|
defineEmits<{
|
||||||
|
(e: 'save'): void;
|
||||||
|
(e: 'edit'): void;
|
||||||
|
(e: 'delete'): void;
|
||||||
|
(e: 'cancel'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const optionStore = useOptionStore();
|
||||||
|
const namePrefix = defineModel<string | null>('namePrefix');
|
||||||
|
const birthDate = defineModel<Date | string | null>('birthDate');
|
||||||
|
const gender = defineModel<string>('gender');
|
||||||
|
|
||||||
|
const address = defineModel<string>('address');
|
||||||
|
const firstName = defineModel<string>('firstName', { required: true });
|
||||||
|
const lastName = defineModel<string>('lastName', { required: true });
|
||||||
|
const firstNameEN = defineModel<string>('firstNameEn', { required: true });
|
||||||
|
const lastNameEN = defineModel<string>('lastNameEn', { required: true });
|
||||||
|
|
||||||
|
const citizenId = defineModel<string | undefined>('citizenId', {
|
||||||
|
required: true,
|
||||||
|
});
|
||||||
|
const nationality = defineModel<string>('nationality');
|
||||||
|
|
||||||
|
const religion = defineModel<string>('religion');
|
||||||
|
|
||||||
|
const branchOptions = defineModel<{ id: string; name: string }[]>(
|
||||||
|
'branchOptions',
|
||||||
|
{ default: [] },
|
||||||
|
);
|
||||||
|
const filteredBranchOptions = ref<Record<string, unknown>[]>([]);
|
||||||
|
|
||||||
|
let branchFilter: (
|
||||||
|
value: string,
|
||||||
|
update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
branchFilter = selectFilterOptionRefMod(
|
||||||
|
branchOptions,
|
||||||
|
filteredBranchOptions,
|
||||||
|
'name',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => branchOptions.value,
|
||||||
|
() => {
|
||||||
|
branchFilter = selectFilterOptionRefMod(
|
||||||
|
branchOptions,
|
||||||
|
filteredBranchOptions,
|
||||||
|
'name',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const prefixNameOptions = ref<Record<string, unknown>[]>([]);
|
||||||
|
let prefixNameFilter: (
|
||||||
|
value: string,
|
||||||
|
update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
const prefixNameEnOptions = ref<Record<string, unknown>[]>([]);
|
||||||
|
let prefixNameEnFilter: (
|
||||||
|
value: string,
|
||||||
|
update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
const genderOptions = ref<Record<string, unknown>[]>([]);
|
||||||
|
let genderFilter: (
|
||||||
|
value: string,
|
||||||
|
update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
prefixNameFilter = selectFilterOptionRefMod(
|
||||||
|
ref(optionStore.globalOption?.prefix),
|
||||||
|
prefixNameOptions,
|
||||||
|
'label',
|
||||||
|
);
|
||||||
|
genderFilter = selectFilterOptionRefMod(
|
||||||
|
ref(optionStore.globalOption?.gender),
|
||||||
|
genderOptions,
|
||||||
|
'label',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => optionStore.globalOption,
|
||||||
|
() => {
|
||||||
|
prefixNameFilter = selectFilterOptionRefMod(
|
||||||
|
ref(optionStore.globalOption.prefix),
|
||||||
|
prefixNameOptions,
|
||||||
|
'label',
|
||||||
|
);
|
||||||
|
genderFilter = selectFilterOptionRefMod(
|
||||||
|
ref(optionStore.globalOption.gender),
|
||||||
|
genderOptions,
|
||||||
|
'label',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
function formatCode(input: string | undefined, type: 'code' | 'number') {
|
||||||
|
if (!input) return;
|
||||||
|
return input.slice(...(type === 'code' ? [0, -6] : [-6]));
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="row q-mb-sm">
|
||||||
|
<template v-if="orc">
|
||||||
|
<div class="row" style="gap: 10px">
|
||||||
|
<div class="col-4 flex flex-center">
|
||||||
|
<q-img
|
||||||
|
src="/images/customer-CORP-avartar.png"
|
||||||
|
width="80px"
|
||||||
|
height="80px"
|
||||||
|
></q-img>
|
||||||
|
</div>
|
||||||
|
<div class="col row" style="gap: 10px">
|
||||||
|
<q-input
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
:readonly="readonly"
|
||||||
|
hide-bottom-space
|
||||||
|
class="col-12"
|
||||||
|
:label="$t('customer.form.citizenId')"
|
||||||
|
for="input-citizen-id"
|
||||||
|
v-model="citizenId"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DatePicker
|
||||||
|
:label="$t('form.birthDate')"
|
||||||
|
v-model="birthDate"
|
||||||
|
class="col-12"
|
||||||
|
:id="`${prefixId}-input-birth-date`"
|
||||||
|
:readonly="readonly"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-input
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
:readonly="readonly"
|
||||||
|
hide-bottom-space
|
||||||
|
class="col"
|
||||||
|
:label="$t('general.nationality')"
|
||||||
|
for="input-nationality"
|
||||||
|
v-model="nationality"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-input
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
:readonly="readonly"
|
||||||
|
hide-bottom-space
|
||||||
|
class="col"
|
||||||
|
:label="$t('customer.form.religion')"
|
||||||
|
for="input-religion"
|
||||||
|
v-model="religion"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-select
|
||||||
|
outlined
|
||||||
|
use-input
|
||||||
|
fill-input
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
hide-selected
|
||||||
|
hide-bottom-space
|
||||||
|
input-debounce="0"
|
||||||
|
option-label="label"
|
||||||
|
option-value="value"
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
class="col"
|
||||||
|
dense
|
||||||
|
:readonly="readonly"
|
||||||
|
:options="genderOptions"
|
||||||
|
:hide-dropdown-icon="readonly"
|
||||||
|
:for="`${prefixId}-select-gender`"
|
||||||
|
:label="$t('form.gender')"
|
||||||
|
@filter="genderFilter"
|
||||||
|
:model-value="readonly ? gender || '-' : gender"
|
||||||
|
@update:model-value="
|
||||||
|
(v) => (typeof v === 'string' ? (gender = v) : '')
|
||||||
|
"
|
||||||
|
@clear="gender = ''"
|
||||||
|
>
|
||||||
|
<template v-slot:no-option>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section class="text-grey">
|
||||||
|
{{ $t('general.noData') }}
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</template>
|
||||||
|
</q-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row q-col-gutter-sm">
|
||||||
|
<q-select
|
||||||
|
outlined
|
||||||
|
use-input
|
||||||
|
fill-input
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
hide-selected
|
||||||
|
hide-bottom-space
|
||||||
|
input-debounce="0"
|
||||||
|
option-label="label"
|
||||||
|
option-value="value"
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
hide-dropdown-icon
|
||||||
|
class="col-2"
|
||||||
|
dense
|
||||||
|
:readonly="readonly"
|
||||||
|
:options="prefixNameOptions"
|
||||||
|
:for="`${prefixId}-select-prefix-name`"
|
||||||
|
:label="$t('form.prefixName')"
|
||||||
|
@filter="prefixNameFilter"
|
||||||
|
:model-value="readonly ? namePrefix || '-' : namePrefix"
|
||||||
|
@update:model-value="
|
||||||
|
(v) => {
|
||||||
|
typeof v === 'string' ? (namePrefix = v) : '';
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@clear="namePrefix = ''"
|
||||||
|
>
|
||||||
|
<template v-slot:no-option>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section class="text-grey">
|
||||||
|
{{ $t('general.noData') }}
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</template>
|
||||||
|
</q-select>
|
||||||
|
|
||||||
|
<q-input
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
:readonly="readonly"
|
||||||
|
hide-bottom-space
|
||||||
|
class="col-5"
|
||||||
|
:label="$t('customer.form.firstName')"
|
||||||
|
for="input-first-name"
|
||||||
|
v-model="firstName"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-input
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
:readonly="readonly"
|
||||||
|
hide-bottom-space
|
||||||
|
class="col-5"
|
||||||
|
:label="$t('customer.form.lastName')"
|
||||||
|
for="input-last-name"
|
||||||
|
v-model="lastName"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-input
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
:disable="!readonly"
|
||||||
|
:readonly="readonly"
|
||||||
|
hide-bottom-space
|
||||||
|
class="col-2"
|
||||||
|
:label="$t('customer.form.prefixName')"
|
||||||
|
for="input-prefix-name"
|
||||||
|
:model-value="
|
||||||
|
namePrefix ? $t(`customer.form.prefix.${namePrefix}`) : '-'
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-input
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
:readonly="readonly"
|
||||||
|
hide-bottom-space
|
||||||
|
class="col-5"
|
||||||
|
:label="$t('customer.form.firstNameEN')"
|
||||||
|
for="input-first-name-en"
|
||||||
|
v-model="firstNameEN"
|
||||||
|
/>
|
||||||
|
<q-input
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
:readonly="readonly"
|
||||||
|
hide-bottom-space
|
||||||
|
class="col-5"
|
||||||
|
:label="$t('customer.form.lastNameEN')"
|
||||||
|
for="input-last-name-en"
|
||||||
|
v-model="lastNameEN"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-input
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
:readonly="readonly"
|
||||||
|
hide-bottom-space
|
||||||
|
class="col-12"
|
||||||
|
:label="$t('general.address')"
|
||||||
|
for="input-address"
|
||||||
|
v-model="address"
|
||||||
|
/>
|
||||||
|
<DatePicker
|
||||||
|
:label="$t('customer.form.issueDate')"
|
||||||
|
v-model="firstName"
|
||||||
|
class="col-6"
|
||||||
|
:id="`${prefixId}-input-issue-date`"
|
||||||
|
:readonly="readonly"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DatePicker
|
||||||
|
:label="$t('customer.form.passportExpiryDate')"
|
||||||
|
v-model="firstName"
|
||||||
|
class="col-6"
|
||||||
|
:id="`${prefixId}-input-passport-expiry-date`"
|
||||||
|
:readonly="readonly"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -1,29 +1,40 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import { SaveButton, UndoButton } from 'components/button';
|
import { SaveButton, UndoButton, CloseButton } from 'components/button';
|
||||||
|
import { dialog } from 'stores/utils';
|
||||||
|
|
||||||
import { VuePDF, usePDF } from '@tato30/vue-pdf';
|
import { VuePDF, usePDF } from '@tato30/vue-pdf';
|
||||||
|
|
||||||
const currentFileUrl = defineModel<string>('currentFileUrl');
|
const currentFileSelected = ref<string>('');
|
||||||
const { pdf, pages } = usePDF(currentFileUrl);
|
const file = defineModel<
|
||||||
|
{
|
||||||
|
group?: string;
|
||||||
|
url?: string;
|
||||||
|
file?: File;
|
||||||
|
}[]
|
||||||
|
>('file', {
|
||||||
|
default: [],
|
||||||
|
});
|
||||||
|
|
||||||
const selected = defineModel<string>('selected');
|
const currentFile = computed(() => file.value.at(currentIndex.value));
|
||||||
const file = defineModel<File | null>('file');
|
const statusOcr = defineModel<boolean>('statusOcr', { default: false });
|
||||||
|
const currentMode = ref<string>('');
|
||||||
|
const currentIndex = ref(0);
|
||||||
|
|
||||||
const scale = ref(1);
|
const scale = ref(1);
|
||||||
const page = ref(1);
|
const page = ref(1);
|
||||||
|
|
||||||
const currentTab = ref<string>('information');
|
|
||||||
|
|
||||||
const currentIndexDropdownList = ref(0);
|
const currentIndexDropdownList = ref(0);
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
tree?: { label: string; children: { label: string }[] }[];
|
treeFile: { label: string; file: { label: string }[] }[];
|
||||||
dropdownList?: string[];
|
readonly?: boolean;
|
||||||
|
dropdownList?: { label: string; value: string }[];
|
||||||
|
hideAction?: boolean;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
tree: () => [],
|
treeFile: () => [],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -47,73 +58,114 @@ function change(e: Event) {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.readAsDataURL(_file);
|
reader.readAsDataURL(_file);
|
||||||
reader.onload = () => {
|
reader.onload = () => {
|
||||||
currentFileUrl.value = reader.result as string;
|
if (file.value[currentIndex.value]) {
|
||||||
|
file.value[currentIndex.value].url = reader.result as string;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_file) file.value = _file;
|
if (_file && file.value[currentIndex.value]) {
|
||||||
|
file.value[currentIndex.value].file = _file;
|
||||||
|
file.value[currentIndex.value].group =
|
||||||
|
props.dropdownList?.[currentIndexDropdownList.value].value;
|
||||||
|
} else {
|
||||||
|
file.value.push({
|
||||||
|
group: props.dropdownList?.[currentIndexDropdownList.value].value,
|
||||||
|
file: _file,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
statusOcr.value = true;
|
||||||
|
|
||||||
emit(
|
emit(
|
||||||
'sendOcr',
|
'sendOcr',
|
||||||
props.dropdownList?.[currentIndexDropdownList.value] || '',
|
props.dropdownList?.[currentIndexDropdownList.value].value || '',
|
||||||
inputFile?.files?.[0],
|
inputFile?.files?.[0],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabsList = [
|
watch(currentFileSelected, () => {
|
||||||
{
|
file.value.findIndex((v, i) => {
|
||||||
label: 'information',
|
if (v.url?.includes(currentFileSelected.value)) {
|
||||||
name: 'information',
|
currentIndex.value = i;
|
||||||
},
|
currentMode.value =
|
||||||
{
|
props.dropdownList?.[currentIndexDropdownList.value].label || 'other';
|
||||||
label: 'document',
|
}
|
||||||
name: 'document',
|
});
|
||||||
},
|
});
|
||||||
];
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'sendOcr', dropdown: string, file?: File): void;
|
(e: 'sendOcr', dropdown: string, file?: File): void;
|
||||||
|
(e: 'save', เgroup: string, file?: File): void;
|
||||||
|
(e: 'deleteFile', filename: string): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const { pdf, pages } = usePDF(computed(() => currentFile.value?.url));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="full-height full-width row">
|
<div class="full-width row no-wrap wrapper">
|
||||||
<div>
|
<div class="col column no-wrap">
|
||||||
<div class="q-pa-sm text-center bordered" style="height: 50px">
|
<div class="q-pa-sm text-center bordered" style="height: 50px">
|
||||||
<q-btn-dropdown icon="mdi-upload" color="info" label="อัปโหลดเอกสาร">
|
<q-btn-dropdown
|
||||||
<q-list v-for="(v, i) in dropdownList" :key="v">
|
:disable="readonly"
|
||||||
|
icon="mdi-upload"
|
||||||
|
color="info"
|
||||||
|
label="อัปโหลดเอกสาร"
|
||||||
|
>
|
||||||
|
<q-list v-for="(v, i) in dropdownList" :key="v.value">
|
||||||
<q-item
|
<q-item
|
||||||
clickable
|
clickable
|
||||||
v-close-popup
|
v-close-popup
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
currentIndexDropdownList = i;
|
currentIndexDropdownList = i;
|
||||||
|
const _idx = file.findIndex(
|
||||||
|
(v) => v.group === dropdownList?.[i].value,
|
||||||
|
);
|
||||||
|
if (_idx !== -1) {
|
||||||
|
currentIndex = _idx;
|
||||||
|
} else {
|
||||||
|
file.push({
|
||||||
|
group: dropdownList?.[i].value || 'other',
|
||||||
|
});
|
||||||
|
currentIndex = file.length - 1;
|
||||||
|
}
|
||||||
browse();
|
browse();
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>{{ v }}</q-item-label>
|
<q-item-label>{{ $t(v.label) }}</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
</q-btn-dropdown>
|
</q-btn-dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="full-height bordered-l bordered-b q-pa-sm">
|
<div class="bordered-l bordered-b q-pa-sm col full-height scroll">
|
||||||
<q-tree
|
<q-tree
|
||||||
:nodes="tree || []"
|
:nodes="treeFile || []"
|
||||||
node-key="label"
|
node-key="label"
|
||||||
|
label-key="label"
|
||||||
|
children-key="file"
|
||||||
selected-color="primary"
|
selected-color="primary"
|
||||||
v-model:selected="selected"
|
v-model:selected="currentFileSelected"
|
||||||
default-expand-all
|
default-expand-all
|
||||||
/>
|
>
|
||||||
|
<template v-slot:default-header="prop">
|
||||||
|
<div class="ellipsis">
|
||||||
|
<q-tooltip>{{ prop.node.label }}</q-tooltip>
|
||||||
|
{{ prop.node.label }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-tree>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col">
|
<div class="col column no-wrap">
|
||||||
<div
|
<div
|
||||||
class="bordered row items-center justify-evenly q-pa-sm"
|
class="bordered row items-center justify-evenly q-pa-sm no-wrap"
|
||||||
style="height: 50px"
|
style="height: 50px"
|
||||||
>
|
>
|
||||||
<q-btn
|
<q-btn
|
||||||
|
|
@ -125,7 +177,7 @@ const emit = defineEmits<{
|
||||||
id="btn-prev-page-top"
|
id="btn-prev-page-top"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div>Page {{ page }} of {{ pages }}</div>
|
<div class="ellipsis">Page {{ page }} of {{ pages }}</div>
|
||||||
|
|
||||||
<q-btn
|
<q-btn
|
||||||
@click="scale = scale > 0.25 ? scale - 0.25 : scale"
|
@click="scale = scale > 0.25 ? scale - 0.25 : scale"
|
||||||
|
|
@ -149,7 +201,7 @@ const emit = defineEmits<{
|
||||||
icon="mdi-magnify-plus-outline"
|
icon="mdi-magnify-plus-outline"
|
||||||
@click="scale = scale < 2 ? scale + 0.25 : scale"
|
@click="scale = scale < 2 ? scale + 0.25 : scale"
|
||||||
>
|
>
|
||||||
<q-tooltip>{{ $t('zoomIn') }}</q-tooltip>
|
<q-tooltip>{{ $t('general.zoomIn') }}</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
|
|
||||||
<q-btn
|
<q-btn
|
||||||
|
|
@ -165,52 +217,97 @@ const emit = defineEmits<{
|
||||||
<div
|
<div
|
||||||
class="flex flex-center surface-2 bordered-l bordered-r bordered-b full-height scroll"
|
class="flex flex-center surface-2 bordered-l bordered-r bordered-b full-height scroll"
|
||||||
>
|
>
|
||||||
<VuePDF
|
<template v-if="statusOcr">
|
||||||
v-if="file?.type === 'application/pdf'"
|
<q-spinner color="primary" size="3em" :thickness="2" />
|
||||||
class="q-py-md"
|
</template>
|
||||||
:pdf="pdf"
|
|
||||||
:page="page"
|
<template v-else>
|
||||||
:scale="scale"
|
<VuePDF
|
||||||
/>
|
v-if="
|
||||||
<q-img v-else class="q-py-md full-width" :src="currentFileUrl" />
|
currentFile?.url?.split('?').at(0)?.endsWith('.pdf') ||
|
||||||
|
currentFile?.file?.type === 'application/pdf'
|
||||||
|
"
|
||||||
|
class="q-py-md"
|
||||||
|
:pdf="pdf"
|
||||||
|
:page="page"
|
||||||
|
:scale="scale"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-img v-else class="q-py-md full-width" :src="currentFile?.url" />
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-4">
|
<div class="col-5 column no-wrap">
|
||||||
<div
|
<div
|
||||||
class="bordered row items-center justify-between q-pa-sm"
|
class="bordered row items-center justify-between q-pa-sm"
|
||||||
style="height: 50px"
|
style="height: 50px"
|
||||||
>
|
>
|
||||||
ข้อมูลหนังสือเดินทาง
|
{{ $t(currentMode) }}
|
||||||
|
<div class="row" v-if="!hideAction">
|
||||||
<div class="row">
|
|
||||||
<UndoButton icon-only type="button" />
|
<UndoButton icon-only type="button" />
|
||||||
<SaveButton icon-only type="button" />
|
<SaveButton
|
||||||
|
icon-only
|
||||||
|
type="button"
|
||||||
|
@click="
|
||||||
|
$emit(
|
||||||
|
'save',
|
||||||
|
dropdownList?.[currentIndexDropdownList].value || '',
|
||||||
|
inputFile?.files?.[0],
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bordered-r bordered-b full-height">
|
<div class="q-pa-sm bordered-r bordered-b full-height col scroll">
|
||||||
<q-tabs
|
<slot name="form" :mode="currentMode" />
|
||||||
dense
|
|
||||||
inline-label
|
<div class="row items-center">
|
||||||
mobile-arrows
|
{{ currentFileSelected }}
|
||||||
v-model="currentTab"
|
<CloseButton
|
||||||
active-class="active-tab text-weight-bold"
|
icon-only
|
||||||
class="app-text-muted full-width"
|
v-if="!readonly"
|
||||||
align="left"
|
type="button"
|
||||||
>
|
class="q-ml-sm"
|
||||||
<q-tab
|
@click="
|
||||||
:id="`tab-${tab.label}`"
|
() => {
|
||||||
v-for="tab in tabsList"
|
const tempValue = treeFile.find(
|
||||||
v-bind:key="tab.name"
|
(v) => v.label === $t(`customer.typeFile.${currentMode}`),
|
||||||
class="content-tab text-capitalize"
|
);
|
||||||
:name="tab.name"
|
|
||||||
:label="$t(tab.label)"
|
if (!tempValue) return;
|
||||||
|
|
||||||
|
const idx = tempValue.file?.findIndex(
|
||||||
|
(v) => v.label === currentFileSelected,
|
||||||
|
);
|
||||||
|
|
||||||
|
dialog({
|
||||||
|
color: 'negative',
|
||||||
|
icon: 'mdi-alert',
|
||||||
|
title: $t('dialog.title.confirmDelete'),
|
||||||
|
actionText: $t('general.delete'),
|
||||||
|
persistent: true,
|
||||||
|
message: $t('dialog.message.confirmDelete'),
|
||||||
|
action: async () => {
|
||||||
|
$emit('deleteFile', currentFileSelected);
|
||||||
|
|
||||||
|
currentFileSelected = tempValue.file?.[idx - 1].label || '';
|
||||||
|
},
|
||||||
|
|
||||||
|
cancel: () => {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</q-tabs>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss"></style>
|
<style lang="scss">
|
||||||
|
.wrapper > * {
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
export { default as UploadFile } from './UploadFile.vue';
|
export { default as UploadFile } from './UploadFile.vue';
|
||||||
|
export { default as FormCitizen } from './FormCitizen.vue';
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ export default {
|
||||||
age: 'Age',
|
age: 'Age',
|
||||||
nationality: 'Nationalality',
|
nationality: 'Nationalality',
|
||||||
times: 'No. {number}',
|
times: 'No. {number}',
|
||||||
|
uploadFile: 'Upload File',
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
dashboard: 'Dashboard',
|
dashboard: 'Dashboard',
|
||||||
|
|
@ -238,6 +239,17 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
customer: {
|
customer: {
|
||||||
|
typeFile: {
|
||||||
|
citizenId: 'National ID card',
|
||||||
|
registrationBook: 'Household registration',
|
||||||
|
houseMap: 'House map',
|
||||||
|
businessRegistration: 'Commercial registration',
|
||||||
|
dbdCertificate: 'DBD Certificate',
|
||||||
|
VatRegistrationCertificate: 'VAT Registration Certificate',
|
||||||
|
powerOfAttorney: 'Power of Attorney',
|
||||||
|
others: 'Others',
|
||||||
|
},
|
||||||
|
|
||||||
employer: 'Employer',
|
employer: 'Employer',
|
||||||
employerLegalEntity: 'Legal Entity',
|
employerLegalEntity: 'Legal Entity',
|
||||||
employerNaturalPerson: 'Natrual Person',
|
employerNaturalPerson: 'Natrual Person',
|
||||||
|
|
@ -255,6 +267,11 @@ export default {
|
||||||
miss: 'Miss.',
|
miss: 'Miss.',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
citizenId: 'Citizen ID',
|
||||||
|
religion: 'Religion',
|
||||||
|
issueDate: 'Issue Date',
|
||||||
|
passportExpiryDate: 'Passport Expiry Date',
|
||||||
|
|
||||||
firstName: 'First Name in Thai',
|
firstName: 'First Name in Thai',
|
||||||
lastName: 'Last Name in Thai',
|
lastName: 'Last Name in Thai',
|
||||||
firstNameEN: 'First Name in English',
|
firstNameEN: 'First Name in English',
|
||||||
|
|
@ -385,6 +402,20 @@ export default {
|
||||||
mother: 'Mother',
|
mother: 'Mother',
|
||||||
motherBirthPlace: 'Mother Birth Place',
|
motherBirthPlace: 'Mother Birth Place',
|
||||||
},
|
},
|
||||||
|
fileType: {
|
||||||
|
passport: 'Passport',
|
||||||
|
visa: 'VISA',
|
||||||
|
tm6: 'TM.6',
|
||||||
|
workPermit: 'Work Permit',
|
||||||
|
noticeJobEmployment: 'Foreign Worker Employment Notification Form',
|
||||||
|
noticeJobEntry:
|
||||||
|
'Foreign Worker Employment Commencement Notification Form',
|
||||||
|
historyJob: 'Employment History Form',
|
||||||
|
acceptJob:
|
||||||
|
'Acknowledgement of Foreign Worker Employment Notification Form',
|
||||||
|
receipt: 'Receipt',
|
||||||
|
other: 'Other',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
customerBranch: {
|
customerBranch: {
|
||||||
tab: {
|
tab: {
|
||||||
|
|
@ -392,7 +423,7 @@ export default {
|
||||||
address: 'Address',
|
address: 'Address',
|
||||||
business: 'Business',
|
business: 'Business',
|
||||||
contact: 'Contact',
|
contact: 'Contact',
|
||||||
attachment: 'Attachment',
|
attachment: 'Upload Document',
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
title: 'Branch',
|
title: 'Branch',
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ export default {
|
||||||
age: 'อายุ',
|
age: 'อายุ',
|
||||||
nationality: 'สัญชาติ',
|
nationality: 'สัญชาติ',
|
||||||
times: 'ครั้งที่ {number}',
|
times: 'ครั้งที่ {number}',
|
||||||
|
uploadFile: 'อัปโหลดไฟล์',
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
dashboard: 'แดชบอร์ด',
|
dashboard: 'แดชบอร์ด',
|
||||||
|
|
@ -239,6 +240,16 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
customer: {
|
customer: {
|
||||||
|
typeFile: {
|
||||||
|
citizenId: 'บัตรประจำตัวประชาชน',
|
||||||
|
registrationBook: 'ทะเบียนบ้าน',
|
||||||
|
houseMap: 'แผนที่ (บ้าน)',
|
||||||
|
businessRegistration: 'ทะเบียนพาณิชย์',
|
||||||
|
dbdCertificate: 'หนังสือรับรอง (DBD)',
|
||||||
|
VatRegistrationCertificate: 'ภ.พ.20',
|
||||||
|
powerOfAttorney: 'หนังสือมอบอำนาจ',
|
||||||
|
others: 'อื่นๆ',
|
||||||
|
},
|
||||||
employer: 'นายจ้าง',
|
employer: 'นายจ้าง',
|
||||||
employee: 'ลูกจ้าง',
|
employee: 'ลูกจ้าง',
|
||||||
employerLegalEntity: 'นิติบุคคล',
|
employerLegalEntity: 'นิติบุคคล',
|
||||||
|
|
@ -256,6 +267,11 @@ export default {
|
||||||
miss: 'Miss.',
|
miss: 'Miss.',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
citizenId: 'บัตรประจำตัวประชาชน',
|
||||||
|
religion: 'ศาสนา',
|
||||||
|
issueDate: 'วันที่ออกหนังสือ',
|
||||||
|
passportExpiryDate: 'วันหiมดอายุหนังสือเดินทาง',
|
||||||
|
|
||||||
firstName: 'ชื่อ ภาษาไทย',
|
firstName: 'ชื่อ ภาษาไทย',
|
||||||
lastName: 'นามสกุล ภาษาไทย',
|
lastName: 'นามสกุล ภาษาไทย',
|
||||||
firstNameEN: 'ชื่อ ภาษาอังกฤษ',
|
firstNameEN: 'ชื่อ ภาษาอังกฤษ',
|
||||||
|
|
@ -385,6 +401,18 @@ export default {
|
||||||
mother: 'มารดา',
|
mother: 'มารดา',
|
||||||
motherBirthPlace: 'สถานที่เกิดของมารดา',
|
motherBirthPlace: 'สถานที่เกิดของมารดา',
|
||||||
},
|
},
|
||||||
|
fileType: {
|
||||||
|
passport: 'ข้อมูลหนังสือการเดินทาง',
|
||||||
|
visa: 'ข้อมูลการตรวจลงตรา',
|
||||||
|
tm6: 'ตม.6',
|
||||||
|
workPermit: 'ใบอนุญาตทำงาน',
|
||||||
|
noticeJobEmployment: 'แบบแจ้งการจ้างคนต่างด้าวทำงาน',
|
||||||
|
noticeJobEntry: 'แบบแจ้งเข้าทำงานของคนต่างด้าว',
|
||||||
|
historyJob: 'ใบคัดประวัติระบบจัดหางาน',
|
||||||
|
acceptJob: 'ใบตอบรับการแจ้งเกี่ยวกับการทำงานของคนต่างด้าว',
|
||||||
|
receipt: 'ใบเสร็จรับเงิน',
|
||||||
|
other: 'อื่นๆ',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
customerBranch: {
|
customerBranch: {
|
||||||
tab: {
|
tab: {
|
||||||
|
|
@ -392,7 +420,7 @@ export default {
|
||||||
address: 'ที่อยู่',
|
address: 'ที่อยู่',
|
||||||
business: 'ธุรกิจ',
|
business: 'ธุรกิจ',
|
||||||
contact: 'ติดต่อ',
|
contact: 'ติดต่อ',
|
||||||
attachment: 'เอกสารเพิ่มเติม',
|
attachment: 'อัปโหลดเอกสาร',
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
title: 'สาขา',
|
title: 'สาขา',
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,8 @@ import {
|
||||||
columnsCustomer,
|
columnsCustomer,
|
||||||
columnsEmployee,
|
columnsEmployee,
|
||||||
formMenuIconEmployee,
|
formMenuIconEmployee,
|
||||||
uploadFileList,
|
uploadFileListEmployee,
|
||||||
|
uploadFileListCustomer,
|
||||||
} from './constant';
|
} from './constant';
|
||||||
import { useCustomerForm, useEmployeeForm } from './form';
|
import { useCustomerForm, useEmployeeForm } from './form';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
@ -1871,6 +1872,7 @@ const emptyCreateDialog = ref(false);
|
||||||
<EmployerFormBranch
|
<EmployerFormBranch
|
||||||
v-if="!!customerFormState.editCustomerId"
|
v-if="!!customerFormState.editCustomerId"
|
||||||
:index="idx"
|
:index="idx"
|
||||||
|
v-model:customer="customerFormData"
|
||||||
v-model:customer-branch="customerFormData.customerBranch[idx]"
|
v-model:customer-branch="customerFormData.customerBranch[idx]"
|
||||||
:customer-type="customerFormData.customerType"
|
:customer-type="customerFormData.customerType"
|
||||||
:customer-name="`${customerFormData.firstName} ${customerFormData.lastName}`"
|
:customer-name="`${customerFormData.firstName} ${customerFormData.lastName}`"
|
||||||
|
|
@ -2049,6 +2051,11 @@ const emptyCreateDialog = ref(false);
|
||||||
anchor: 'form-visa',
|
anchor: 'form-visa',
|
||||||
tab: 'personalInfo',
|
tab: 'personalInfo',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: $t('general.uploadFile'),
|
||||||
|
anchor: 'drawer-info-file-upload',
|
||||||
|
tab: 'personalInfo',
|
||||||
|
},
|
||||||
...(currentFromDataEmployee.employeeCheckup?.map((v, i) => ({
|
...(currentFromDataEmployee.employeeCheckup?.map((v, i) => ({
|
||||||
name: $t('general.times', { number: i + 1 }),
|
name: $t('general.times', { number: i + 1 }),
|
||||||
anchor: `form-employee-checkup-${i}`,
|
anchor: `form-employee-checkup-${i}`,
|
||||||
|
|
@ -2160,6 +2167,7 @@ const emptyCreateDialog = ref(false);
|
||||||
employee
|
employee
|
||||||
separator
|
separator
|
||||||
title="customerEmployee.form.group.personalInfo"
|
title="customerEmployee.form.group.personalInfo"
|
||||||
|
:readonly="!employeeFormState.isEmployeeEdit"
|
||||||
v-model:open="employeeFormState.dialogModal"
|
v-model:open="employeeFormState.dialogModal"
|
||||||
v-model:prefixName="currentFromDataEmployee.namePrefix"
|
v-model:prefixName="currentFromDataEmployee.namePrefix"
|
||||||
v-model:firstName="currentFromDataEmployee.firstName"
|
v-model:firstName="currentFromDataEmployee.firstName"
|
||||||
|
|
@ -2176,6 +2184,7 @@ const emptyCreateDialog = ref(false);
|
||||||
<AddressForm
|
<AddressForm
|
||||||
id="form-personal-address"
|
id="form-personal-address"
|
||||||
prefix-id="form-employee"
|
prefix-id="form-employee"
|
||||||
|
:readonly="!employeeFormState.isEmployeeEdit"
|
||||||
v-model:same-with-employer="
|
v-model:same-with-employer="
|
||||||
employeeFormState.formDataEmployeeSameAddr
|
employeeFormState.formDataEmployeeSameAddr
|
||||||
"
|
"
|
||||||
|
|
@ -2197,6 +2206,7 @@ const emptyCreateDialog = ref(false);
|
||||||
outlined
|
outlined
|
||||||
separator
|
separator
|
||||||
:title="$t('customerEmployee.form.group.passport')"
|
:title="$t('customerEmployee.form.group.passport')"
|
||||||
|
:readonly="!employeeFormState.isEmployeeEdit"
|
||||||
v-model:passport-type="currentFromDataEmployee.passportType"
|
v-model:passport-type="currentFromDataEmployee.passportType"
|
||||||
v-model:passport-number="currentFromDataEmployee.passportNumber"
|
v-model:passport-number="currentFromDataEmployee.passportNumber"
|
||||||
v-model:passport-issue-date="
|
v-model:passport-issue-date="
|
||||||
|
|
@ -2223,6 +2233,7 @@ const emptyCreateDialog = ref(false);
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
title="customerEmployee.form.group.visa"
|
title="customerEmployee.form.group.visa"
|
||||||
|
:readonly="!employeeFormState.isEmployeeEdit"
|
||||||
v-model:visa-type="currentFromDataEmployee.visaType"
|
v-model:visa-type="currentFromDataEmployee.visaType"
|
||||||
v-model:visa-number="currentFromDataEmployee.visaNumber"
|
v-model:visa-number="currentFromDataEmployee.visaNumber"
|
||||||
v-model:visa-issue-date="currentFromDataEmployee.visaIssueDate"
|
v-model:visa-issue-date="currentFromDataEmployee.visaIssueDate"
|
||||||
|
|
@ -2237,6 +2248,84 @@ const emptyCreateDialog = ref(false);
|
||||||
v-model:entry-date="currentFromDataEmployee.entryDate"
|
v-model:entry-date="currentFromDataEmployee.entryDate"
|
||||||
class="q-mb-xl"
|
class="q-mb-xl"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div class="row q-mb-md" id="drawer-info-file-upload">
|
||||||
|
<div class="col-12 q-pb-sm text-weight-bold text-body1">
|
||||||
|
<q-icon
|
||||||
|
flat
|
||||||
|
size="xs"
|
||||||
|
class="q-pa-sm rounded q-mr-xs"
|
||||||
|
color="info"
|
||||||
|
name="mdi-upload"
|
||||||
|
style="background-color: var(--surface-3)"
|
||||||
|
/>
|
||||||
|
{{ $t(`general.uploadFile`) }}
|
||||||
|
</div>
|
||||||
|
<UploadFile
|
||||||
|
:tree-file="
|
||||||
|
Object.values(
|
||||||
|
currentFromDataEmployee.file?.reduce<
|
||||||
|
Record<
|
||||||
|
string,
|
||||||
|
{ label: string; file: { label: string }[] }
|
||||||
|
>
|
||||||
|
>((a, c) => {
|
||||||
|
const _group = c.group || 'other';
|
||||||
|
if (!a[_group]) {
|
||||||
|
a[_group] = {
|
||||||
|
label: $t(
|
||||||
|
uploadFileListEmployee.find(
|
||||||
|
(v) => v.value === _group,
|
||||||
|
)?.label || _group,
|
||||||
|
),
|
||||||
|
file: [
|
||||||
|
{
|
||||||
|
label:
|
||||||
|
c.name ||
|
||||||
|
`${c.group}-${c.file?.name || Date.now()}`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
a[_group].file.push({
|
||||||
|
label:
|
||||||
|
c.name ||
|
||||||
|
`${c.group}-${c.file?.name || Date.now()}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}, {}) || {},
|
||||||
|
)
|
||||||
|
"
|
||||||
|
v-model:file="currentFromDataEmployee.file"
|
||||||
|
hide-action
|
||||||
|
v-model:status-ocr="employeeFormState.ocr"
|
||||||
|
:readonly="!employeeFormState.isEmployeeEdit"
|
||||||
|
:dropdown-list="uploadFileListEmployee"
|
||||||
|
@delete-file="
|
||||||
|
async (filename) => {
|
||||||
|
if (currentFromDataEmployee.id) {
|
||||||
|
const result = await employeeStore.deleteAttachment(
|
||||||
|
currentFromDataEmployee.id,
|
||||||
|
filename,
|
||||||
|
);
|
||||||
|
if (result) {
|
||||||
|
currentFromDataEmployee.file =
|
||||||
|
currentFromDataEmployee.file?.filter(
|
||||||
|
(v) => v.name !== filename,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@send-ocr="
|
||||||
|
async (_, file) => {
|
||||||
|
if (file) await ocrStore.sendOcr({ file });
|
||||||
|
employeeFormState.ocr = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="employeeFormState.currentTab === 'healthCheck'">
|
<template v-if="employeeFormState.currentTab === 'healthCheck'">
|
||||||
|
|
@ -2338,6 +2427,7 @@ const emptyCreateDialog = ref(false);
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
a
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="employeeFormState.currentTab === 'other'">
|
<template v-if="employeeFormState.currentTab === 'other'">
|
||||||
|
|
@ -2466,8 +2556,8 @@ const emptyCreateDialog = ref(false);
|
||||||
"
|
"
|
||||||
:show="
|
:show="
|
||||||
async () => {
|
async () => {
|
||||||
await fetchListOfOptionBranch();
|
// await fetchListOfOptionBranch();
|
||||||
customerFormStore.resetForm(customerFormState.dialogType === 'create');
|
// customerFormStore.resetForm(true);
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
:before-close="
|
:before-close="
|
||||||
|
|
@ -2477,6 +2567,7 @@ const emptyCreateDialog = ref(false);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
fetchListCustomer();
|
fetchListCustomer();
|
||||||
|
customerFormStore.resetForm(true);
|
||||||
customerFormState.branchIndex = -1;
|
customerFormState.branchIndex = -1;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -2515,10 +2606,15 @@ const emptyCreateDialog = ref(false);
|
||||||
name: $t('form.field.basicInformation'),
|
name: $t('form.field.basicInformation'),
|
||||||
anchor: 'form-basic-info-customer',
|
anchor: 'form-basic-info-customer',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: $t('customerBranch.tab.attachment'),
|
||||||
|
anchor: 'form-upload-file-customer',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: $t('customer.form.group.branch'),
|
name: $t('customer.form.group.branch'),
|
||||||
anchor: 'form-branch-customer-branch',
|
anchor: 'form-branch-customer-branch',
|
||||||
},
|
},
|
||||||
|
|
||||||
...(customerFormData.customerBranch?.map((v, i) => ({
|
...(customerFormData.customerBranch?.map((v, i) => ({
|
||||||
name:
|
name:
|
||||||
i === 0
|
i === 0
|
||||||
|
|
@ -2546,7 +2642,6 @@ const emptyCreateDialog = ref(false);
|
||||||
style="height: 100%; max-height: 100%; overflow-y: auto"
|
style="height: 100%; max-height: 100%; overflow-y: auto"
|
||||||
>
|
>
|
||||||
<EmployerFormBasicInfo
|
<EmployerFormBasicInfo
|
||||||
class="q-mb-xl"
|
|
||||||
:readonly="
|
:readonly="
|
||||||
(customerFormState.dialogType === 'edit' &&
|
(customerFormState.dialogType === 'edit' &&
|
||||||
customerFormState.readonly === true) ||
|
customerFormState.readonly === true) ||
|
||||||
|
|
@ -2577,6 +2672,19 @@ const emptyCreateDialog = ref(false);
|
||||||
v-model:birth-date="customerFormData.birthDate"
|
v-model:birth-date="customerFormData.birthDate"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- <div class="row q-col-gutter-sm q-mb-xl">
|
||||||
|
<UploadFile
|
||||||
|
id="form-upload-file-customer"
|
||||||
|
class="q-mb-xl"
|
||||||
|
hide-action
|
||||||
|
:dropdown-list="uploadFileList"
|
||||||
|
v-model:file="customerFormState.file"
|
||||||
|
@send-ocr="
|
||||||
|
(group: any, file: any) => ocrStore.sendOcr({ file })
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
<div class="row q-col-gutter-sm" id="form-branch-customer-branch">
|
<div class="row q-col-gutter-sm" id="form-branch-customer-branch">
|
||||||
<div
|
<div
|
||||||
class="col-12 text-weight-bold text-body1 row items-center"
|
class="col-12 text-weight-bold text-body1 row items-center"
|
||||||
|
|
@ -2663,9 +2771,33 @@ const emptyCreateDialog = ref(false);
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
customerFormData.customerBranch[idx].file?.forEach(
|
||||||
|
async (v) => {
|
||||||
|
if (!v.file) return;
|
||||||
|
|
||||||
|
const ext = v.file.name.split('.').at(-1);
|
||||||
|
let filename = v.group + '-' + new Date().getTime();
|
||||||
|
if (ext) filename += `.${ext}`;
|
||||||
|
|
||||||
|
const res = await customerStore.putAttachment({
|
||||||
|
branchId:
|
||||||
|
customerFormData.customerBranch?.[idx].id || '',
|
||||||
|
file: v.file,
|
||||||
|
filename,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
await customerFormStore.assignFormData(
|
||||||
|
customerFormState.editCustomerId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
await customerFormStore.assignFormData(
|
await customerFormStore.assignFormData(
|
||||||
customerFormState.editCustomerId,
|
customerFormState.editCustomerId,
|
||||||
);
|
);
|
||||||
|
|
||||||
customerFormStore.resetForm();
|
customerFormStore.resetForm();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2674,9 +2806,11 @@ const emptyCreateDialog = ref(false);
|
||||||
<EmployerFormBranch
|
<EmployerFormBranch
|
||||||
v-if="!!customerFormState.editCustomerId"
|
v-if="!!customerFormState.editCustomerId"
|
||||||
:index="idx"
|
:index="idx"
|
||||||
|
v-model:customer="customerFormData"
|
||||||
v-model:customer-branch="
|
v-model:customer-branch="
|
||||||
customerFormData.customerBranch[idx]
|
customerFormData.customerBranch[idx]
|
||||||
"
|
"
|
||||||
|
:tree-file="customerFormState.treeFile"
|
||||||
:customer-type="customerFormData.customerType"
|
:customer-type="customerFormData.customerType"
|
||||||
:customer-name="`${customerFormData.firstName} ${customerFormData.lastName}`"
|
:customer-name="`${customerFormData.firstName} ${customerFormData.lastName}`"
|
||||||
:action-disabled="
|
:action-disabled="
|
||||||
|
|
@ -2869,7 +3003,7 @@ const emptyCreateDialog = ref(false);
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: $t('อัปโหลดไฟล์'),
|
name: $t('general.uploadFile'),
|
||||||
anchor: 'drawer-upload-file',
|
anchor: 'drawer-upload-file',
|
||||||
tab: 'personalInfo',
|
tab: 'personalInfo',
|
||||||
},
|
},
|
||||||
|
|
@ -3062,17 +3196,83 @@ const emptyCreateDialog = ref(false);
|
||||||
class="q-mb-xl"
|
class="q-mb-xl"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<UploadFile
|
<div class="row" id="drawer-upload-file">
|
||||||
:tree="[]"
|
<div class="col-12 q-pb-sm text-weight-bold text-body1">
|
||||||
:dropdown-list="uploadFileList"
|
<q-icon
|
||||||
@send-ocr="
|
flat
|
||||||
async (v: any, f: any) => {
|
size="xs"
|
||||||
console.log(v, f);
|
class="q-pa-sm rounded q-mr-xs"
|
||||||
|
color="info"
|
||||||
await ocrStore.sendOcr({ file: f });
|
name="mdi-upload"
|
||||||
}
|
style="background-color: var(--surface-3)"
|
||||||
"
|
/>
|
||||||
/>
|
{{ $t(`general.uploadFile`) }}
|
||||||
|
</div>
|
||||||
|
<UploadFile
|
||||||
|
:tree-file="
|
||||||
|
Object.values(
|
||||||
|
currentFromDataEmployee.file?.reduce<
|
||||||
|
Record<
|
||||||
|
string,
|
||||||
|
{ label: string; file: { label: string }[] }
|
||||||
|
>
|
||||||
|
>((a, c) => {
|
||||||
|
const _group = c.group || 'other';
|
||||||
|
if (!a[_group]) {
|
||||||
|
a[_group] = {
|
||||||
|
label: $t(
|
||||||
|
uploadFileListEmployee.find(
|
||||||
|
(v) => v.value === _group,
|
||||||
|
)?.label || _group,
|
||||||
|
),
|
||||||
|
file: [
|
||||||
|
{
|
||||||
|
label:
|
||||||
|
c.name ||
|
||||||
|
`${c.group}-${c.file?.name || Date.now()}`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
a[_group].file.push({
|
||||||
|
label:
|
||||||
|
c.name ||
|
||||||
|
`${c.group}-${c.file?.name || Date.now()}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}, {}) || {},
|
||||||
|
)
|
||||||
|
"
|
||||||
|
v-model:file="currentFromDataEmployee.file"
|
||||||
|
hide-action
|
||||||
|
v-model:status-ocr="employeeFormState.ocr"
|
||||||
|
:readonly="!employeeFormState.isEmployeeEdit"
|
||||||
|
:dropdown-list="uploadFileListEmployee"
|
||||||
|
@delete-file="
|
||||||
|
async (filename) => {
|
||||||
|
if (currentFromDataEmployee.id) {
|
||||||
|
const result = await employeeStore.deleteAttachment(
|
||||||
|
currentFromDataEmployee.id,
|
||||||
|
filename,
|
||||||
|
);
|
||||||
|
if (result) {
|
||||||
|
currentFromDataEmployee.file =
|
||||||
|
currentFromDataEmployee.file?.filter(
|
||||||
|
(v) => v.name !== filename,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@send-ocr="
|
||||||
|
async (_, file) => {
|
||||||
|
if (file) await ocrStore.sendOcr({ file });
|
||||||
|
employeeFormState.ocr = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="employeeFormState.currentTab === 'healthCheck'">
|
<template v-if="employeeFormState.currentTab === 'healthCheck'">
|
||||||
<FormEmployeeHealthCheck
|
<FormEmployeeHealthCheck
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,32 @@ import EmployerFormBusiness from './EmployerFormBusiness.vue';
|
||||||
import EmployerFormContact from './EmployerFormContact.vue';
|
import EmployerFormContact from './EmployerFormContact.vue';
|
||||||
import { CustomerCreate } from 'stores/customer/types';
|
import { CustomerCreate } from 'stores/customer/types';
|
||||||
import EmployerFormAbout from './EmployerFormAbout.vue';
|
import EmployerFormAbout from './EmployerFormAbout.vue';
|
||||||
import EmployerFormAttachment from './EmployerFormAttachment.vue';
|
import { useCustomerForm } from 'src/pages/03_customer-management/form';
|
||||||
|
|
||||||
|
const customerFormStore = useCustomerForm();
|
||||||
|
import { FormCitizen } from 'components/upload-file/';
|
||||||
|
|
||||||
|
import useOcrStore from 'stores/ocr';
|
||||||
|
|
||||||
|
const ocrStore = useOcrStore();
|
||||||
import {
|
import {
|
||||||
SaveButton,
|
SaveButton,
|
||||||
EditButton,
|
EditButton,
|
||||||
DeleteButton,
|
DeleteButton,
|
||||||
UndoButton,
|
UndoButton,
|
||||||
} from 'components/button';
|
} from 'components/button';
|
||||||
|
import UploadFile from 'src/components/upload-file/UploadFile.vue';
|
||||||
|
import { uploadFileListCustomer } from '../../constant';
|
||||||
|
|
||||||
|
const statusOcr = ref(false);
|
||||||
|
|
||||||
|
const customer = defineModel<CustomerCreate>('customer', { required: true });
|
||||||
|
|
||||||
const item = defineModel<NonNullable<CustomerCreate['customerBranch']>[number]>(
|
const item = defineModel<NonNullable<CustomerCreate['customerBranch']>[number]>(
|
||||||
'customerBranch',
|
'customerBranch',
|
||||||
{ required: true },
|
{ required: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
const tab = ref('main');
|
const tab = ref('main');
|
||||||
|
|
||||||
defineEmits<{
|
defineEmits<{
|
||||||
|
|
@ -33,6 +47,7 @@ defineProps<{
|
||||||
prefixId?: string;
|
prefixId?: string;
|
||||||
actionDisabled?: boolean;
|
actionDisabled?: boolean;
|
||||||
customerType?: 'CORP' | 'PERS';
|
customerType?: 'CORP' | 'PERS';
|
||||||
|
treeFile?: { label: string; file: { label: string }[] }[];
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -160,10 +175,103 @@ defineProps<{
|
||||||
/>
|
/>
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
<q-tab-panel name="attachment">
|
<q-tab-panel name="attachment">
|
||||||
<EmployerFormAttachment
|
<UploadFile
|
||||||
|
hide-action
|
||||||
|
:readonly="readonly"
|
||||||
|
:dropdown-list="uploadFileListCustomer"
|
||||||
|
v-model:status-ocr="statusOcr"
|
||||||
|
v-model:file="item.file"
|
||||||
|
:tree-file="
|
||||||
|
Object.values(
|
||||||
|
item.file?.reduce<
|
||||||
|
Record<string, { label: string; file: { label: string }[] }>
|
||||||
|
>((a, c) => {
|
||||||
|
const _group = c.group || 'other';
|
||||||
|
console.log(c);
|
||||||
|
|
||||||
|
if (!a[_group]) {
|
||||||
|
a[_group] = {
|
||||||
|
label: $t(
|
||||||
|
uploadFileListCustomer.find((v) => v.value === _group)
|
||||||
|
?.label || _group,
|
||||||
|
),
|
||||||
|
file: [
|
||||||
|
{
|
||||||
|
label:
|
||||||
|
c.name ||
|
||||||
|
`${c.group}-${c.file?.name || Date.now()}`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
a[_group].file.push({
|
||||||
|
label:
|
||||||
|
c.name || `${c.group}-${c.file?.name || Date.now()}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}, {}) || {},
|
||||||
|
)
|
||||||
|
"
|
||||||
|
@send-ocr="
|
||||||
|
async (v: any, f: any) => {
|
||||||
|
const res = await ocrStore.sendOcr({ file: f });
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
const map = res.fields.reduce<Record<string, string>>(
|
||||||
|
(a, c) => {
|
||||||
|
a[c.name] = c.value;
|
||||||
|
return a;
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
if (!item.citizenId) item.citizenId = map['citizen_id'] || '';
|
||||||
|
if (!item.address) item.address = map['address'] || '';
|
||||||
|
if (!customer.firstName)
|
||||||
|
customer.firstName = map['firstname'] || '';
|
||||||
|
if (!customer.lastName)
|
||||||
|
customer.lastName = map['lastname'] || '';
|
||||||
|
if (!customer.firstNameEN)
|
||||||
|
customer.firstNameEN = map['firstname_en'] || '';
|
||||||
|
if (!customer.lastNameEN)
|
||||||
|
customer.lastNameEN = map['lastname_en'] || '';
|
||||||
|
if (!customer.birthDate)
|
||||||
|
customer.birthDate = new Date(map['birth_date'] || '');
|
||||||
|
}
|
||||||
|
|
||||||
|
statusOcr = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@delete-file="
|
||||||
|
(filename) => {
|
||||||
|
if (!item.id) return;
|
||||||
|
|
||||||
|
customerFormStore.deleteAttachment(
|
||||||
|
{ branchId: item.id, customerId: item.customerId },
|
||||||
|
filename,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #form="{ mode }">
|
||||||
|
<FormCitizen
|
||||||
|
v-if="mode === 'citizenId'"
|
||||||
|
orc
|
||||||
|
v-model:citizen-id="item.citizenId"
|
||||||
|
v-model:birth-date="customer.birthDate"
|
||||||
|
v-model:first-name="customer.firstName"
|
||||||
|
v-model:first-name-en="customer.firstNameEN"
|
||||||
|
v-model:last-name="customer.lastName"
|
||||||
|
v-model:last-name-en="customer.lastNameEN"
|
||||||
|
v-model:address="item.address"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</UploadFile>
|
||||||
|
|
||||||
|
<!-- <EmployerFormAttachment
|
||||||
:readonly="readonly"
|
:readonly="readonly"
|
||||||
v-model:attachment="item.file"
|
v-model:attachment="item.file"
|
||||||
/>
|
/> -->
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
</q-tab-panels>
|
</q-tab-panels>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,93 @@
|
||||||
import { QTableProps } from 'quasar';
|
import { QTableProps } from 'quasar';
|
||||||
|
|
||||||
export const uploadFileList: string[] = [
|
export const uploadFileListCustomer: {
|
||||||
'ข้อมูลหนังสือการเดินทาง',
|
label: string;
|
||||||
'ข้อมูลการตรวจลงตรา',
|
value: string;
|
||||||
'ตม.6',
|
}[] = [
|
||||||
'ใบอนุญาตทำงาน',
|
{
|
||||||
'แบบแจ้งการจ้างคนต่างด้าวทำงาน',
|
label: 'customer.typeFile.citizenId',
|
||||||
'แบบแจ้งเข้าทำงานของคนต่างด้าว',
|
value: 'citizenId',
|
||||||
'ใบคัดประวัติระบบจัดหางาน',
|
},
|
||||||
'ใบตอบรับการแจ้งเกี่ยวกับการทำงานของคนต่างด้าว',
|
{
|
||||||
'ใบเสร็จรับเงิน',
|
label: 'customer.typeFile.registrationBook',
|
||||||
'อื่นๆ',
|
value: 'registrationBook',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: 'customer.typeFile.houseMap',
|
||||||
|
value: 'houseMap',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: 'customer.typeFile.businessRegistration',
|
||||||
|
value: 'businessRegistration',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: 'customer.typeFile.dbdCertificate',
|
||||||
|
value: 'dbdCertificate',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: 'customer.typeFile.vatRegistrationCertificate',
|
||||||
|
value: 'vatRegistrationCertificate',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: 'customer.typeFile.powerOfAttorney',
|
||||||
|
value: 'powerOfAttorney',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: 'customer.typeFile.others',
|
||||||
|
value: 'others',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const uploadFileListEmployee: {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
label: 'customerEmployee.fileType.passport',
|
||||||
|
value: 'passport',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'customerEmployee.fileType.visa',
|
||||||
|
value: 'visa',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'customerEmployee.fileType.tm6',
|
||||||
|
value: 'tm6',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'customerEmployee.fileType.workPermit',
|
||||||
|
value: 'workPermit',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'customerEmployee.fileType.noticeJobEmployment',
|
||||||
|
value: 'noticeJobEmployment',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'customerEmployee.fileType.noticeJobEntry',
|
||||||
|
value: 'noticeJobEntry',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'customerEmployee.fileType.historyJob',
|
||||||
|
value: 'historyJob',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'customerEmployee.fileType.acceptJob',
|
||||||
|
value: 'acceptJob',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'customerEmployee.fileType.receipt',
|
||||||
|
value: 'receipt',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'customerEmployee.fileType.other',
|
||||||
|
value: 'other',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const formMenuIconEmployee = [
|
export const formMenuIconEmployee = [
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { ref, toRaw, watch } from 'vue';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { CustomerBranchCreate, CustomerCreate } from 'stores/customer/types';
|
import { CustomerBranchCreate, CustomerCreate } from 'stores/customer/types';
|
||||||
import { Employee, EmployeeCreate } from 'stores/employee/types';
|
import { Employee, EmployeeCreate } from 'stores/employee/types';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import useMyBranch from 'stores/my-branch';
|
import useMyBranch from 'stores/my-branch';
|
||||||
import useCustomerStore from 'stores/customer';
|
import useCustomerStore from 'stores/customer';
|
||||||
|
|
@ -9,6 +10,7 @@ import useEmployeeStore from 'stores/employee';
|
||||||
import useFlowStore from 'stores/flow';
|
import useFlowStore from 'stores/flow';
|
||||||
|
|
||||||
export const useCustomerForm = defineStore('form-customer', () => {
|
export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
|
const { t } = useI18n();
|
||||||
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
|
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
|
||||||
|
|
||||||
const customerStore = useCustomerStore();
|
const customerStore = useCustomerStore();
|
||||||
|
|
@ -46,6 +48,8 @@ export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
editCustomerId?: string;
|
editCustomerId?: string;
|
||||||
editCustomerCode?: string;
|
editCustomerCode?: string;
|
||||||
editCustomerBranchId?: string;
|
editCustomerBranchId?: string;
|
||||||
|
treeFile: { label: string; file: { label: string }[] }[];
|
||||||
|
formDataOcr: Record<string, any>;
|
||||||
}>({
|
}>({
|
||||||
dialogType: 'info',
|
dialogType: 'info',
|
||||||
dialogOpen: false,
|
dialogOpen: false,
|
||||||
|
|
@ -59,6 +63,8 @@ export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
editCustomerId: '',
|
editCustomerId: '',
|
||||||
editCustomerBranchId: '',
|
editCustomerBranchId: '',
|
||||||
defaultCustomerImageUrl: '',
|
defaultCustomerImageUrl: '',
|
||||||
|
treeFile: [],
|
||||||
|
formDataOcr: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
@ -66,6 +72,16 @@ export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
(v) => (defaultFormData.customerType = v.customerType),
|
(v) => (defaultFormData.customerType = v.customerType),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
async function deleteAttachment(
|
||||||
|
id: { branchId: string; customerId: string },
|
||||||
|
filename: string,
|
||||||
|
) {
|
||||||
|
const res = await customerStore.deleteAttachment(id.branchId, filename);
|
||||||
|
if (res) {
|
||||||
|
assignFormData(id.customerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function isFormDataDifferent() {
|
function isFormDataDifferent() {
|
||||||
return (
|
return (
|
||||||
JSON.stringify(resetFormData) !== JSON.stringify(currentFormData.value)
|
JSON.stringify(resetFormData) !== JSON.stringify(currentFormData.value)
|
||||||
|
|
@ -82,6 +98,8 @@ export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
resetFormData = structuredClone(defaultFormData);
|
resetFormData = structuredClone(defaultFormData);
|
||||||
resetFormData.registeredBranchId = branchStore.currentMyBranch?.id || '';
|
resetFormData.registeredBranchId = branchStore.currentMyBranch?.id || '';
|
||||||
state.value.editCustomerId = '';
|
state.value.editCustomerId = '';
|
||||||
|
state.value.treeFile = [];
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,41 +145,59 @@ export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
resetFormData.birthDate = new Date(data.birthDate);
|
resetFormData.birthDate = new Date(data.birthDate);
|
||||||
resetFormData.image = null;
|
resetFormData.image = null;
|
||||||
|
|
||||||
resetFormData.customerBranch = data.branch.map((v) => ({
|
resetFormData.customerBranch = await Promise.all(
|
||||||
id: v.id,
|
data.branch.map(async (v) => ({
|
||||||
code: v.code || '',
|
id: v.id,
|
||||||
customerCode: '',
|
code: v.code || '',
|
||||||
provinceId: v.provinceId,
|
customerCode: '',
|
||||||
districtId: v.districtId,
|
provinceId: v.provinceId,
|
||||||
subDistrictId: v.subDistrictId,
|
districtId: v.districtId,
|
||||||
wageRate: v.wageRate,
|
subDistrictId: v.subDistrictId,
|
||||||
payDate: new Date(v.payDate), // Convert the string to a Date object
|
wageRate: v.wageRate,
|
||||||
saleEmployee: v.saleEmployee,
|
payDate: new Date(v.payDate), // Convert the string to a Date object
|
||||||
jobDescription: v.jobDescription,
|
saleEmployee: v.saleEmployee,
|
||||||
jobPositionEN: v.jobPositionEN,
|
jobDescription: v.jobDescription,
|
||||||
jobPosition: v.jobPosition,
|
jobPositionEN: v.jobPositionEN,
|
||||||
businessTypeEN: v.businessTypeEN,
|
jobPosition: v.jobPosition,
|
||||||
businessType: v.businessType,
|
businessTypeEN: v.businessTypeEN,
|
||||||
employmentOffice: v.employmentOffice,
|
businessType: v.businessType,
|
||||||
telephoneNo: v.telephoneNo,
|
employmentOffice: v.employmentOffice,
|
||||||
email: v.email,
|
telephoneNo: v.telephoneNo,
|
||||||
addressEN: v.addressEN,
|
email: v.email,
|
||||||
address: v.address,
|
addressEN: v.addressEN,
|
||||||
workplaceEN: v.workplaceEN,
|
address: v.address,
|
||||||
workplace: v.workplace,
|
workplaceEN: v.workplaceEN,
|
||||||
status: v.status,
|
workplace: v.workplace,
|
||||||
customerId: v.customerId,
|
status: v.status,
|
||||||
citizenId: v.citizenId || '',
|
customerId: v.customerId,
|
||||||
authorizedCapital: v.authorizedCapital || '',
|
citizenId: v.citizenId || '',
|
||||||
registerDate: new Date(v.registerDate), // Convert the string to a Date object
|
authorizedCapital: v.authorizedCapital || '',
|
||||||
registerNameEN: v.registerNameEN || '',
|
registerDate: new Date(v.registerDate), // Convert the string to a Date object
|
||||||
registerName: v.registerName || '',
|
registerNameEN: v.registerNameEN || '',
|
||||||
legalPersonNo: v.legalPersonNo || '',
|
registerName: v.registerName || '',
|
||||||
registerCompanyName: '',
|
legalPersonNo: v.legalPersonNo || '',
|
||||||
statusSave: true,
|
registerCompanyName: '',
|
||||||
contactName: v.contactName || '',
|
statusSave: true,
|
||||||
file: undefined,
|
contactName: v.contactName || '',
|
||||||
}));
|
file: await customerStore.listAttachment(v.id).then(async (r) => {
|
||||||
|
if (r) {
|
||||||
|
return await Promise.all(
|
||||||
|
r.map(async (item) => {
|
||||||
|
const fragment = item.split('-');
|
||||||
|
const group = fragment.length === 1 ? 'other' : fragment.at(0);
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: await customerStore.getAttachment(v.id, item),
|
||||||
|
name: item,
|
||||||
|
group: group,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}),
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
currentFormData.value = structuredClone(resetFormData);
|
currentFormData.value = structuredClone(resetFormData);
|
||||||
}
|
}
|
||||||
|
|
@ -269,11 +305,13 @@ export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
assignFormData,
|
assignFormData,
|
||||||
submitFormCustomer,
|
submitFormCustomer,
|
||||||
addCurrentCustomerBranch,
|
addCurrentCustomerBranch,
|
||||||
|
deleteAttachment,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useCustomerBranchForm = defineStore('form-customer-branch', () => {
|
export const useCustomerBranchForm = defineStore('form-customer-branch', () => {
|
||||||
const customerStore = useCustomerStore();
|
const customerStore = useCustomerStore();
|
||||||
|
const customerFormStore = useCustomerForm();
|
||||||
|
|
||||||
const defaultFormData: CustomerBranchCreate & { id?: string } = {
|
const defaultFormData: CustomerBranchCreate & { id?: string } = {
|
||||||
code: '',
|
code: '',
|
||||||
|
|
@ -404,6 +442,10 @@ export const useCustomerBranchForm = defineStore('form-customer-branch', () => {
|
||||||
if (!currentFormData.value.id) {
|
if (!currentFormData.value.id) {
|
||||||
const res = await customerStore.createBranch({
|
const res = await customerStore.createBranch({
|
||||||
...currentFormData.value,
|
...currentFormData.value,
|
||||||
|
citizenId:
|
||||||
|
customerFormStore.currentFormData.customerType === 'CORP'
|
||||||
|
? undefined
|
||||||
|
: currentFormData.value.citizenId,
|
||||||
customerId: state.value.currentCustomerId,
|
customerId: state.value.currentCustomerId,
|
||||||
});
|
});
|
||||||
if (res) return res;
|
if (res) return res;
|
||||||
|
|
@ -418,8 +460,8 @@ export const useCustomerBranchForm = defineStore('form-customer-branch', () => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state,
|
state,
|
||||||
initForm,
|
|
||||||
currentFormData,
|
currentFormData,
|
||||||
|
initForm,
|
||||||
isFormDataDifferent,
|
isFormDataDifferent,
|
||||||
submitForm,
|
submitForm,
|
||||||
};
|
};
|
||||||
|
|
@ -467,6 +509,7 @@ export const useEmployeeForm = defineStore('form-employee', () => {
|
||||||
zipCode: string;
|
zipCode: string;
|
||||||
}
|
}
|
||||||
| undefined;
|
| undefined;
|
||||||
|
ocr: boolean;
|
||||||
}>({
|
}>({
|
||||||
currentIndex: -1,
|
currentIndex: -1,
|
||||||
statusSavePersonal: false,
|
statusSavePersonal: false,
|
||||||
|
|
@ -484,6 +527,7 @@ export const useEmployeeForm = defineStore('form-employee', () => {
|
||||||
editReadonly: false,
|
editReadonly: false,
|
||||||
infoEmployeePersonCard: [],
|
infoEmployeePersonCard: [],
|
||||||
formDataEmployeeOwner: undefined,
|
formDataEmployeeOwner: undefined,
|
||||||
|
ocr: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultFormData: EmployeeCreate = {
|
const defaultFormData: EmployeeCreate = {
|
||||||
|
|
@ -783,10 +827,12 @@ export const useEmployeeForm = defineStore('form-employee', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await employeeStore.fetchById(id);
|
const _data = await employeeStore.fetchById(id);
|
||||||
|
|
||||||
if (res) {
|
if (_data) {
|
||||||
state.value.currentEmployee = res;
|
const _attach = await employeeStore.listAttachment(_data.id);
|
||||||
|
|
||||||
|
state.value.currentEmployee = _data;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
createdAt,
|
createdAt,
|
||||||
|
|
@ -800,47 +846,61 @@ export const useEmployeeForm = defineStore('form-employee', () => {
|
||||||
createdBy,
|
createdBy,
|
||||||
updatedBy,
|
updatedBy,
|
||||||
profileImageUrl,
|
profileImageUrl,
|
||||||
...playlond
|
...payload
|
||||||
} = res;
|
} = _data;
|
||||||
|
|
||||||
resetEmployeeData = {
|
resetEmployeeData = {
|
||||||
...playlond,
|
...payload,
|
||||||
provinceId: province?.id,
|
provinceId: province?.id,
|
||||||
districtId: district?.id,
|
districtId: district?.id,
|
||||||
subDistrictId: subDistrict?.id,
|
subDistrictId: subDistrict?.id,
|
||||||
employeeCheckup: structuredClone(
|
employeeCheckup: structuredClone(
|
||||||
playlond.employeeCheckup?.length === 0
|
payload.employeeCheckup?.length === 0
|
||||||
? defaultFormData.employeeCheckup
|
? defaultFormData.employeeCheckup
|
||||||
: playlond.employeeCheckup?.map((item) => ({
|
: payload.employeeCheckup?.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
statusSave: true,
|
statusSave: true,
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
employeeOtherInfo: structuredClone(
|
employeeOtherInfo: structuredClone(
|
||||||
{
|
{
|
||||||
...playlond.employeeOtherInfo,
|
...payload.employeeOtherInfo,
|
||||||
statusSave: !!playlond.employeeOtherInfo?.id ? true : false,
|
statusSave: !!payload.employeeOtherInfo?.id ? true : false,
|
||||||
} || {},
|
} || {},
|
||||||
),
|
),
|
||||||
employeeWork: structuredClone(
|
employeeWork: structuredClone(
|
||||||
playlond.employeeWork?.length === 0
|
payload.employeeWork?.length === 0
|
||||||
? defaultFormData.employeeWork
|
? defaultFormData.employeeWork
|
||||||
: playlond.employeeWork?.map((item) => ({
|
: payload.employeeWork?.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
statusSave: true,
|
statusSave: true,
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
|
file: _attach
|
||||||
|
? await Promise.all(
|
||||||
|
_attach.map(async (name) => {
|
||||||
|
const fragment = name.split('-');
|
||||||
|
const group = fragment.length === 1 ? 'other' : fragment.at(0);
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: await employeeStore.getAttachment(_data.id, name),
|
||||||
|
name,
|
||||||
|
group,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
: [],
|
||||||
image: null,
|
image: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
currentFromDataEmployee.value = structuredClone(resetEmployeeData);
|
currentFromDataEmployee.value = structuredClone(resetEmployeeData);
|
||||||
const foundBranch = await customerStore.fetchListCustomeBranchById(
|
const foundBranch = await customerStore.fetchListCustomeBranchById(
|
||||||
playlond.customerBranchId,
|
payload.customerBranchId,
|
||||||
);
|
);
|
||||||
|
|
||||||
state.value.currentEmployeeCode = playlond.code;
|
state.value.currentEmployeeCode = payload.code;
|
||||||
|
|
||||||
state.value.profileUrl = profileImageUrl || ' ';
|
state.value.profileUrl = profileImageUrl || '';
|
||||||
|
|
||||||
profileImageUrl
|
profileImageUrl
|
||||||
? (state.value.profileSubmit = true)
|
? (state.value.profileSubmit = true)
|
||||||
|
|
@ -849,8 +909,8 @@ export const useEmployeeForm = defineStore('form-employee', () => {
|
||||||
state.value.formDataEmployeeOwner = { ...foundBranch };
|
state.value.formDataEmployeeOwner = { ...foundBranch };
|
||||||
|
|
||||||
if (
|
if (
|
||||||
foundBranch.address === playlond.address &&
|
foundBranch.address === payload.address &&
|
||||||
foundBranch.zipCode === playlond.zipCode
|
foundBranch.zipCode === payload.zipCode
|
||||||
) {
|
) {
|
||||||
state.value.formDataEmployeeSameAddr = true;
|
state.value.formDataEmployeeSameAddr = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import {
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import useFlowStore from '../flow';
|
import useFlowStore from '../flow';
|
||||||
import { Employee } from '../employee/types';
|
import { Employee } from '../employee/types';
|
||||||
|
import { baseUrl } from '../utils';
|
||||||
|
|
||||||
const useCustomerStore = defineStore('api-customer', () => {
|
const useCustomerStore = defineStore('api-customer', () => {
|
||||||
const flowStore = useFlowStore();
|
const flowStore = useFlowStore();
|
||||||
|
|
@ -208,6 +209,64 @@ const useCustomerStore = defineStore('api-customer', () => {
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function putAttachment(opts: {
|
||||||
|
branchId: string;
|
||||||
|
file: File;
|
||||||
|
filename?: string;
|
||||||
|
}) {
|
||||||
|
const res = await api.put(
|
||||||
|
`/customer-branch/${opts.branchId}/attachment/${opts.filename || opts.file.name}`,
|
||||||
|
opts.file,
|
||||||
|
{
|
||||||
|
headers: { 'X-Rtid': flowStore.rtid, 'Content-Type': opts.file.type },
|
||||||
|
onUploadProgress: (e) => console.log(e),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.status >= 400) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteAttachment(id: string, filename: string) {
|
||||||
|
const res = await api.delete(
|
||||||
|
`/customer-branch/${id}/attachment/${filename}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.status >= 400) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function listAttachment(id: string) {
|
||||||
|
const res = await api.get<string[]>(`/customer-branch/${id}/attachment`, {
|
||||||
|
headers: { 'X-Rtid': flowStore.rtid },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.status >= 400) return false;
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAttachment(id: string, filename: string, download = false) {
|
||||||
|
const url = `${baseUrl}/customer-branch/${id}/attachment/${filename}`;
|
||||||
|
const res = await api.get<string>(url);
|
||||||
|
|
||||||
|
if (download) {
|
||||||
|
fetch(res.data)
|
||||||
|
.then(async (res) => await res.blob())
|
||||||
|
.then((blob) => {
|
||||||
|
let a = document.createElement('a');
|
||||||
|
a.download = filename;
|
||||||
|
a.href = window.URL.createObjectURL(blob);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
|
||||||
async function create(
|
async function create(
|
||||||
data: CustomerCreate,
|
data: CustomerCreate,
|
||||||
flow?: {
|
flow?: {
|
||||||
|
|
@ -395,7 +454,7 @@ const useCustomerStore = defineStore('api-customer', () => {
|
||||||
});
|
});
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
||||||
if (file) await addBranchAttachment(res.data.id, { file });
|
// if (file) await addBranchAttachment(res.data.id, { file });
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
@ -443,7 +502,7 @@ const useCustomerStore = defineStore('api-customer', () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (file) await addBranchAttachment(id, { file });
|
// if (file) await addBranchAttachment(id, { file });
|
||||||
|
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
||||||
|
|
@ -472,68 +531,6 @@ const useCustomerStore = defineStore('api-customer', () => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addBranchAttachment(
|
|
||||||
branchId: string,
|
|
||||||
payload: BranchAttachmentCreate,
|
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const list: { name: string; file: File }[] = [];
|
|
||||||
|
|
||||||
payload.file.forEach((v) => {
|
|
||||||
let filename = v.name;
|
|
||||||
|
|
||||||
if (list.some((v) => v.name === filename)) {
|
|
||||||
const dotIndex = filename.lastIndexOf('.');
|
|
||||||
const originalName =
|
|
||||||
dotIndex !== -1 && !filename.startsWith('.')
|
|
||||||
? filename.slice(0, dotIndex)
|
|
||||||
: filename;
|
|
||||||
const extension =
|
|
||||||
dotIndex !== -1 && !filename.startsWith('.')
|
|
||||||
? filename.slice(dotIndex)
|
|
||||||
: '';
|
|
||||||
|
|
||||||
let i = 0;
|
|
||||||
|
|
||||||
while (list.some((v) => v.name === filename)) {
|
|
||||||
filename = `${originalName} (${++i})`;
|
|
||||||
if (dotIndex !== -1) filename += extension;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list.push({ name: filename, file: v });
|
|
||||||
});
|
|
||||||
|
|
||||||
const res = await api.post<(BranchAttachment & { uploadUrl: string })[]>(
|
|
||||||
`/customer-branch/${branchId}/attachment`,
|
|
||||||
{ file: list.map((v) => v.name) },
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await Promise.all(
|
|
||||||
res.data.map(async (a) => {
|
|
||||||
const found = list.find((b) => b.name === a.name)!;
|
|
||||||
|
|
||||||
await axios
|
|
||||||
.put(a.uploadUrl, found.file, {
|
|
||||||
headers: { 'Content-Type': found.file.type },
|
|
||||||
onUploadProgress: (e) => console.log(e),
|
|
||||||
})
|
|
||||||
.catch((e) => console.error(e));
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchListCustomeBranchById(
|
async function fetchListCustomeBranchById(
|
||||||
branchId: string,
|
branchId: string,
|
||||||
flow?: {
|
flow?: {
|
||||||
|
|
@ -576,6 +573,11 @@ const useCustomerStore = defineStore('api-customer', () => {
|
||||||
fetchListCustomeBranchById,
|
fetchListCustomeBranchById,
|
||||||
|
|
||||||
fetchBranchEmployee,
|
fetchBranchEmployee,
|
||||||
|
|
||||||
|
listAttachment,
|
||||||
|
getAttachment,
|
||||||
|
putAttachment,
|
||||||
|
deleteAttachment,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,12 @@ export type CustomerBranchCreate = {
|
||||||
registerCompanyName: string;
|
registerCompanyName: string;
|
||||||
|
|
||||||
statusSave?: boolean;
|
statusSave?: boolean;
|
||||||
file?: File[];
|
file?: {
|
||||||
|
name?: string;
|
||||||
|
group?: string;
|
||||||
|
url?: string;
|
||||||
|
file?: File;
|
||||||
|
}[];
|
||||||
|
|
||||||
// id?: string;
|
// id?: string;
|
||||||
// code?: string;
|
// code?: string;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import {
|
||||||
import { CustomerBranch } from '../customer/types';
|
import { CustomerBranch } from '../customer/types';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import useFlowStore from '../flow';
|
import useFlowStore from '../flow';
|
||||||
|
import { baseUrl } from '../utils';
|
||||||
|
|
||||||
const useEmployeeStore = defineStore('api-employee', () => {
|
const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
const flowStore = useFlowStore();
|
const flowStore = useFlowStore();
|
||||||
|
|
@ -31,22 +32,15 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchList(
|
async function fetchList(opts?: {
|
||||||
opts?: {
|
page?: number;
|
||||||
page?: number;
|
pageSize?: number;
|
||||||
pageSize?: number;
|
query?: string;
|
||||||
query?: string;
|
gender?: string;
|
||||||
gender?: string;
|
status?: Status;
|
||||||
status?: Status;
|
zipCode?: string;
|
||||||
zipCode?: string;
|
customerId?: string;
|
||||||
customerId?: string;
|
}) {
|
||||||
},
|
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
for (const [k, v] of Object.entries(opts || {})) {
|
for (const [k, v] of Object.entries(opts || {})) {
|
||||||
|
|
@ -58,11 +52,7 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
const res = await api.get<Pagination<Employee[]>>(
|
const res = await api.get<Pagination<Employee[]>>(
|
||||||
`/employee${(params && '?'.concat(query)) || ''}`,
|
`/employee${(params && '?'.concat(query)) || ''}`,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: { 'X-Rtid': flowStore.rtid },
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -73,58 +63,54 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function create(
|
async function create(data: EmployeeCreate) {
|
||||||
data: EmployeeCreate,
|
const { id, code, image, file, ...payload } = data;
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const { id, code, image, ...payload } = data;
|
|
||||||
const res = await api.post<
|
const res = await api.post<
|
||||||
Employee & { profileImageUrl: string; profileImageUploadUrl: string }
|
Employee & { profileImageUrl: string; profileImageUploadUrl: string }
|
||||||
>('/employee', payload, {
|
>('/employee', payload, {
|
||||||
headers: {
|
headers: { 'X-Rtid': flowStore.rtid },
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
image &&
|
|
||||||
(await axios
|
|
||||||
.put(res.data.profileImageUploadUrl, image, {
|
|
||||||
headers: { 'Content-Type': image?.type },
|
|
||||||
onUploadProgress: (e) => console.log(e),
|
|
||||||
})
|
|
||||||
.catch((e) => console.error(e)));
|
|
||||||
|
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
||||||
|
if (res.data.id) {
|
||||||
|
if (image) {
|
||||||
|
await api
|
||||||
|
.put(`/employee/${res.data.id}/image`, image, {
|
||||||
|
headers: { 'Content-Type': image?.type },
|
||||||
|
onUploadProgress: (e) => console.log(e),
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
|
}
|
||||||
|
if (file) {
|
||||||
|
const attachmentUpload = file.map(async ({ group, file }) => {
|
||||||
|
if (file) {
|
||||||
|
const _name = file.name;
|
||||||
|
const _ext = _name.split('.').at(-1);
|
||||||
|
|
||||||
|
let filename = (group || 'other') + '-' + Date.now();
|
||||||
|
|
||||||
|
if (_ext) filename = filename + '.' + _ext;
|
||||||
|
|
||||||
|
await uploadAttachment(res.data.id, file, filename);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await Promise.all(attachmentUpload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createEmployeeCheckup(
|
async function createEmployeeCheckup(
|
||||||
employeeId: string,
|
employeeId: string,
|
||||||
data: EmployeeCheckupCreate,
|
data: EmployeeCheckupCreate,
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
const { id, statusSave, ...payload } = data;
|
const { id, statusSave, ...payload } = data;
|
||||||
const res = await api.post<EmployeeCheckupCreate>(
|
const res = await api.post<EmployeeCheckupCreate>(
|
||||||
`/employee/${employeeId}/checkup`,
|
`/employee/${employeeId}/checkup`,
|
||||||
{ ...payload },
|
{ ...payload },
|
||||||
{
|
{ headers: { 'X-Rtid': flowStore.rtid } },
|
||||||
headers: {
|
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
@ -135,23 +121,12 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
async function createEmployeeWork(
|
async function createEmployeeWork(
|
||||||
employeeId: string,
|
employeeId: string,
|
||||||
data: EmployeeWorkCreate,
|
data: EmployeeWorkCreate,
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
const { id, ...payload } = data;
|
const { id, ...payload } = data;
|
||||||
const res = await api.post<EmployeeWorkCreate>(
|
const res = await api.post<EmployeeWorkCreate>(
|
||||||
`/employee/${employeeId}/work`,
|
`/employee/${employeeId}/work`,
|
||||||
{ ...payload },
|
{ ...payload },
|
||||||
{
|
{ headers: { 'X-Rtid': flowStore.rtid } },
|
||||||
headers: {
|
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
@ -162,22 +137,13 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
async function createEmployeeOtherInfo(
|
async function createEmployeeOtherInfo(
|
||||||
employeeId: string,
|
employeeId: string,
|
||||||
data: EmployeeOtherCreate,
|
data: EmployeeOtherCreate,
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
const { id, statusSave, ...payload } = data;
|
const { id, statusSave, ...payload } = data;
|
||||||
const res = await api.post<EmployeeOtherCreate>(
|
const res = await api.post<EmployeeOtherCreate>(
|
||||||
`/employee/${employeeId}/other-info`,
|
`/employee/${employeeId}/other-info`,
|
||||||
{ ...payload },
|
{ ...payload },
|
||||||
{
|
{
|
||||||
headers: {
|
headers: { 'X-Rtid': flowStore.rtid },
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -189,11 +155,6 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
async function editByIdEmployeeCheckup(
|
async function editByIdEmployeeCheckup(
|
||||||
employeeOfId: string,
|
employeeOfId: string,
|
||||||
data: Partial<EmployeeCheckupCreate>,
|
data: Partial<EmployeeCheckupCreate>,
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
|
|
@ -208,13 +169,7 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
const res = await api.put<EmployeeCheckupCreate>(
|
const res = await api.put<EmployeeCheckupCreate>(
|
||||||
`/employee/${employeeOfId}/checkup/${id}`,
|
`/employee/${employeeOfId}/checkup/${id}`,
|
||||||
{ ...payload },
|
{ ...payload },
|
||||||
{
|
{ headers: { 'X-Rtid': flowStore.rtid } },
|
||||||
headers: {
|
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
@ -225,11 +180,6 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
async function editByIdEmployeeWork(
|
async function editByIdEmployeeWork(
|
||||||
employeeOfId: string,
|
employeeOfId: string,
|
||||||
data: Partial<EmployeeWorkCreate>,
|
data: Partial<EmployeeWorkCreate>,
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
|
|
@ -244,13 +194,7 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
const res = await api.put<EmployeeWorkCreate>(
|
const res = await api.put<EmployeeWorkCreate>(
|
||||||
`/employee/${employeeOfId}/work/${id}`,
|
`/employee/${employeeOfId}/work/${id}`,
|
||||||
{ ...payload },
|
{ ...payload },
|
||||||
{
|
{ headers: { 'X-Rtid': flowStore.rtid } },
|
||||||
headers: {
|
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
@ -261,11 +205,6 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
async function editByIdEmployeeOtherInfo(
|
async function editByIdEmployeeOtherInfo(
|
||||||
employeeOfId: string,
|
employeeOfId: string,
|
||||||
data: Partial<EmployeeOtherCreate>,
|
data: Partial<EmployeeOtherCreate>,
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
|
|
@ -280,13 +219,7 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
const res = await api.put<EmployeeOtherCreate>(
|
const res = await api.put<EmployeeOtherCreate>(
|
||||||
`/employee/${employeeOfId}/other-info/${id}`,
|
`/employee/${employeeOfId}/other-info/${id}`,
|
||||||
{ ...payload },
|
{ ...payload },
|
||||||
{
|
{ headers: { 'X-Rtid': flowStore.rtid } },
|
||||||
headers: {
|
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
@ -294,59 +227,50 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function editById(
|
async function editById(employeeId: string, data: Partial<EmployeeCreate>) {
|
||||||
employeeId: string,
|
const { id, code, image, file, ...payload } = data;
|
||||||
data: Partial<EmployeeCreate>,
|
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const { id, code, image, ...payload } = data;
|
|
||||||
const res = await api.put<
|
const res = await api.put<
|
||||||
Employee & { imageUrl: string; profileImageUploadUrl: string }
|
Employee & { imageUrl: string; profileImageUploadUrl: string }
|
||||||
>(`/employee/${employeeId}`, payload, {
|
>(`/employee/${employeeId}`, payload, {
|
||||||
headers: {
|
headers: { 'X-Rtid': flowStore.rtid },
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
image &&
|
if (!res) return false;
|
||||||
(await axios
|
|
||||||
.put(res.data.profileImageUploadUrl, image, {
|
if (image) {
|
||||||
headers: { 'Content-Type': image.type },
|
await api
|
||||||
|
.put(`/employee/${employeeId}/image`, image, {
|
||||||
|
headers: { 'Content-Type': image?.type },
|
||||||
onUploadProgress: (e) => console.log(e),
|
onUploadProgress: (e) => console.log(e),
|
||||||
})
|
})
|
||||||
.catch((e) => console.error(e)));
|
.catch((e) => console.error(e));
|
||||||
|
}
|
||||||
|
if (file) {
|
||||||
|
const attachmentUpload = file.map(async ({ group, file }) => {
|
||||||
|
if (file) {
|
||||||
|
const _name = file.name;
|
||||||
|
const _ext = _name.split('.').at(-1);
|
||||||
|
|
||||||
if (!res) return false;
|
let filename = (group || 'other') + '-' + Date.now();
|
||||||
|
|
||||||
|
if (_ext) filename = filename + '.' + _ext;
|
||||||
|
|
||||||
|
await uploadAttachment(employeeId, file, filename);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await Promise.all(attachmentUpload);
|
||||||
|
}
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteByIdCheckUp(
|
async function deleteByIdCheckUp(opts: {
|
||||||
opts: {
|
employeeId: string;
|
||||||
employeeId: string;
|
checkUpId?: string;
|
||||||
checkUpId?: string;
|
}) {
|
||||||
},
|
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const res = await api.delete<Employee>(
|
const res = await api.delete<Employee>(
|
||||||
`/employee/${opts.employeeId}/checkup/${opts.checkUpId}`,
|
`/employee/${opts.employeeId}/checkup/${opts.checkUpId}`,
|
||||||
{
|
{ headers: { 'X-Rtid': flowStore.rtid } },
|
||||||
headers: {
|
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
@ -355,25 +279,11 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteByIdWork(
|
async function deleteByIdWork(opts: { employeeId: string; workId?: string }) {
|
||||||
opts: {
|
|
||||||
employeeId: string;
|
|
||||||
workId?: string;
|
|
||||||
},
|
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const res = await api.delete<Employee>(
|
const res = await api.delete<Employee>(
|
||||||
`/employee/${opts.employeeId}/work/${opts.workId}`,
|
`/employee/${opts.employeeId}/work/${opts.workId}`,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: { 'X-Rtid': flowStore.rtid },
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -383,20 +293,9 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteById(
|
async function deleteById(id: string) {
|
||||||
id: string,
|
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const res = await api.delete<Employee>(`/employee/${id}`, {
|
const res = await api.delete<Employee>(`/employee/${id}`, {
|
||||||
headers: {
|
headers: { 'X-Rtid': flowStore.rtid },
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
@ -405,82 +304,38 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchCheckup(
|
async function fetchCheckup(id: string) {
|
||||||
id: string,
|
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const res = await api.get<EmployeeCheckup[]>(`/employee/${id}/checkup`, {
|
const res = await api.get<EmployeeCheckup[]>(`/employee/${id}/checkup`, {
|
||||||
headers: {
|
headers: { 'X-Rtid': flowStore.rtid },
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
if (res && res.status === 200) {
|
if (res && res.status === 200) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchWork(
|
async function fetchWork(id: string) {
|
||||||
id: string,
|
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const res = await api.get<EmployeeWork[]>(`/employee/${id}/work`, {
|
const res = await api.get<EmployeeWork[]>(`/employee/${id}/work`, {
|
||||||
headers: {
|
headers: { 'X-Rtid': flowStore.rtid },
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
if (res && res.status === 200) {
|
if (res && res.status === 200) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchOther(
|
async function fetchOther(id: string) {
|
||||||
id: string,
|
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const res = await api.get<EmployeeOther>(`/employee/${id}/other-info`, {
|
const res = await api.get<EmployeeOther>(`/employee/${id}/other-info`, {
|
||||||
headers: {
|
headers: { 'X-Rtid': flowStore.rtid },
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
if (res && res.status === 200) {
|
if (res && res.status === 200) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getStatsEmployee(
|
async function getStatsEmployee(customerBranchId?: string) {
|
||||||
customerBranchId?: string,
|
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const res = await api.get(
|
const res = await api.get(
|
||||||
`/employee/stats${customerBranchId ? '?customerBranchId=' + customerBranchId : ''}/`,
|
`/employee/stats${customerBranchId ? '?customerBranchId=' + customerBranchId : ''}/`,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: { 'X-Rtid': flowStore.rtid },
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if (res && res.status === 200) {
|
if (res && res.status === 200) {
|
||||||
|
|
@ -488,19 +343,11 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getStatsEmployeeGender(
|
async function getStatsEmployeeGender(opts?: {
|
||||||
opts?: {
|
customerBranchId?: string;
|
||||||
customerBranchId?: string;
|
status?: 'CREATED' | 'ACTIVE' | 'INACTIVE';
|
||||||
status?: 'CREATED' | 'ACTIVE' | 'INACTIVE';
|
query?: string;
|
||||||
query?: string;
|
}) {
|
||||||
},
|
|
||||||
|
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
for (const [k, v] of Object.entries(opts || {})) {
|
for (const [k, v] of Object.entries(opts || {})) {
|
||||||
|
|
@ -512,11 +359,7 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
const res = await api.get(
|
const res = await api.get(
|
||||||
`/employee/stats/gender${(params && '?'.concat(query)) || ''}`,
|
`/employee/stats/gender${(params && '?'.concat(query)) || ''}`,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: { 'X-Rtid': flowStore.rtid },
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if (res && res.status === 200) {
|
if (res && res.status === 200) {
|
||||||
|
|
@ -524,26 +367,66 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getEditHistory(
|
async function getEditHistory(employeeId: string) {
|
||||||
employeeId: string,
|
|
||||||
flow?: {
|
|
||||||
sessionId?: string;
|
|
||||||
refTransactionId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const res = await api.get(`/employee/${employeeId}/edit-history`, {
|
const res = await api.get(`/employee/${employeeId}/edit-history`, {
|
||||||
headers: {
|
headers: { 'X-Rtid': flowStore.rtid },
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
if (res && res.status === 200) {
|
if (res && res.status === 200) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function listAttachment(employeeId: string) {
|
||||||
|
const res = await api.get<string[]>(`/employee/${employeeId}/attachment`);
|
||||||
|
return !res || res.status >= 400 ? false : res.data;
|
||||||
|
}
|
||||||
|
async function getAttachment(
|
||||||
|
employeeId: string,
|
||||||
|
filename: string,
|
||||||
|
download = false,
|
||||||
|
) {
|
||||||
|
const url = `${baseUrl}/employee/${employeeId}/attachment/${filename}`;
|
||||||
|
const res = await api.get<string>(url);
|
||||||
|
|
||||||
|
if (download) {
|
||||||
|
fetch(res.data)
|
||||||
|
.then(async (res) => await res.blob())
|
||||||
|
.then((blob) => {
|
||||||
|
let a = document.createElement('a');
|
||||||
|
a.download = filename;
|
||||||
|
a.href = window.URL.createObjectURL(blob);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
async function uploadAttachment(
|
||||||
|
employeeId: string,
|
||||||
|
file: File,
|
||||||
|
filename?: string,
|
||||||
|
) {
|
||||||
|
const res = await api.put(
|
||||||
|
`/employee/${employeeId}/attachment/${filename || file.name}`,
|
||||||
|
file,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'X-Rtid': flowStore.rtid,
|
||||||
|
'Content-Type': file.type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return !(!res || res.status >= 400);
|
||||||
|
}
|
||||||
|
async function deleteAttachment(employeeId: string, filename: string) {
|
||||||
|
const res = await api.delete(
|
||||||
|
`/employee/${employeeId}/attachment/${filename}`,
|
||||||
|
{ headers: { 'X-Rtid': flowStore.rtid } },
|
||||||
|
);
|
||||||
|
return !(!res || res.status >= 400);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data,
|
data,
|
||||||
globalOption,
|
globalOption,
|
||||||
|
|
@ -571,6 +454,11 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
||||||
|
|
||||||
createEmployeeOtherInfo,
|
createEmployeeOtherInfo,
|
||||||
editByIdEmployeeOtherInfo,
|
editByIdEmployeeOtherInfo,
|
||||||
|
|
||||||
|
listAttachment,
|
||||||
|
getAttachment,
|
||||||
|
uploadAttachment,
|
||||||
|
deleteAttachment,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ export type Employee = {
|
||||||
createdByUserId: string;
|
createdByUserId: string;
|
||||||
updatedByUserId: string;
|
updatedByUserId: string;
|
||||||
statusOrder: string;
|
statusOrder: string;
|
||||||
|
namePrefix: string;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
firstNameEN: string;
|
firstNameEN: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
|
@ -107,6 +108,13 @@ export type EmployeeCreate = {
|
||||||
employeeCheckup?: EmployeeCheckupCreate[];
|
employeeCheckup?: EmployeeCheckupCreate[];
|
||||||
|
|
||||||
employeeOtherInfo?: EmployeeOtherCreate;
|
employeeOtherInfo?: EmployeeOtherCreate;
|
||||||
|
|
||||||
|
file?: {
|
||||||
|
name?: string;
|
||||||
|
group?: string;
|
||||||
|
url?: string;
|
||||||
|
file?: File;
|
||||||
|
}[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type EmployeeUpdate = {
|
export type EmployeeUpdate = {
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,19 @@ const useOcr = defineStore('useOcrStore', () => {
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
const res = await axios
|
const res = await axios
|
||||||
.post(`${baseUrl}/`, payload.file, {
|
.post<{
|
||||||
|
document: string;
|
||||||
|
fields: { name: string; value: string }[];
|
||||||
|
result: string;
|
||||||
|
}>(`${baseUrl}/`, payload.file, {
|
||||||
headers: { 'Content-Type': payload.file?.type },
|
headers: { 'Content-Type': payload.file?.type },
|
||||||
onUploadProgress: (e) => console.log(e),
|
onUploadProgress: (e) => console.log(e),
|
||||||
})
|
})
|
||||||
.catch((e) => console.error(e));
|
.catch((e) => console.error(e));
|
||||||
// ]);
|
|
||||||
|
if (!res || res.status >= 400) return false;
|
||||||
|
|
||||||
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue