Squashed commit of the following:
commit eb6c7b164a9f182f8d1ce73cc5354866c6d6b10e
Author: puriphatt <puriphat@frappet.com>
Date: Wed Sep 11 11:29:44 2024 +0700
refactor: no img close to default on create
commit eae9eb26071cc2985624bb1c6ce551bf5eb6eb8b
Author: puriphatt <puriphat@frappet.com>
Date: Wed Sep 11 11:04:04 2024 +0700
refactor/feat: save => apply, disabled selected img, no img close to default
commit ccbf80fc53db3144873c049bd6dbd37b4e2e9ff3
Author: puriphatt <puriphat@frappet.com>
Date: Wed Sep 11 09:31:32 2024 +0700
fix(01): use submit function
commit 36b4f6ca15e5966f37dfefc9fdb744feec60dd27
Author: puriphatt <puriphat@frappet.com>
Date: Tue Sep 10 17:45:19 2024 +0700
fix: imgList error
commit bac0eaf3ab955672ae0c78d3295b4a839827c5f2
Author: puriphatt <puriphat@frappet.com>
Date: Tue Sep 10 17:18:03 2024 +0700
refactor(03): customer new upload img dialog
commit 9d7398e9613a738c33e265482cdb7d7bb250ea9f
Author: puriphatt <puriphat@frappet.com>
Date: Tue Sep 10 15:40:39 2024 +0700
refactor(02): new upload dialog
commit 8b91d43f41eae3ba2442f6c742d617c25ee180cb
Author: puriphatt <puriphat@frappet.com>
Date: Tue Sep 10 15:25:21 2024 +0700
refactor(01): new upload dialog, confirm remove, individual action
commit 61caf1919168bc5635568d7ca246574fdc43cd04
Author: puriphatt <puriphat@frappet.com>
Date: Mon Sep 9 17:08:42 2024 +0700
refactor(01): branch new img upload
commit e791b7316d001d839c8afb1950f7331c62d9e81a
Author: puriphatt <puriphat@frappet.com>
Date: Mon Sep 9 17:08:42 2024 +0700
refactor(02): personnel new img upload
commit af4d11312b9cb666338901efa9971117cb7738c4
Author: puriphatt <puriphat@frappet.com>
Date: Mon Sep 9 17:08:42 2024 +0700
feat(02): new image upload
commit e4d7afdb8c74d65a550644f2c60f70909d51d4a8
Author: puriphatt <puriphat@frappet.com>
Date: Mon Sep 9 17:08:41 2024 +0700
refactor: mock select image function
commit 5ab3f045b9c7d2c821920c12114da15eed09655a
Author: puriphatt <puriphat@frappet.com>
Date: Mon Sep 9 17:08:41 2024 +0700
refactor: mock new image preview
This commit is contained in:
parent
ab0b3bb4f3
commit
62fc7055dd
13 changed files with 925 additions and 254 deletions
|
|
@ -1,17 +1,23 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
import AppBox from './app/AppBox.vue';
|
import AppBox from './app/AppBox.vue';
|
||||||
import { CancelButton, ClearButton, SaveButton } from './button';
|
import { CancelButton, ClearButton, SaveButton } from './button';
|
||||||
|
import { dialog } from 'src/stores/utils';
|
||||||
|
|
||||||
defineExpose({ browse });
|
defineExpose({ browse });
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
changeDisabled?: boolean;
|
changeDisabled?: boolean;
|
||||||
clearButtonDisabled?: boolean;
|
clearButtonDisabled?: boolean;
|
||||||
clearButton?: boolean;
|
clearButton?: boolean;
|
||||||
hiddenFooter?: boolean;
|
hiddenFooter?: boolean;
|
||||||
defaultUrl?: string;
|
defaultUrl?: string;
|
||||||
|
onCreate?: boolean;
|
||||||
}>();
|
}>();
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'save', file: File | null, url: string | null): void;
|
(e: 'save', file: File | null, url: string | null): void;
|
||||||
|
(e: 'addImage', file: File | null): void;
|
||||||
|
(e: 'removeImage', name: string): void;
|
||||||
|
(e: 'submit', name: string): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const imageUrl = defineModel<string>('imageUrl', {
|
const imageUrl = defineModel<string>('imageUrl', {
|
||||||
|
|
@ -29,7 +35,22 @@ const dialogState = defineModel<boolean>('dialogState', {
|
||||||
const file = defineModel<File | null>('file', {
|
const file = defineModel<File | null>('file', {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
const dataList = defineModel<{ selectedImage: string; list: string[] }>(
|
||||||
|
'dataList',
|
||||||
|
{
|
||||||
|
required: false,
|
||||||
|
default: { selectedImage: '', list: [] },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const onCreateData = defineModel<{
|
||||||
|
selectedImage: string;
|
||||||
|
list: { url: string; imgFile: File | null; name: string }[];
|
||||||
|
}>('onCreateDataList', {
|
||||||
|
required: false,
|
||||||
|
default: { selectedImage: '', list: [] },
|
||||||
|
});
|
||||||
|
|
||||||
|
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
const inputFile = (() => {
|
const inputFile = (() => {
|
||||||
const _element = document.createElement('input');
|
const _element = document.createElement('input');
|
||||||
|
|
@ -39,8 +60,25 @@ const inputFile = (() => {
|
||||||
return _element;
|
return _element;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
const selectedImg = ref('');
|
||||||
|
const tempImage = ref<string | null>('');
|
||||||
|
|
||||||
reader.addEventListener('load', () => {
|
reader.addEventListener('load', () => {
|
||||||
if (typeof reader.result === 'string') imageUrl.value = reader.result;
|
if (typeof reader.result === 'string') {
|
||||||
|
tempImage.value = reader.result;
|
||||||
|
if (props.onCreate) {
|
||||||
|
onCreateData.value.list.push({
|
||||||
|
url: reader.result,
|
||||||
|
imgFile: file.value,
|
||||||
|
name: Date.now().toString(),
|
||||||
|
});
|
||||||
|
onCreateData.value.selectedImage =
|
||||||
|
onCreateData.value.list[onCreateData.value.list.length - 1].name;
|
||||||
|
selectedImg.value = reader.result;
|
||||||
|
} else {
|
||||||
|
emit('addImage', file.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function browse() {
|
function browse() {
|
||||||
|
|
@ -55,12 +93,13 @@ function change(e: Event) {
|
||||||
file.value = _file;
|
file.value = _file;
|
||||||
reader.readAsDataURL(_file);
|
reader.readAsDataURL(_file);
|
||||||
if (!dialogState.value) {
|
if (!dialogState.value) {
|
||||||
emit('save', _file, imageUrl.value);
|
emit('save', _file, tempImage.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadImage(url: string) {
|
async function downloadImage(url: string | null) {
|
||||||
|
if (!url) return;
|
||||||
const res = await fetch(url);
|
const res = await fetch(url);
|
||||||
const blob = await res.blob();
|
const blob = await res.blob();
|
||||||
|
|
||||||
|
|
@ -76,57 +115,235 @@ async function downloadImage(url: string) {
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectImg(name: string) {
|
||||||
|
if (props.onCreate) {
|
||||||
|
selectedImg.value = name;
|
||||||
|
tempImage.value = name;
|
||||||
|
onCreateData.value.selectedImage =
|
||||||
|
onCreateData.value.list.find((v) => v.url === name)?.name || '';
|
||||||
|
} else {
|
||||||
|
selectedImg.value = name.split('/').pop() || '';
|
||||||
|
tempImage.value = `${apiBaseUrl}/${name}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeCheckToDefault() {
|
||||||
|
let imgNameList: string[];
|
||||||
|
let currentSelected: string;
|
||||||
|
let inList: boolean;
|
||||||
|
|
||||||
|
if (props.onCreate) {
|
||||||
|
imgNameList = onCreateData.value.list.map((v) => v.url || '');
|
||||||
|
currentSelected = imageUrl.value;
|
||||||
|
} else {
|
||||||
|
imgNameList = dataList.value.list.map((v) => v.split('/').pop() || '');
|
||||||
|
currentSelected = dataList.value.selectedImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
inList = imgNameList.includes(currentSelected);
|
||||||
|
|
||||||
|
if (!inList && currentSelected !== '') {
|
||||||
|
selectImg('');
|
||||||
|
emit('submit', selectedImg.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => dialogState.value,
|
||||||
|
() => {
|
||||||
|
if (dialogState.value) {
|
||||||
|
if (props.onCreate) {
|
||||||
|
tempImage.value = imageUrl.value;
|
||||||
|
selectedImg.value = imageUrl.value;
|
||||||
|
} else {
|
||||||
|
tempImage.value = `${imageUrl.value}?ts=${Date.now()}`;
|
||||||
|
selectedImg.value = dataList.value.selectedImage;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tempImage.value = '';
|
||||||
|
selectedImg.value = '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => dataList.value.list,
|
||||||
|
(n, o) => {
|
||||||
|
if (n.length > o.length) {
|
||||||
|
selectImg(n[n.length - 1]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true },
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<q-dialog v-model="dialogState">
|
<q-dialog v-model="dialogState" @before-hide="closeCheckToDefault">
|
||||||
<AppBox class="image-dialog-content">
|
<AppBox class="image-dialog-content column">
|
||||||
|
<!-- header -->
|
||||||
<div class="row items-center q-py-sm q-px-md bordered-b">
|
<div class="row items-center q-py-sm q-px-md bordered-b">
|
||||||
|
<div style="width: 38.61px" />
|
||||||
<div style="flex: 1"><slot name="title" /></div>
|
<div style="flex: 1"><slot name="title" /></div>
|
||||||
<div>
|
<div>
|
||||||
<q-btn
|
<CancelButton v-close-popup icon-only @click="closeCheckToDefault" />
|
||||||
round
|
</div>
|
||||||
flat
|
</div>
|
||||||
icon="mdi-close"
|
|
||||||
padding="xs"
|
<!-- body -->
|
||||||
class="close-btn"
|
<div class="q-px-lg surface-2 col row full-width">
|
||||||
:class="{ dark: $q.dark.isActive }"
|
<div
|
||||||
v-close-popup
|
class="image-dialog-body q-my-lg relative-position rounded surface-1 flex items-center"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:src="tempImage || fallbackUrl"
|
||||||
|
v-if="tempImage || fallbackUrl"
|
||||||
|
style="object-fit: contain; width: 100%"
|
||||||
|
@error="
|
||||||
|
() => {
|
||||||
|
tempImage = '';
|
||||||
|
}
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
style="object-fit: contain; height: 100%; width: 100%"
|
||||||
|
v-if="!tempImage && !fallbackUrl"
|
||||||
|
>
|
||||||
|
<slot name="error"></slot>
|
||||||
|
</div>
|
||||||
|
<div class="absolute-top-left q-pa-md">
|
||||||
|
<q-btn
|
||||||
|
class="upload-image-btn q-mr-md"
|
||||||
|
icon="mdi-camera-plus-outline"
|
||||||
|
id="btn-add-img"
|
||||||
|
size="md"
|
||||||
|
unelevated
|
||||||
|
round
|
||||||
|
v-if="!changeDisabled"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
inputFile?.click();
|
||||||
|
}
|
||||||
|
"
|
||||||
|
style="color: hsla(var(--stone-0-hsl) / 0.7)"
|
||||||
|
></q-btn>
|
||||||
|
<q-btn
|
||||||
|
v-if="!onCreate"
|
||||||
|
class="upload-image-btn"
|
||||||
|
icon="mdi-download-outline"
|
||||||
|
id="btn-download-img"
|
||||||
|
size="md"
|
||||||
|
unelevated
|
||||||
|
round
|
||||||
|
@click="downloadImage(tempImage)"
|
||||||
|
style="color: hsla(var(--stone-0-hsl) / 0.7)"
|
||||||
|
></q-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="!hiddenFooter"
|
||||||
|
class="col q-ml-md q-pt-sm q-my-md"
|
||||||
|
style="width: 40em; height: 30em; overflow: auto"
|
||||||
|
>
|
||||||
|
<div class="row items-center q-gutter-sm">
|
||||||
|
<div
|
||||||
|
class="rounded surface-1 relative-position"
|
||||||
|
:class="{
|
||||||
|
'selected-img': selectedImg === '',
|
||||||
|
}"
|
||||||
|
style="
|
||||||
|
object-fit: cover;
|
||||||
|
height: 5vw;
|
||||||
|
width: 5vw;
|
||||||
|
overflow: hidden;
|
||||||
|
"
|
||||||
|
@click="selectImg('')"
|
||||||
|
>
|
||||||
|
<slot name="error"></slot>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-if="dataList">
|
||||||
|
<div
|
||||||
|
v-for="(img, n) in onCreate
|
||||||
|
? onCreateData.list.map((item) => item.url)
|
||||||
|
: dataList.list"
|
||||||
|
:key="n"
|
||||||
|
class="rounded surface-1 relative-position"
|
||||||
|
:class="{
|
||||||
|
'selected-img':
|
||||||
|
selectedImg && onCreate
|
||||||
|
? selectedImg === img
|
||||||
|
: selectedImg === img.split('/').pop(),
|
||||||
|
}"
|
||||||
|
style="height: 5vw; width: 5vw"
|
||||||
|
@click="selectImg(img)"
|
||||||
|
>
|
||||||
|
<q-btn
|
||||||
|
icon="mdi-close"
|
||||||
|
class="absolute-top-right"
|
||||||
|
rounded
|
||||||
|
padding="0"
|
||||||
|
size="sm"
|
||||||
|
style="
|
||||||
|
z-index: 2;
|
||||||
|
top: -5px;
|
||||||
|
right: -5px;
|
||||||
|
background: var(--surface-1);
|
||||||
|
color: hsl(var(--negative-bg));
|
||||||
|
"
|
||||||
|
@click.stop="
|
||||||
|
() => {
|
||||||
|
if (onCreate) {
|
||||||
|
const v = onCreateData.list.splice(n, 1);
|
||||||
|
if (v[0].url === selectedImg) {
|
||||||
|
if (onCreateData.list.length === 0 || n === 0) {
|
||||||
|
selectImg('');
|
||||||
|
} else {
|
||||||
|
selectImg(onCreateData.list[n - 1].url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dialog({
|
||||||
|
color: 'negative',
|
||||||
|
icon: 'mdi-alert',
|
||||||
|
title: $t('dialog.title.confirmDelete'),
|
||||||
|
actionText: $t('general.delete'),
|
||||||
|
message: $t('dialog.message.confirmDelete'),
|
||||||
|
action: async () => {
|
||||||
|
$emit('removeImage', img);
|
||||||
|
const index = dataList.list.indexOf(img);
|
||||||
|
if (img.split('/').pop() === selectedImg) {
|
||||||
|
if (dataList.list.length === 0 || index === 0) {
|
||||||
|
selectImg('');
|
||||||
|
} else {
|
||||||
|
selectImg(dataList.list[index - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancel: () => {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
></q-btn>
|
||||||
|
<div
|
||||||
|
class="rounded full-width full-height surface-1"
|
||||||
|
style="overflow: hidden"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-if="img"
|
||||||
|
:src="onCreate ? img : `${apiBaseUrl}/${img}`"
|
||||||
|
class=""
|
||||||
|
style="object-fit: cover; height: 100%; width: 100%"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="image-dialog-body">
|
|
||||||
<img
|
<!-- footer -->
|
||||||
:src="imageUrl || fallbackUrl"
|
|
||||||
v-if="imageUrl || fallbackUrl"
|
|
||||||
class="image-container"
|
|
||||||
style="object-fit: contain"
|
|
||||||
@error="imageUrl = ''"
|
|
||||||
/>
|
|
||||||
<div class="image-container" v-if="!imageUrl && !fallbackUrl">
|
|
||||||
<slot name="error"></slot>
|
|
||||||
</div>
|
|
||||||
<div style="position: fixed; padding: var(--size-2)">
|
|
||||||
<q-btn
|
|
||||||
class="upload-image-btn q-mr-md"
|
|
||||||
icon="mdi-camera-outline"
|
|
||||||
size="md"
|
|
||||||
unelevated
|
|
||||||
round
|
|
||||||
v-if="!changeDisabled"
|
|
||||||
@click="inputFile?.click()"
|
|
||||||
style="color: hsla(var(--stone-0-hsl) / 0.7)"
|
|
||||||
></q-btn>
|
|
||||||
<q-btn
|
|
||||||
class="upload-image-btn"
|
|
||||||
icon="mdi-download-outline"
|
|
||||||
size="md"
|
|
||||||
unelevated
|
|
||||||
round
|
|
||||||
@click="downloadImage(imageUrl)"
|
|
||||||
style="color: hsla(var(--stone-0-hsl) / 0.7)"
|
|
||||||
></q-btn>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
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"
|
||||||
|
|
@ -147,20 +364,25 @@ async function downloadImage(url: string) {
|
||||||
"
|
"
|
||||||
v-if="clearButton"
|
v-if="clearButton"
|
||||||
/>
|
/>
|
||||||
<CancelButton
|
<!-- <CancelButton
|
||||||
|
id="btn-cancel-img"
|
||||||
outlined
|
outlined
|
||||||
class="q-px-md q-mr-sm"
|
class="q-px-md q-mr-sm"
|
||||||
@click="
|
@click="
|
||||||
inputFile && (inputFile.value = ''),
|
inputFile && (inputFile.value = ''),
|
||||||
(imageUrl = defaultUrl || fallbackUrl || ''),
|
(tempImage = defaultUrl || fallbackUrl || ''),
|
||||||
(file = null)
|
(file = null)
|
||||||
"
|
"
|
||||||
v-close-popup
|
v-close-popup
|
||||||
/>
|
/> -->
|
||||||
<SaveButton
|
<SaveButton
|
||||||
|
id="btn-save-img"
|
||||||
outlined
|
outlined
|
||||||
@click="$emit('save', inputFile?.files?.[0] || null, imageUrl)"
|
:disabled="dataList.selectedImage === selectedImg"
|
||||||
|
:label="$t('general.apply')"
|
||||||
|
@click="$emit('submit', selectedImg)"
|
||||||
/>
|
/>
|
||||||
|
<!-- @click="$emit('save', inputFile?.files?.[0] || null, tempImage)" -->
|
||||||
</div>
|
</div>
|
||||||
</AppBox>
|
</AppBox>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
@ -171,24 +393,24 @@ async function downloadImage(url: string) {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: var(--radius-2);
|
border-radius: var(--radius-2);
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
width: 100%;
|
|
||||||
max-width: 80%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.image-dialog-content {
|
.image-dialog-content {
|
||||||
max-width: 60%;
|
max-width: 70%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-dialog-body {
|
.image-dialog-body {
|
||||||
overflow-y: auto;
|
/* overflow-y: auto;
|
||||||
background-color: var(--surface-2) !important;
|
background-color: var(--surface-1) !important;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1;
|
flex: 1; */
|
||||||
height: calc(100vh - 200px);
|
overflow: hidden;
|
||||||
|
width: 30em;
|
||||||
|
height: 30em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-image-btn {
|
.upload-image-btn {
|
||||||
|
|
@ -227,4 +449,21 @@ async function downloadImage(url: string) {
|
||||||
border: 1px solid hsl(var(--negative-bg));
|
border: 1px solid hsl(var(--negative-bg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.selected-img {
|
||||||
|
position: relative;
|
||||||
|
border: 2px solid hsl(var(--info-bg));
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-img:before {
|
||||||
|
content: ' ';
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
border: 2px solid var(--surface-1);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@ export default {
|
||||||
success: 'Success',
|
success: 'Success',
|
||||||
taxNo: 'Legal Person',
|
taxNo: 'Legal Person',
|
||||||
contactName: 'Contact Name',
|
contactName: 'Contact Name',
|
||||||
|
image: 'Image of ',
|
||||||
|
apply: 'Apply',
|
||||||
},
|
},
|
||||||
|
|
||||||
menu: {
|
menu: {
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@ export default {
|
||||||
success: 'สำเร็จ',
|
success: 'สำเร็จ',
|
||||||
taxNo: 'ทะเบียนนิติบุคคล',
|
taxNo: 'ทะเบียนนิติบุคคล',
|
||||||
contactName: 'ติดต่อ',
|
contactName: 'ติดต่อ',
|
||||||
|
image: 'รูปภาพ',
|
||||||
|
apply: 'นำไปใช้',
|
||||||
},
|
},
|
||||||
|
|
||||||
menu: {
|
menu: {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@ import {
|
||||||
UndoButton,
|
UndoButton,
|
||||||
} from 'components/button';
|
} from 'components/button';
|
||||||
|
|
||||||
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const utilsStore = useUtilsStore();
|
const utilsStore = useUtilsStore();
|
||||||
|
|
@ -160,12 +159,18 @@ const refQrCodeUpload = ref();
|
||||||
const refImageUpload = ref();
|
const refImageUpload = ref();
|
||||||
const isImageEdit = ref(false);
|
const isImageEdit = ref(false);
|
||||||
const isQrCodeEdit = ref(false);
|
const isQrCodeEdit = ref(false);
|
||||||
const profileFile = ref<File | undefined>(undefined);
|
const profileFile = ref<File | null>(null);
|
||||||
const qrCodeFile = ref<File | undefined>(undefined);
|
const qrCodeFile = ref<File | undefined>(undefined);
|
||||||
const imageUrl = ref<string>('');
|
const imageUrl = ref<string>('');
|
||||||
const prevImageUrl = ref<string>('');
|
const prevImageUrl = ref<string>('');
|
||||||
const currentNode = ref<BranchWithChildren>();
|
const currentNode = ref<BranchWithChildren>();
|
||||||
const imageDialog = ref(false);
|
const imageDialog = ref(false);
|
||||||
|
const refreshImageState = ref(false);
|
||||||
|
const imageList = ref<{ selectedImage: string; list: string[] }>();
|
||||||
|
const onCreateImageList = ref<{
|
||||||
|
selectedImage: string;
|
||||||
|
list: { url: string; imgFile: File | null; name: string }[];
|
||||||
|
}>({ selectedImage: '', list: [] });
|
||||||
const qrCodeDialog = ref(false);
|
const qrCodeDialog = ref(false);
|
||||||
|
|
||||||
const qrCodeimageUrl = ref<string>('');
|
const qrCodeimageUrl = ref<string>('');
|
||||||
|
|
@ -335,6 +340,7 @@ const defaultFormData = {
|
||||||
lineId: '',
|
lineId: '',
|
||||||
webUrl: '',
|
webUrl: '',
|
||||||
virtual: false,
|
virtual: false,
|
||||||
|
selectedImage: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
const formDialogRef = ref();
|
const formDialogRef = ref();
|
||||||
|
|
@ -350,11 +356,11 @@ const currentEdit = ref<{ id: string; code: string }>({
|
||||||
code: '',
|
code: '',
|
||||||
});
|
});
|
||||||
const formData = ref<
|
const formData = ref<
|
||||||
Omit<BranchCreate & { codeHeadOffice?: string }, 'qrCodeImage' | 'imageUrl'>
|
Omit<BranchCreate & { codeHeadOffice?: string }, 'qrCodeImage'>
|
||||||
>(structuredClone(defaultFormData));
|
>(structuredClone(defaultFormData));
|
||||||
|
|
||||||
const prevFormData = ref<
|
const prevFormData = ref<
|
||||||
Omit<BranchCreate & { codeHeadOffice?: string }, 'qrCodeImage' | 'imageUrl'>
|
Omit<BranchCreate & { codeHeadOffice?: string }, 'qrCodeImage'>
|
||||||
>(structuredClone(defaultFormData));
|
>(structuredClone(defaultFormData));
|
||||||
|
|
||||||
const modalDrawer = ref<boolean>(false);
|
const modalDrawer = ref<boolean>(false);
|
||||||
|
|
@ -383,8 +389,8 @@ async function selectedSubBranche(id: string) {
|
||||||
async function fetchBranchById(id: string) {
|
async function fetchBranchById(id: string) {
|
||||||
const res = await branchStore.fetchById(id, { includeContact: true });
|
const res = await branchStore.fetchById(id, { includeContact: true });
|
||||||
if (res) {
|
if (res) {
|
||||||
qrCodeimageUrl.value = `${apiBaseUrl}/branch/${res.id}/line-image?ts=${Date.now()}`;
|
qrCodeimageUrl.value = `${baseUrl}/branch/${res.id}/image?ts=${Date.now()}`;
|
||||||
imageUrl.value = `${apiBaseUrl}/branch/${res.id}/branch-image`;
|
imageUrl.value = `${baseUrl}/branch/${res.id}/image/${res.selectedImage}`;
|
||||||
prevImageUrl.value = res.imageUrl;
|
prevImageUrl.value = res.imageUrl;
|
||||||
formBankBook.value = res.bank;
|
formBankBook.value = res.bank;
|
||||||
|
|
||||||
|
|
@ -417,6 +423,7 @@ async function fetchBranchById(id: string) {
|
||||||
status: res.status,
|
status: res.status,
|
||||||
webUrl: res.webUrl,
|
webUrl: res.webUrl,
|
||||||
virtual: res.virtual,
|
virtual: res.virtual,
|
||||||
|
selectedImage: res.selectedImage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -447,8 +454,9 @@ async function undo() {
|
||||||
isQrCodeEdit.value = false;
|
isQrCodeEdit.value = false;
|
||||||
isImageEdit.value = false;
|
isImageEdit.value = false;
|
||||||
formType.value = 'view';
|
formType.value = 'view';
|
||||||
imageUrl.value = prevImageUrl.value;
|
const tempSelectedImage = formData.value.selectedImage;
|
||||||
formData.value = prevFormData.value;
|
formData.value = JSON.parse(JSON.stringify(prevFormData.value));
|
||||||
|
formData.value.selectedImage = tempSelectedImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(expandedTree, async () => {
|
watch(expandedTree, async () => {
|
||||||
|
|
@ -501,9 +509,7 @@ function drawerEdit() {
|
||||||
isQrCodeEdit.value = true;
|
isQrCodeEdit.value = true;
|
||||||
isImageEdit.value = true;
|
isImageEdit.value = true;
|
||||||
formType.value = 'edit';
|
formType.value = 'edit';
|
||||||
prevFormData.value = {
|
prevFormData.value = JSON.parse(JSON.stringify(formData.value));
|
||||||
...formData.value,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentBranchAdmin = ref<User | null>(null);
|
const currentBranchAdmin = ref<User | null>(null);
|
||||||
|
|
@ -514,6 +520,8 @@ async function triggerEdit(
|
||||||
code?: string,
|
code?: string,
|
||||||
) {
|
) {
|
||||||
await fetchBranchById(id);
|
await fetchBranchById(id);
|
||||||
|
await fetchImageList(id, formData.value.selectedImage || '');
|
||||||
|
|
||||||
if (openFormType === 'form') {
|
if (openFormType === 'form') {
|
||||||
formType.value = 'edit';
|
formType.value = 'edit';
|
||||||
openDialog();
|
openDialog();
|
||||||
|
|
@ -675,12 +683,12 @@ async function triggerChangeStatus(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onSubmit() {
|
async function onSubmit(submitSelectedItem?: boolean) {
|
||||||
if (formType.value === 'edit') {
|
if (formType.value === 'edit' || submitSelectedItem) {
|
||||||
delete formData.value['codeHeadOffice'];
|
delete formData.value['codeHeadOffice'];
|
||||||
delete formData.value['code'];
|
delete formData.value['code'];
|
||||||
|
|
||||||
await branchStore.editById(
|
const res = await branchStore.editById(
|
||||||
currentEdit.value.id,
|
currentEdit.value.id,
|
||||||
{
|
{
|
||||||
...formData.value,
|
...formData.value,
|
||||||
|
|
@ -695,8 +703,12 @@ async function onSubmit() {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
formData.value.codeHeadOffice = formData.value.code = res.code;
|
||||||
|
imageUrl.value = `${baseUrl}/branch/${res.id}/image/${res.selectedImage}`;
|
||||||
|
|
||||||
await fetchList({ pageSize: 99999 });
|
await fetchList({ pageSize: 99999 });
|
||||||
if (!imageDialog.value) modalDrawer.value = false;
|
|
||||||
|
if (!imageDialog.value) modalDrawer.value = submitSelectedItem || false;
|
||||||
modal.value = false;
|
modal.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -709,6 +721,7 @@ async function onSubmit() {
|
||||||
imageUrl: profileFile.value,
|
imageUrl: profileFile.value,
|
||||||
},
|
},
|
||||||
formBankBook.value,
|
formBankBook.value,
|
||||||
|
onCreateImageList.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
await fetchList({ pageSize: 99999 });
|
await fetchList({ pageSize: 99999 });
|
||||||
|
|
@ -801,6 +814,15 @@ function handleHold(node: BranchWithChildren) {
|
||||||
// };
|
// };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchImageList(id: string, selectedName: string) {
|
||||||
|
const res = await branchStore.fetchImageListById(id);
|
||||||
|
imageList.value = {
|
||||||
|
selectedImage: selectedName,
|
||||||
|
list: res.map((n: string) => `branch/${id}/image/${n}`),
|
||||||
|
};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => profileFile.value,
|
() => profileFile.value,
|
||||||
() => {
|
() => {
|
||||||
|
|
@ -1291,7 +1313,11 @@ watch(currentHq, () => {
|
||||||
:ratio="1"
|
:ratio="1"
|
||||||
:src="
|
:src="
|
||||||
baseUrl +
|
baseUrl +
|
||||||
`/branch/${props.row.id}/branch-image?ts=${Date.now()}`
|
`/branch/${props.row.id}/image/${props.row.selectedImage}`.concat(
|
||||||
|
refreshImageState
|
||||||
|
? `?ts=${Date.now()}`
|
||||||
|
: '',
|
||||||
|
)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<template #error>
|
<template #error>
|
||||||
|
|
@ -1392,6 +1418,7 @@ watch(currentHq, () => {
|
||||||
'subBranch',
|
'subBranch',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
await drawerEdit();
|
||||||
formType = 'edit';
|
formType = 'edit';
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
|
|
@ -1465,7 +1492,7 @@ watch(currentHq, () => {
|
||||||
$i18n.locale === 'eng'
|
$i18n.locale === 'eng'
|
||||||
? `${props.row.addressEN || ''} ${props.row.subDistrict?.nameEN || ''} ${props.row.district?.nameEN || ''} ${props.row.province?.nameEN || ''}`
|
? `${props.row.addressEN || ''} ${props.row.subDistrict?.nameEN || ''} ${props.row.district?.nameEN || ''} ${props.row.province?.nameEN || ''}`
|
||||||
: `${props.row.address || ''} ${props.row.subDistrict?.name || ''} ${props.row.district?.name || ''} ${props.row.province?.name || ''}`,
|
: `${props.row.address || ''} ${props.row.subDistrict?.name || ''} ${props.row.district?.name || ''} ${props.row.province?.name || ''}`,
|
||||||
branchImgUrl: `/branch/${props.row.id}/branch-image`,
|
branchImgUrl: `/branch/${props.row.id}/branch`,
|
||||||
}"
|
}"
|
||||||
:field-selected="fieldSelected"
|
:field-selected="fieldSelected"
|
||||||
:badge-field="['branchLabelStatus']"
|
:badge-field="['branchLabelStatus']"
|
||||||
|
|
@ -1517,6 +1544,7 @@ watch(currentHq, () => {
|
||||||
'subBranch',
|
'subBranch',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
await drawerEdit();
|
||||||
formType = 'edit';
|
formType = 'edit';
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
|
|
@ -1556,13 +1584,15 @@ watch(currentHq, () => {
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
:close="
|
:close="
|
||||||
() => (
|
() => {
|
||||||
(formLastSubBranch = 0),
|
formLastSubBranch = 0;
|
||||||
(modal = false),
|
modal = false;
|
||||||
(profileFile = undefined),
|
profileFile = null;
|
||||||
(isImageEdit = false),
|
isImageEdit = false;
|
||||||
(isSubCreate = false)
|
isSubCreate = false;
|
||||||
)
|
imageList = { selectedImage: '', list: [] };
|
||||||
|
onCreateImageList = { selectedImage: '', list: [] };
|
||||||
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div class="q-mx-lg q-mt-lg">
|
<div class="q-mx-lg q-mt-lg">
|
||||||
|
|
@ -1604,8 +1634,13 @@ watch(currentHq, () => {
|
||||||
: '--violet-11'
|
: '--violet-11'
|
||||||
}-hsl)/${imageUrl ? '0' : '0.15'})`"
|
}-hsl)/${imageUrl ? '0' : '0.15'})`"
|
||||||
:menu="formMenuIcon"
|
:menu="formMenuIcon"
|
||||||
@view="imageDialog = true"
|
@view="
|
||||||
@edit="refImageUpload && refImageUpload.browse()"
|
() => {
|
||||||
|
imageDialog = true;
|
||||||
|
isImageEdit = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@edit="imageDialog = isImageEdit = true"
|
||||||
@update:toggle-status="
|
@update:toggle-status="
|
||||||
() => {
|
() => {
|
||||||
formData.status =
|
formData.status =
|
||||||
|
|
@ -1769,21 +1804,18 @@ watch(currentHq, () => {
|
||||||
<DrawerInfo
|
<DrawerInfo
|
||||||
ref="formDialogRef"
|
ref="formDialogRef"
|
||||||
v-model:drawer-open="modalDrawer"
|
v-model:drawer-open="modalDrawer"
|
||||||
|
:submit="() => onSubmit()"
|
||||||
:category="changeTitle(formType, formTypeBranch)"
|
:category="changeTitle(formType, formTypeBranch)"
|
||||||
:title="$i18n.locale === 'eng' ? formData.nameEN : formData.name"
|
:title="$i18n.locale === 'eng' ? formData.nameEN : formData.name"
|
||||||
:address-separator="true"
|
|
||||||
:undo="() => undo()"
|
|
||||||
:is-edit="formType === 'edit'"
|
|
||||||
:edit-data="() => drawerEdit()"
|
|
||||||
:submit="() => onSubmit()"
|
|
||||||
:delete-data="() => triggerDelete(currentEdit.id)"
|
|
||||||
:close="
|
:close="
|
||||||
() => (
|
() => {
|
||||||
(modalDrawer = false),
|
modalDrawer = false;
|
||||||
flowStore.rotate(),
|
isImageEdit = false;
|
||||||
(isImageEdit = false),
|
imageList = { selectedImage: '', list: [] };
|
||||||
resetScrollBar('branch-info')
|
onCreateImageList = { selectedImage: '', list: [] };
|
||||||
)
|
flowStore.rotate();
|
||||||
|
resetScrollBar('branch-info');
|
||||||
|
}
|
||||||
"
|
"
|
||||||
:statusBranch="formData.status"
|
:statusBranch="formData.status"
|
||||||
hide-action
|
hide-action
|
||||||
|
|
@ -1796,8 +1828,11 @@ watch(currentHq, () => {
|
||||||
v-model:cover-url="imageUrl"
|
v-model:cover-url="imageUrl"
|
||||||
:toggleTitle="$t('status.title')"
|
:toggleTitle="$t('status.title')"
|
||||||
:hideFade="imageUrl === '' || imageUrl === null"
|
:hideFade="imageUrl === '' || imageUrl === null"
|
||||||
:img="imageUrl || null"
|
:img="
|
||||||
:cover="imageUrl || null"
|
`${baseUrl}/branch/${currentId}/image/${formData.selectedImage}`.concat(
|
||||||
|
refreshImageState ? `?ts=${Date.now()}` : '',
|
||||||
|
) || null
|
||||||
|
"
|
||||||
:title="formData.name"
|
:title="formData.name"
|
||||||
:caption="formData.code"
|
:caption="formData.code"
|
||||||
icon="mdi-office-building-outline"
|
icon="mdi-office-building-outline"
|
||||||
|
|
@ -1820,10 +1855,15 @@ watch(currentHq, () => {
|
||||||
: $q.dark.isActive
|
: $q.dark.isActive
|
||||||
? '--violet-10'
|
? '--violet-10'
|
||||||
: '--violet-11'
|
: '--violet-11'
|
||||||
}-hsl)/${imageUrl ? '0' : '0.15'})`"
|
}-hsl)/${imageUrl ? '0' : '0.1'})`"
|
||||||
v-model:toggle-status="formData.status"
|
v-model:toggle-status="formData.status"
|
||||||
@view="imageDialog = true"
|
@view="
|
||||||
@edit="refImageUpload && refImageUpload.browse()"
|
() => {
|
||||||
|
imageDialog = true;
|
||||||
|
isImageEdit = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@edit="imageDialog = isImageEdit = true"
|
||||||
@update:toggle-status="
|
@update:toggle-status="
|
||||||
async (v) => {
|
async (v) => {
|
||||||
const res = await triggerChangeStatus(currentId, v);
|
const res = await triggerChangeStatus(currentId, v);
|
||||||
|
|
@ -1836,7 +1876,6 @@ watch(currentHq, () => {
|
||||||
await fetchList({ pageSize: 99999 });
|
await fetchList({ pageSize: 99999 });
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
:readonly="formType === 'view'"
|
|
||||||
:menu="formMenuIcon"
|
:menu="formMenuIcon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -2200,12 +2239,53 @@ watch(currentHq, () => {
|
||||||
<ImageUploadDialog
|
<ImageUploadDialog
|
||||||
ref="refImageUpload"
|
ref="refImageUpload"
|
||||||
v-model:dialogState="imageDialog"
|
v-model:dialogState="imageDialog"
|
||||||
v-model:file="profileFile as File"
|
v-model:file="profileFile"
|
||||||
v-model:image-url="imageUrl"
|
v-model:image-url="imageUrl"
|
||||||
:hiddenFooter="!isImageEdit && !modal"
|
v-model:data-list="imageList"
|
||||||
@save="imageDialog = false"
|
v-model:on-create-data-list="onCreateImageList"
|
||||||
clearButton
|
:on-create="modal"
|
||||||
|
:hiddenFooter="!isImageEdit"
|
||||||
|
@add-image="
|
||||||
|
async (v) => {
|
||||||
|
if (!v) return;
|
||||||
|
if (!currentId) return;
|
||||||
|
await branchStore.addImageList(v, currentId, Date.now());
|
||||||
|
await fetchImageList(currentId, formData.selectedImage || '');
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@remove-image="
|
||||||
|
async (v) => {
|
||||||
|
if (!v) return;
|
||||||
|
if (!currentId) return;
|
||||||
|
const name = v.split('/').pop() || '';
|
||||||
|
await branchStore.deleteImageByName(currentId, name);
|
||||||
|
await fetchImageList(currentId, name);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@submit="
|
||||||
|
async (v) => {
|
||||||
|
if (modal) {
|
||||||
|
imageUrl = v;
|
||||||
|
imageDialog = false;
|
||||||
|
} else {
|
||||||
|
refreshImageState = true;
|
||||||
|
formData.selectedImage = v;
|
||||||
|
imageList ? (imageList.selectedImage = v) : '';
|
||||||
|
imageUrl = `${baseUrl}/branch/${currentId && currentId}/image/${v}`;
|
||||||
|
await onSubmit(true);
|
||||||
|
imageDialog = false;
|
||||||
|
refreshImageState = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
>
|
>
|
||||||
|
<template #title>
|
||||||
|
<span v-if="!modal" class="justify-center flex text-bold">
|
||||||
|
{{ $t('general.image') }}
|
||||||
|
{{ changeTitle(formType, formTypeBranch) }}
|
||||||
|
{{ $i18n.locale === 'eng' ? formData.nameEN : formData.name }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
<template #error>
|
<template #error>
|
||||||
<div class="full-height full-width" style="background: white">
|
<div class="full-height full-width" style="background: white">
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, watch, computed } from 'vue';
|
import { ref, onMounted, watch, computed } from 'vue';
|
||||||
import useUtilsStore, { dialog } from 'stores/utils';
|
import useUtilsStore, { dialog, baseUrl } from 'stores/utils';
|
||||||
import { calculateAge } from 'src/utils/datetime';
|
import { calculateAge } from 'src/utils/datetime';
|
||||||
import { useQuasar, type QTableProps } from 'quasar';
|
import { useQuasar, type QTableProps } from 'quasar';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
@ -59,7 +59,6 @@ const adrressStore = useAddressStore();
|
||||||
const useMyBranchStore = useMyBranch();
|
const useMyBranchStore = useMyBranch();
|
||||||
const { data: userData } = storeToRefs(userStore);
|
const { data: userData } = storeToRefs(userStore);
|
||||||
const { myBranch } = storeToRefs(useMyBranchStore);
|
const { myBranch } = storeToRefs(useMyBranchStore);
|
||||||
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
|
|
||||||
|
|
||||||
const defaultFormData = {
|
const defaultFormData = {
|
||||||
provinceId: null,
|
provinceId: null,
|
||||||
|
|
@ -87,7 +86,6 @@ const defaultFormData = {
|
||||||
firstName: '',
|
firstName: '',
|
||||||
userRole: '',
|
userRole: '',
|
||||||
userType: '',
|
userType: '',
|
||||||
profileImage: null,
|
|
||||||
birthDate: null,
|
birthDate: null,
|
||||||
responsibleArea: null,
|
responsibleArea: null,
|
||||||
username: '',
|
username: '',
|
||||||
|
|
@ -178,7 +176,6 @@ const userCode = ref<string>();
|
||||||
const currentUser = ref<User>();
|
const currentUser = ref<User>();
|
||||||
const infoDrawerEdit = ref(false);
|
const infoDrawerEdit = ref(false);
|
||||||
const infoPersonId = ref<string>('');
|
const infoPersonId = ref<string>('');
|
||||||
const infoPersonCard = ref();
|
|
||||||
const infoDrawer = ref(false);
|
const infoDrawer = ref(false);
|
||||||
const profileSubmit = ref(false);
|
const profileSubmit = ref(false);
|
||||||
const urlProfile = ref<string>();
|
const urlProfile = ref<string>();
|
||||||
|
|
@ -198,6 +195,7 @@ const typeStats = ref<UserTypeStats>();
|
||||||
const agencyFile = ref<File[]>([]);
|
const agencyFile = ref<File[]>([]);
|
||||||
const agencyFileList = ref<{ name: string; url: string }[]>([]);
|
const agencyFileList = ref<{ name: string; url: string }[]>([]);
|
||||||
const formData = ref<UserCreate>({
|
const formData = ref<UserCreate>({
|
||||||
|
selectedImage: '',
|
||||||
branchId: '',
|
branchId: '',
|
||||||
provinceId: null,
|
provinceId: null,
|
||||||
districtId: null,
|
districtId: null,
|
||||||
|
|
@ -227,7 +225,6 @@ const formData = ref<UserCreate>({
|
||||||
namePrefix: null,
|
namePrefix: null,
|
||||||
userRole: '',
|
userRole: '',
|
||||||
userType: '',
|
userType: '',
|
||||||
profileImage: null,
|
|
||||||
birthDate: null,
|
birthDate: null,
|
||||||
responsibleArea: null,
|
responsibleArea: null,
|
||||||
checkpoint: null,
|
checkpoint: null,
|
||||||
|
|
@ -240,12 +237,18 @@ const isImageEdit = ref<boolean>(false);
|
||||||
const imageUrl = ref<string>('');
|
const imageUrl = ref<string>('');
|
||||||
const profileFileImg = ref<File | null>(null);
|
const profileFileImg = ref<File | null>(null);
|
||||||
const imageDialog = ref(false);
|
const imageDialog = ref(false);
|
||||||
|
const refreshImageState = ref(false);
|
||||||
|
const imageList = ref<{ selectedImage: string; list: string[] }>();
|
||||||
|
const onCreateImageList = ref<{
|
||||||
|
selectedImage: string;
|
||||||
|
list: { url: string; imgFile: File | null; name: string }[];
|
||||||
|
}>({ selectedImage: '', list: [] });
|
||||||
|
|
||||||
// const inputFile = document.createElement('input');
|
// const inputFile = document.createElement('input');
|
||||||
// inputFile.type = 'file';
|
// inputFile.type = 'file';
|
||||||
// inputFile.accept = 'image/*';
|
// inputFile.accept = 'image/*';
|
||||||
|
|
||||||
const reader = new FileReader();
|
// const reader = new FileReader();
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
|
|
@ -357,23 +360,6 @@ async function openDialog(
|
||||||
|
|
||||||
infoDrawerEdit.value = isPersonEdit ? true : false;
|
infoDrawerEdit.value = isPersonEdit ? true : false;
|
||||||
infoDrawer.value = true;
|
infoDrawer.value = true;
|
||||||
const user = userData.value.result.find((x) => x.id === id);
|
|
||||||
infoPersonCard.value = user
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
id: user.id,
|
|
||||||
img: `${user.profileImageUrl}`,
|
|
||||||
name:
|
|
||||||
locale.value === 'eng'
|
|
||||||
? `${user.firstNameEN} ${user.lastNameEN}`
|
|
||||||
: `${user.firstName} ${user.lastName}`,
|
|
||||||
male: user.gender === 'male',
|
|
||||||
female: user.gender === 'female',
|
|
||||||
badge: user.code,
|
|
||||||
disabled: user.status === 'INACTIVE',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
statusToggle.value = true;
|
statusToggle.value = true;
|
||||||
|
|
@ -387,7 +373,11 @@ function undo() {
|
||||||
assignFormData(infoPersonId.value);
|
assignFormData(infoPersonId.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClose() {
|
function onClose(excludeDialog?: boolean) {
|
||||||
|
if (excludeDialog) {
|
||||||
|
infoDrawer.value = excludeDialog || false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
hqId.value = '';
|
hqId.value = '';
|
||||||
brId.value = '';
|
brId.value = '';
|
||||||
userId.value = '';
|
userId.value = '';
|
||||||
|
|
@ -398,17 +388,17 @@ function onClose() {
|
||||||
agencyFile.value = [];
|
agencyFile.value = [];
|
||||||
modal.value = false;
|
modal.value = false;
|
||||||
isEdit.value = false;
|
isEdit.value = false;
|
||||||
infoDrawer.value = false;
|
|
||||||
profileSubmit.value = false;
|
profileSubmit.value = false;
|
||||||
statusToggle.value = true;
|
statusToggle.value = true;
|
||||||
isImageEdit.value = false;
|
isImageEdit.value = false;
|
||||||
|
currentUser.value = undefined;
|
||||||
Object.assign(formData.value, defaultFormData);
|
Object.assign(formData.value, defaultFormData);
|
||||||
mapUserType(selectorLabel.value);
|
mapUserType(selectorLabel.value);
|
||||||
|
imageList.value = { selectedImage: '', list: [] };
|
||||||
|
onCreateImageList.value = { selectedImage: '', list: [] };
|
||||||
flowStore.rotate();
|
flowStore.rotate();
|
||||||
}
|
}
|
||||||
async function onSubmit() {
|
async function onSubmit(excludeDialog?: boolean) {
|
||||||
formData.value.profileImage = profileFileImg.value as File;
|
|
||||||
|
|
||||||
if (isEdit.value && userId.value) {
|
if (isEdit.value && userId.value) {
|
||||||
if (!userId.value) return;
|
if (!userId.value) return;
|
||||||
|
|
||||||
|
|
@ -441,7 +431,7 @@ async function onSubmit() {
|
||||||
if (res) {
|
if (res) {
|
||||||
userStats.value = res;
|
userStats.value = res;
|
||||||
}
|
}
|
||||||
onClose();
|
onClose(excludeDialog);
|
||||||
} else {
|
} else {
|
||||||
if (!hqId.value) return;
|
if (!hqId.value) return;
|
||||||
|
|
||||||
|
|
@ -456,7 +446,10 @@ async function onSubmit() {
|
||||||
: hqId.value
|
: hqId.value
|
||||||
? hqId.value
|
? hqId.value
|
||||||
: '';
|
: '';
|
||||||
const result = await userStore.create(formData.value);
|
const result = await userStore.create(
|
||||||
|
formData.value,
|
||||||
|
onCreateImageList.value,
|
||||||
|
);
|
||||||
|
|
||||||
if (result && formData.value.userType === 'AGENCY') {
|
if (result && formData.value.userType === 'AGENCY') {
|
||||||
if (!agencyFile.value) return;
|
if (!agencyFile.value) return;
|
||||||
|
|
@ -558,7 +551,6 @@ async function assignFormData(idEdit: string) {
|
||||||
currentUser.value = foundUser;
|
currentUser.value = foundUser;
|
||||||
if (currentUser.value) {
|
if (currentUser.value) {
|
||||||
infoPersonId.value = currentUser.value.id;
|
infoPersonId.value = currentUser.value.id;
|
||||||
imageUrl.value = currentUser.value.profileImageUrl;
|
|
||||||
}
|
}
|
||||||
formData.value = {
|
formData.value = {
|
||||||
branchId: foundUser.branch[0]?.id,
|
branchId: foundUser.branch[0]?.id,
|
||||||
|
|
@ -591,6 +583,7 @@ async function assignFormData(idEdit: string) {
|
||||||
checkpointEN: foundUser.checkpointEN,
|
checkpointEN: foundUser.checkpointEN,
|
||||||
responsibleArea: foundUser.responsibleArea,
|
responsibleArea: foundUser.responsibleArea,
|
||||||
status: foundUser.status,
|
status: foundUser.status,
|
||||||
|
selectedImage: foundUser.selectedImage,
|
||||||
licenseExpireDate:
|
licenseExpireDate:
|
||||||
(foundUser.licenseExpireDate &&
|
(foundUser.licenseExpireDate &&
|
||||||
new Date(foundUser.licenseExpireDate)) ||
|
new Date(foundUser.licenseExpireDate)) ||
|
||||||
|
|
@ -619,14 +612,14 @@ async function assignFormData(idEdit: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
userCode.value = foundUser.code;
|
userCode.value = foundUser.code;
|
||||||
urlProfile.value = `${apiBaseUrl}/user/${foundUser.id}/image`;
|
urlProfile.value = `${baseUrl}/user/${foundUser.id}/profile-image/${foundUser.selectedImage}`;
|
||||||
|
|
||||||
isEdit.value = true;
|
isEdit.value = true;
|
||||||
profileSubmit.value = true;
|
profileSubmit.value = true;
|
||||||
hqId.value && (await userStore.fetchBrOption(hqId.value));
|
hqId.value && (await userStore.fetchBrOption(hqId.value));
|
||||||
if (infoPersonCard.value) {
|
|
||||||
infoPersonCard.value[0].img = foundUser.profileImageUrl;
|
await fetchImageList(foundUser.id, foundUser.selectedImage);
|
||||||
}
|
|
||||||
if (formData.value.districtId) {
|
if (formData.value.districtId) {
|
||||||
await adrressStore.fetchSubDistrictByProvinceId(
|
await adrressStore.fetchSubDistrictByProvinceId(
|
||||||
formData.value.districtId,
|
formData.value.districtId,
|
||||||
|
|
@ -635,10 +628,6 @@ async function assignFormData(idEdit: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function openImageDialog() {
|
|
||||||
imageDialog.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
utilsStore.currentTitle.title = 'personnel.title';
|
utilsStore.currentTitle.title = 'personnel.title';
|
||||||
utilsStore.currentTitle.path = [{ text: 'personnel.caption', i18n: true }];
|
utilsStore.currentTitle.path = [{ text: 'personnel.caption', i18n: true }];
|
||||||
|
|
@ -667,6 +656,15 @@ function mapRole(value: string) {
|
||||||
return option ? option.label : '-';
|
return option ? option.label : '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchImageList(id: string, selectedName: string) {
|
||||||
|
const res = await userStore.fetchImageListById(id);
|
||||||
|
imageList.value = {
|
||||||
|
selectedImage: selectedName,
|
||||||
|
list: res.map((n: string) => `user/${id}/profile-image/${n}`),
|
||||||
|
};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => selectorLabel.value,
|
() => selectorLabel.value,
|
||||||
async (label) => {
|
async (label) => {
|
||||||
|
|
@ -1145,7 +1143,7 @@ watch(
|
||||||
<q-img
|
<q-img
|
||||||
class="text-center"
|
class="text-center"
|
||||||
:ratio="1"
|
:ratio="1"
|
||||||
:src="`${apiBaseUrl}/user/${props.row.id}/image?ts=${Date.now()}`"
|
:src="`${baseUrl}/user/${props.row.id}/profile-image/${props.row.selectedImage}?ts=${Date.now()}`"
|
||||||
>
|
>
|
||||||
<template #error>
|
<template #error>
|
||||||
<div
|
<div
|
||||||
|
|
@ -1314,7 +1312,6 @@ watch(
|
||||||
:prefix-id="props.row.username"
|
:prefix-id="props.row.username"
|
||||||
:data="{
|
:data="{
|
||||||
code: props.row.code,
|
code: props.row.code,
|
||||||
|
|
||||||
name:
|
name:
|
||||||
$i18n.locale === 'eng'
|
$i18n.locale === 'eng'
|
||||||
? `${props.row.firstNameEN} ${props.row.lastNameEN}`.trim()
|
? `${props.row.firstNameEN} ${props.row.lastNameEN}`.trim()
|
||||||
|
|
@ -1366,7 +1363,7 @@ watch(
|
||||||
<q-img
|
<q-img
|
||||||
class="text-center"
|
class="text-center"
|
||||||
:ratio="1"
|
:ratio="1"
|
||||||
:src="`${apiBaseUrl}/user/${props.row.id}/image?ts=${Date.now()}`"
|
:src="`${baseUrl}/user/${props.row.id}/profile-image/${props.row.selectedImage}?ts=${Date.now()}`"
|
||||||
style="
|
style="
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
@ -1532,12 +1529,13 @@ watch(
|
||||||
v-model:toggle-status="formData.status"
|
v-model:toggle-status="formData.status"
|
||||||
hideFade
|
hideFade
|
||||||
:menu="formMenuIcon"
|
:menu="formMenuIcon"
|
||||||
:readonly="!infoDrawerEdit"
|
|
||||||
:toggleTitle="$t('status.title')"
|
:toggleTitle="$t('status.title')"
|
||||||
:title="`${$i18n.locale === 'eng' ? `${formData.firstNameEN} ${formData.lastNameEN}` : `${formData.firstName} ${formData.lastName}`}`"
|
:title="`${$i18n.locale === 'eng' ? `${formData.firstNameEN} ${formData.lastNameEN}` : `${formData.firstName} ${formData.lastName}`}`"
|
||||||
:caption="userCode"
|
:caption="userCode"
|
||||||
:img="
|
:img="
|
||||||
urlProfile ||
|
`${baseUrl}/user/${currentUser.id}/profile-image/${formData.selectedImage}`.concat(
|
||||||
|
refreshImageState ? `?ts=${Date.now()}` : '',
|
||||||
|
) ||
|
||||||
{
|
{
|
||||||
male: '/no-img-man.png',
|
male: '/no-img-man.png',
|
||||||
female: '/no-img-female.png',
|
female: '/no-img-female.png',
|
||||||
|
|
@ -1549,8 +1547,13 @@ watch(
|
||||||
female: '/no-img-female.png',
|
female: '/no-img-female.png',
|
||||||
}[formData.gender]
|
}[formData.gender]
|
||||||
"
|
"
|
||||||
@view="openImageDialog"
|
@view="
|
||||||
@edit="refImageUpload && refImageUpload.browse()"
|
() => {
|
||||||
|
imageDialog = true;
|
||||||
|
isImageEdit = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@edit="imageDialog = isImageEdit = true"
|
||||||
@update:toggle-status="
|
@update:toggle-status="
|
||||||
async (v) => {
|
async (v) => {
|
||||||
await triggerChangeStatus(infoPersonId, v);
|
await triggerChangeStatus(infoPersonId, v);
|
||||||
|
|
@ -1779,8 +1782,13 @@ watch(
|
||||||
}[formData.gender]
|
}[formData.gender]
|
||||||
"
|
"
|
||||||
hideFade
|
hideFade
|
||||||
@view="imageDialog = true"
|
@view="
|
||||||
@edit="refImageUpload && refImageUpload.browse()"
|
() => {
|
||||||
|
imageDialog = true;
|
||||||
|
isImageEdit = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@edit="imageDialog = isImageEdit = true"
|
||||||
@update:toggle-status="
|
@update:toggle-status="
|
||||||
() => {
|
() => {
|
||||||
formData.status =
|
formData.status =
|
||||||
|
|
@ -1914,10 +1922,59 @@ watch(
|
||||||
v-model:dialogState="imageDialog"
|
v-model:dialogState="imageDialog"
|
||||||
v-model:file="profileFileImg"
|
v-model:file="profileFileImg"
|
||||||
v-model:image-url="urlProfile"
|
v-model:image-url="urlProfile"
|
||||||
:hiddenFooter="!isImageEdit && !modal"
|
v-model:data-list="imageList"
|
||||||
@save="imageDialog = false"
|
v-model:on-create-data-list="onCreateImageList"
|
||||||
clearButton
|
:on-create="modal"
|
||||||
|
:hiddenFooter="!isImageEdit"
|
||||||
|
@add-image="
|
||||||
|
async (v) => {
|
||||||
|
if (!v) return;
|
||||||
|
if (!currentUser) return;
|
||||||
|
const res = await userStore.addImageList(
|
||||||
|
v,
|
||||||
|
currentUser?.id,
|
||||||
|
Date.now(),
|
||||||
|
);
|
||||||
|
await fetchImageList(currentUser?.id, res);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@remove-image="
|
||||||
|
async (v) => {
|
||||||
|
if (!v) return;
|
||||||
|
if (!currentUser) return;
|
||||||
|
|
||||||
|
const name = v.split('/').pop() || '';
|
||||||
|
await userStore.deleteImageByName(currentUser?.id, name);
|
||||||
|
await fetchImageList(currentUser?.id, name);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@submit="
|
||||||
|
async (v) => {
|
||||||
|
if (modal) {
|
||||||
|
urlProfile = v;
|
||||||
|
imageDialog = false;
|
||||||
|
} else {
|
||||||
|
refreshImageState = true;
|
||||||
|
formData.selectedImage = v;
|
||||||
|
imageList ? (imageList.selectedImage = v) : '';
|
||||||
|
urlProfile = `${baseUrl}/user/${currentUser && currentUser.id}/profile-image/${v}`;
|
||||||
|
await onSubmit(true);
|
||||||
|
imageDialog = false;
|
||||||
|
refreshImageState = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
>
|
>
|
||||||
|
<template #title>
|
||||||
|
<span v-if="!modal" class="justify-center flex text-bold">
|
||||||
|
{{ $t('general.image') }}
|
||||||
|
{{
|
||||||
|
$i18n.locale === 'eng'
|
||||||
|
? `${formData.firstNameEN} ${formData.lastNameEN}`
|
||||||
|
: `${formData.firstName} ${formData.lastName}`
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
<template #error>
|
<template #error>
|
||||||
<div class="full-height full-width" style="background: white">
|
<div class="full-height full-width" style="background: white">
|
||||||
<div
|
<div
|
||||||
|
|
@ -1938,7 +1995,7 @@ watch(
|
||||||
/>
|
/>
|
||||||
<q-icon
|
<q-icon
|
||||||
v-else
|
v-else
|
||||||
size="7vw"
|
size="3rem"
|
||||||
:name="
|
:name="
|
||||||
infoDrawer ? 'mdi-account-outline' : 'mdi-account-plus-outline'
|
infoDrawer ? 'mdi-account-outline' : 'mdi-account-plus-outline'
|
||||||
"
|
"
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,14 @@ const dialogCreateCustomerItem = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// image
|
||||||
|
const refreshImageState = ref(false);
|
||||||
|
const imageList = ref<{ selectedImage: string; list: string[] }>();
|
||||||
|
const onCreateImageList = ref<{
|
||||||
|
selectedImage: string;
|
||||||
|
list: { url: string; imgFile: File | null; name: string }[];
|
||||||
|
}>({ selectedImage: '', list: [] });
|
||||||
|
|
||||||
watch(() => route.name, init);
|
watch(() => route.name, init);
|
||||||
watch(
|
watch(
|
||||||
[currentTab, currentStatus, inputSearch, customerTypeSelected],
|
[currentTab, currentStatus, inputSearch, customerTypeSelected],
|
||||||
|
|
@ -475,6 +483,7 @@ async function openHistory(id: string) {
|
||||||
async function editCustomerForm(id: string) {
|
async function editCustomerForm(id: string) {
|
||||||
await customerFormStore.assignFormData(id);
|
await customerFormStore.assignFormData(id);
|
||||||
await fetchListOfOptionBranch();
|
await fetchListOfOptionBranch();
|
||||||
|
await fetchImageList(id, customerFormData.value.selectedImage || '');
|
||||||
customerFormState.value.dialogType = 'edit';
|
customerFormState.value.dialogType = 'edit';
|
||||||
customerFormState.value.drawerModal = true;
|
customerFormState.value.drawerModal = true;
|
||||||
customerFormState.value.editCustomerId = id;
|
customerFormState.value.editCustomerId = id;
|
||||||
|
|
@ -563,6 +572,15 @@ function returnCountryCode(country: string) {
|
||||||
return tempValue?.value;
|
return tempValue?.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchImageList(id: string, selectedName: string) {
|
||||||
|
const res = await customerStore.fetchImageListById(id);
|
||||||
|
imageList.value = {
|
||||||
|
selectedImage: selectedName,
|
||||||
|
list: res.map((n: string) => `customer/${id}/image/${n}`),
|
||||||
|
};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: When in employee form, if select address same as customer then auto fill
|
// TODO: When in employee form, if select address same as customer then auto fill
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
@ -705,6 +723,14 @@ watch(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => customerFormData.value.image,
|
||||||
|
() => {
|
||||||
|
if (customerFormData.value.image !== null)
|
||||||
|
customerFormState.value.isImageEdit = true;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const emptyCreateDialog = ref(false);
|
const emptyCreateDialog = ref(false);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -1161,7 +1187,7 @@ const emptyCreateDialog = ref(false);
|
||||||
<div class="branch-card__icon">
|
<div class="branch-card__icon">
|
||||||
<q-avatar size="md">
|
<q-avatar size="md">
|
||||||
<q-img
|
<q-img
|
||||||
:src="`${baseUrl}/customer/${props.row.id}/image`"
|
:src="`${baseUrl}/customer/${props.row.id}/image/${props.row.selectedImage}`"
|
||||||
class="full-height full-width"
|
class="full-height full-width"
|
||||||
>
|
>
|
||||||
<template #error>
|
<template #error>
|
||||||
|
|
@ -1371,7 +1397,7 @@ const emptyCreateDialog = ref(false);
|
||||||
$i18n.locale === 'eng'
|
$i18n.locale === 'eng'
|
||||||
? `${props.row.firstNameEN} ${props.row.lastNameEN} `.trim()
|
? `${props.row.firstNameEN} ${props.row.lastNameEN} `.trim()
|
||||||
: `${props.row.firstName} ${props.row.lastName} `.trim(),
|
: `${props.row.firstName} ${props.row.lastName} `.trim(),
|
||||||
img: `${baseUrl}/customer/${props.row.id}/image`,
|
img: `${baseUrl}/customer/${props.row.id}/image/${props.row.selectedImage}`,
|
||||||
fallbackImg: `/images/customer-${props.row.customerType}-avartar-${props.row.gender}.png`,
|
fallbackImg: `/images/customer-${props.row.customerType}-avartar-${props.row.gender}.png`,
|
||||||
male: undefined,
|
male: undefined,
|
||||||
female: undefined,
|
female: undefined,
|
||||||
|
|
@ -1750,8 +1776,15 @@ const emptyCreateDialog = ref(false);
|
||||||
? 'mdi-account-plus-outline'
|
? 'mdi-account-plus-outline'
|
||||||
: 'mdi-office-building-outline'
|
: 'mdi-office-building-outline'
|
||||||
"
|
"
|
||||||
@view="customerFormState.imageDialog = true"
|
@view="
|
||||||
@edit="dialogCustomerImageUpload?.browse()"
|
() => {
|
||||||
|
customerFormState.imageDialog = true;
|
||||||
|
customerFormState.isImageEdit = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@edit="
|
||||||
|
customerFormState.imageDialog = customerFormState.isImageEdit = true
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
@ -1804,7 +1837,7 @@ const emptyCreateDialog = ref(false);
|
||||||
<q-form
|
<q-form
|
||||||
@submit.prevent="
|
@submit.prevent="
|
||||||
async () => {
|
async () => {
|
||||||
await customerFormStore.submitFormCustomer();
|
await customerFormStore.submitFormCustomer(onCreateImageList);
|
||||||
customerFormState.readonly = true;
|
customerFormState.readonly = true;
|
||||||
notify('create', $t('general.success'));
|
notify('create', $t('general.success'));
|
||||||
await fetchListCustomer();
|
await fetchListCustomer();
|
||||||
|
|
@ -2629,18 +2662,69 @@ const emptyCreateDialog = ref(false);
|
||||||
v-model:dialog-state="customerFormState.imageDialog"
|
v-model:dialog-state="customerFormState.imageDialog"
|
||||||
v-model:file="customerFormData.image"
|
v-model:file="customerFormData.image"
|
||||||
v-model:image-url="customerFormState.customerImageUrl"
|
v-model:image-url="customerFormState.customerImageUrl"
|
||||||
|
v-model:data-list="imageList"
|
||||||
|
v-model:on-create-data-list="onCreateImageList"
|
||||||
|
:on-create="customerFormState.dialogModal"
|
||||||
:default-url="customerFormState.defaultCustomerImageUrl"
|
:default-url="customerFormState.defaultCustomerImageUrl"
|
||||||
clear-button
|
:hiddenFooter="!customerFormState.isImageEdit"
|
||||||
@save="
|
@add-image="
|
||||||
async (v) => {
|
async (v) => {
|
||||||
if (v && customerFormState.editCustomerId) {
|
if (!v) return;
|
||||||
await customerStore.setImage(customerFormState.editCustomerId, v);
|
if (!customerFormState.editCustomerId) return;
|
||||||
await fetchListCustomer();
|
await customerStore.addImageList(
|
||||||
|
v,
|
||||||
|
customerFormState.editCustomerId,
|
||||||
|
Date.now(),
|
||||||
|
);
|
||||||
|
await fetchImageList(
|
||||||
|
customerFormState.editCustomerId,
|
||||||
|
customerFormData.selectedImage || '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@remove-image="
|
||||||
|
async (v) => {
|
||||||
|
if (!v) return;
|
||||||
|
if (!customerFormState.editCustomerId) return;
|
||||||
|
const name = v.split('/').pop() || '';
|
||||||
|
await customerStore.deleteImageByName(
|
||||||
|
customerFormState.editCustomerId,
|
||||||
|
name,
|
||||||
|
);
|
||||||
|
await fetchImageList(customerFormState.editCustomerId, name);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@submit="
|
||||||
|
async (v) => {
|
||||||
|
if (customerFormState.dialogModal) {
|
||||||
|
customerFormState.customerImageUrl = v;
|
||||||
customerFormState.imageDialog = false;
|
customerFormState.imageDialog = false;
|
||||||
|
} else {
|
||||||
|
refreshImageState = true;
|
||||||
|
customerFormData.selectedImage = v;
|
||||||
|
imageList ? (imageList.selectedImage = v) : '';
|
||||||
|
customerFormState.customerImageUrl = `${baseUrl}/customer/${customerFormState.editCustomerId && customerFormState.editCustomerId}/image/${v}`;
|
||||||
|
customerFormStore.resetForm();
|
||||||
|
await customerFormStore.submitFormCustomer();
|
||||||
|
customerFormState.imageDialog = false;
|
||||||
|
refreshImageState = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
<template #title>
|
||||||
|
<span
|
||||||
|
v-if="!customerFormState.dialogModal"
|
||||||
|
class="justify-center flex text-bold"
|
||||||
|
>
|
||||||
|
{{ $t('general.image') }}
|
||||||
|
{{
|
||||||
|
$i18n.locale === 'eng'
|
||||||
|
? `${customerFormData.firstNameEN} ${customerFormData.lastNameEN}`
|
||||||
|
: `${customerFormData.firstName} ${customerFormData.lastName}`
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
<template #error>
|
<template #error>
|
||||||
<div class="full-height full-width" style="background: white">
|
<div class="full-height full-width" style="background: white">
|
||||||
<div
|
<div
|
||||||
|
|
@ -2663,7 +2747,7 @@ const emptyCreateDialog = ref(false);
|
||||||
class="full-width full-height column items-center justify-center"
|
class="full-width full-height column items-center justify-center"
|
||||||
>
|
>
|
||||||
<q-icon
|
<q-icon
|
||||||
size="7vw"
|
size="3rem"
|
||||||
:name="
|
:name="
|
||||||
customerFormData.customerType === 'PERS'
|
customerFormData.customerType === 'PERS'
|
||||||
? 'mdi-account-plus-outline'
|
? 'mdi-account-plus-outline'
|
||||||
|
|
@ -2766,8 +2850,9 @@ const emptyCreateDialog = ref(false);
|
||||||
hide-fade
|
hide-fade
|
||||||
:fallback-cover="`/images/customer-${customerFormData.customerType}-banner-bg.jpg`"
|
:fallback-cover="`/images/customer-${customerFormData.customerType}-banner-bg.jpg`"
|
||||||
:img="
|
:img="
|
||||||
customerFormState.customerImageUrl ||
|
`${baseUrl}/customer/${customerFormState.editCustomerId}/image/${customerFormData.selectedImage}`.concat(
|
||||||
`/images/customer-${customerFormData.customerType}-avartar-${customerFormData.gender}.png`
|
refreshImageState ? `?ts=${Date.now()}` : '',
|
||||||
|
) || null
|
||||||
"
|
"
|
||||||
:fallbackImg="`/images/customer-${customerFormData.customerType}-avartar-${customerFormData.gender}.png`"
|
:fallbackImg="`/images/customer-${customerFormData.customerType}-avartar-${customerFormData.gender}.png`"
|
||||||
:color="`hsla(var(--${customerFormData.customerType === 'PERS' ? 'teal-10-hsl' : 'violet-11-hsl'})/1)`"
|
:color="`hsla(var(--${customerFormData.customerType === 'PERS' ? 'teal-10-hsl' : 'violet-11-hsl'})/1)`"
|
||||||
|
|
@ -2777,8 +2862,15 @@ const emptyCreateDialog = ref(false);
|
||||||
? 'mdi-account-plus-outline'
|
? 'mdi-account-plus-outline'
|
||||||
: 'mdi-office-building-outline'
|
: 'mdi-office-building-outline'
|
||||||
"
|
"
|
||||||
@view="customerFormState.imageDialog = true"
|
@view="
|
||||||
@edit="dialogCustomerImageUpload?.browse()"
|
() => {
|
||||||
|
customerFormState.imageDialog = true;
|
||||||
|
customerFormState.isImageEdit = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@edit="
|
||||||
|
customerFormState.imageDialog = customerFormState.isImageEdit = true
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
registeredBranchId: branchStore.currentMyBranch?.id || '',
|
registeredBranchId: branchStore.currentMyBranch?.id || '',
|
||||||
customerBranch: [],
|
customerBranch: [],
|
||||||
image: null,
|
image: null,
|
||||||
|
selectedImage: '',
|
||||||
};
|
};
|
||||||
let resetFormData = structuredClone(defaultFormData);
|
let resetFormData = structuredClone(defaultFormData);
|
||||||
|
|
||||||
|
|
@ -50,6 +51,7 @@ export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
editCustomerBranchId?: string;
|
editCustomerBranchId?: string;
|
||||||
treeFile: { label: string; file: { label: string }[] }[];
|
treeFile: { label: string; file: { label: string }[] }[];
|
||||||
formDataOcr: Record<string, any>;
|
formDataOcr: Record<string, any>;
|
||||||
|
isImageEdit: boolean;
|
||||||
}>({
|
}>({
|
||||||
dialogType: 'info',
|
dialogType: 'info',
|
||||||
dialogOpen: false,
|
dialogOpen: false,
|
||||||
|
|
@ -65,6 +67,7 @@ export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
defaultCustomerImageUrl: '',
|
defaultCustomerImageUrl: '',
|
||||||
treeFile: [],
|
treeFile: [],
|
||||||
formDataOcr: {},
|
formDataOcr: {},
|
||||||
|
isImageEdit: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
@ -110,8 +113,9 @@ export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
if (state.value.dialogType === 'create') {
|
if (state.value.dialogType === 'create') {
|
||||||
state.value.editCustomerId = '';
|
state.value.editCustomerId = '';
|
||||||
}
|
}
|
||||||
|
const currentImg = currentFormData.value.selectedImage;
|
||||||
currentFormData.value = structuredClone(resetFormData);
|
currentFormData.value = structuredClone(resetFormData);
|
||||||
|
currentFormData.value.selectedImage = currentImg;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function assignFormData(id?: string) {
|
async function assignFormData(id?: string) {
|
||||||
|
|
@ -129,8 +133,8 @@ export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
state.value.dialogType = 'edit';
|
state.value.dialogType = 'edit';
|
||||||
state.value.editCustomerId = id;
|
state.value.editCustomerId = id;
|
||||||
state.value.editCustomerCode = data.code;
|
state.value.editCustomerCode = data.code;
|
||||||
state.value.customerImageUrl = `${apiBaseUrl}/customer/${id}/image`;
|
state.value.customerImageUrl = `${apiBaseUrl}/customer/${id}/image/${data.selectedImage}`;
|
||||||
state.value.defaultCustomerImageUrl = `${apiBaseUrl}/customer/${id}/image`;
|
state.value.defaultCustomerImageUrl = `${apiBaseUrl}/customer/${id}/image/${data.selectedImage}`;
|
||||||
|
|
||||||
resetFormData.registeredBranchId = data.registeredBranchId;
|
resetFormData.registeredBranchId = data.registeredBranchId;
|
||||||
resetFormData.code = data.code || '';
|
resetFormData.code = data.code || '';
|
||||||
|
|
@ -144,6 +148,7 @@ export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
resetFormData.gender = data.gender;
|
resetFormData.gender = data.gender;
|
||||||
resetFormData.birthDate = new Date(data.birthDate);
|
resetFormData.birthDate = new Date(data.birthDate);
|
||||||
resetFormData.image = null;
|
resetFormData.image = null;
|
||||||
|
resetFormData.selectedImage = data.selectedImage;
|
||||||
|
|
||||||
resetFormData.customerBranch = await Promise.all(
|
resetFormData.customerBranch = await Promise.all(
|
||||||
data.branch.map(async (v) => ({
|
data.branch.map(async (v) => ({
|
||||||
|
|
@ -259,11 +264,14 @@ export const useCustomerForm = defineStore('form-customer', () => {
|
||||||
(currentFormData.value.customerBranch?.length || 0) - 1;
|
(currentFormData.value.customerBranch?.length || 0) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submitFormCustomer() {
|
async function submitFormCustomer(imgList?: {
|
||||||
|
selectedImage: string;
|
||||||
|
list: { url: string; imgFile: File | null; name: string }[];
|
||||||
|
}) {
|
||||||
if (state.value.dialogType === 'info') return;
|
if (state.value.dialogType === 'info') return;
|
||||||
|
|
||||||
if (state.value.dialogType === 'create') {
|
if (state.value.dialogType === 'create') {
|
||||||
const _data = await customerStore.create(currentFormData.value);
|
const _data = await customerStore.create(currentFormData.value, imgList);
|
||||||
|
|
||||||
if (_data) await assignFormData(_data.id);
|
if (_data) await assignFormData(_data.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,15 +87,80 @@ const useBranchStore = defineStore('api-branch', () => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function create(branch: BranchCreate, bank?: BankBook[]) {
|
async function fetchImageListById(
|
||||||
const { qrCodeImage, imageUrl, zipCode, ...payload } = branch;
|
id: string,
|
||||||
|
flow?: {
|
||||||
|
sessionId?: string;
|
||||||
|
refTransactionId?: string;
|
||||||
|
transactionId?: string;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const res = await api.get(`/branch/${id}/image`, {
|
||||||
|
headers: {
|
||||||
|
'X-Session-Id': flow?.sessionId,
|
||||||
|
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
||||||
|
'X-Tid': flow?.transactionId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res) return false;
|
||||||
|
if (res.status === 200) return res.data;
|
||||||
|
if (res.status === 204) return null;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addImageList(file: File, branchId: string, name: string) {
|
||||||
|
await api
|
||||||
|
.put(`/branch/${branchId}/image/${name}`, file, {
|
||||||
|
headers: { 'Content-Type': file.type },
|
||||||
|
onUploadProgress: (e) => console.log(e),
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteImageByName(
|
||||||
|
id: string,
|
||||||
|
name: string,
|
||||||
|
flow?: {
|
||||||
|
sessionId?: string;
|
||||||
|
refTransactionId?: string;
|
||||||
|
transactionId?: string;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const res = await api.delete(`/branch/${id}/image/${name}`, {
|
||||||
|
headers: {
|
||||||
|
'X-Session-Id': flow?.sessionId,
|
||||||
|
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
||||||
|
'X-Tid': flow?.transactionId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function create(
|
||||||
|
branch: BranchCreate,
|
||||||
|
bank?: BankBook[],
|
||||||
|
imgList?: {
|
||||||
|
selectedImage: string;
|
||||||
|
list: { url: string; imgFile: File | null; name: string }[];
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const { qrCodeImage, zipCode, ...payload } = branch;
|
||||||
const bankPayload = bank?.map(({ bankUrl, bankQr, ...rest }) => ({
|
const bankPayload = bank?.map(({ bankUrl, bankQr, ...rest }) => ({
|
||||||
...rest,
|
...rest,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const res = await api.post<Branch>(
|
const res = await api.post<Branch>(
|
||||||
'/branch',
|
'/branch',
|
||||||
{ ...payload, bank: bankPayload },
|
{
|
||||||
|
...payload,
|
||||||
|
selectedImage: (imgList && imgList.selectedImage) || '',
|
||||||
|
bank: bankPayload,
|
||||||
|
},
|
||||||
{ headers: { 'X-Rtid': flowStore.rtid } },
|
{ headers: { 'X-Rtid': flowStore.rtid } },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -108,15 +173,6 @@ const useBranchStore = defineStore('api-branch', () => {
|
||||||
.catch((e) => console.error(e));
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imageUrl) {
|
|
||||||
await api
|
|
||||||
.put(`/branch/${res.data.id}/branch-image`, imageUrl, {
|
|
||||||
headers: { 'Content-Type': imageUrl.type },
|
|
||||||
onUploadProgress: (e) => console.log(e),
|
|
||||||
})
|
|
||||||
.catch((e) => console.error(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.data.bank && bank) {
|
if (res.data.bank && bank) {
|
||||||
for (let i = 0; i < bank?.length; i++) {
|
for (let i = 0; i < bank?.length; i++) {
|
||||||
if (bank[i].bankQr) {
|
if (bank[i].bankQr) {
|
||||||
|
|
@ -134,6 +190,14 @@ const useBranchStore = defineStore('api-branch', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (imgList && imgList.list.length > 0 && res.data.id) {
|
||||||
|
for (let index = 0; index < imgList.list.length; index++) {
|
||||||
|
const imgFile = imgList.list[index].imgFile;
|
||||||
|
if (imgFile)
|
||||||
|
await addImageList(imgFile, res.data.id, imgList.list[index].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
|
|
@ -143,7 +207,6 @@ const useBranchStore = defineStore('api-branch', () => {
|
||||||
id: string,
|
id: string,
|
||||||
data: Partial<BranchCreate & { status: 'ACTIVE' | 'INACTIVE' | 'CREATED' }>,
|
data: Partial<BranchCreate & { status: 'ACTIVE' | 'INACTIVE' | 'CREATED' }>,
|
||||||
qrCodeImage?: File | undefined,
|
qrCodeImage?: File | undefined,
|
||||||
imageHq?: File | undefined,
|
|
||||||
bank?: BankBook[],
|
bank?: BankBook[],
|
||||||
opts?: {
|
opts?: {
|
||||||
deleteQrCodeImage?: boolean;
|
deleteQrCodeImage?: boolean;
|
||||||
|
|
@ -178,15 +241,6 @@ const useBranchStore = defineStore('api-branch', () => {
|
||||||
.catch((e) => console.error(e));
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imageHq) {
|
|
||||||
await api
|
|
||||||
.put(`/branch/${res.data.id}/branch-image`, imageHq, {
|
|
||||||
headers: { 'Content-Type': imageHq.type },
|
|
||||||
onUploadProgress: (e) => console.log(e),
|
|
||||||
})
|
|
||||||
.catch((e) => console.error(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!!res.data.bank && !!bank) {
|
if (!!res.data.bank && !!bank) {
|
||||||
for (let i = 0; i < bank?.length; i++) {
|
for (let i = 0; i < bank?.length; i++) {
|
||||||
if (bank?.[i].bankQr) {
|
if (bank?.[i].bankQr) {
|
||||||
|
|
@ -339,6 +393,10 @@ const useBranchStore = defineStore('api-branch', () => {
|
||||||
fetchList,
|
fetchList,
|
||||||
fetchById,
|
fetchById,
|
||||||
|
|
||||||
|
fetchImageListById,
|
||||||
|
addImageList,
|
||||||
|
deleteImageByName,
|
||||||
|
|
||||||
create,
|
create,
|
||||||
editById,
|
editById,
|
||||||
deleteById,
|
deleteById,
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ export type BankBook = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Branch = {
|
export type Branch = {
|
||||||
|
selectedImage?: string;
|
||||||
subDistrict: SubDistrict | null;
|
subDistrict: SubDistrict | null;
|
||||||
district: District | null;
|
district: District | null;
|
||||||
province: Province | null;
|
province: Province | null;
|
||||||
|
|
@ -30,7 +31,6 @@ export type Branch = {
|
||||||
latitude: string;
|
latitude: string;
|
||||||
contactName: string;
|
contactName: string;
|
||||||
qrCodeImageUrl: string;
|
qrCodeImageUrl: string;
|
||||||
imageUrl: string;
|
|
||||||
email: string;
|
email: string;
|
||||||
zipCode: string;
|
zipCode: string;
|
||||||
subDistrictId: string | null;
|
subDistrictId: string | null;
|
||||||
|
|
@ -57,6 +57,7 @@ export type Branch = {
|
||||||
export type BranchWithChildren = Branch & { branch: Branch[] };
|
export type BranchWithChildren = Branch & { branch: Branch[] };
|
||||||
|
|
||||||
export type BranchCreate = {
|
export type BranchCreate = {
|
||||||
|
selectedImage?: string;
|
||||||
code?: string;
|
code?: string;
|
||||||
taxNo: string;
|
taxNo: string;
|
||||||
nameEN: string;
|
nameEN: string;
|
||||||
|
|
@ -76,7 +77,6 @@ export type BranchCreate = {
|
||||||
contactName: string;
|
contactName: string;
|
||||||
contact: string;
|
contact: string;
|
||||||
qrCodeImage?: File;
|
qrCodeImage?: File;
|
||||||
imageUrl?: File;
|
|
||||||
lineId: string;
|
lineId: string;
|
||||||
webUrl?: string;
|
webUrl?: string;
|
||||||
virtual: boolean;
|
virtual: boolean;
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,7 @@ const useCustomerStore = defineStore('api-customer', () => {
|
||||||
fetch(res.data)
|
fetch(res.data)
|
||||||
.then(async (res) => await res.blob())
|
.then(async (res) => await res.blob())
|
||||||
.then((blob) => {
|
.then((blob) => {
|
||||||
let a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
a.download = filename;
|
a.download = filename;
|
||||||
a.href = window.URL.createObjectURL(blob);
|
a.href = window.URL.createObjectURL(blob);
|
||||||
a.click();
|
a.click();
|
||||||
|
|
@ -267,8 +267,66 @@ const useCustomerStore = defineStore('api-customer', () => {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchImageListById(
|
||||||
|
id: string,
|
||||||
|
flow?: {
|
||||||
|
sessionId?: string;
|
||||||
|
refTransactionId?: string;
|
||||||
|
transactionId?: string;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const res = await api.get(`/customer/${id}/image`, {
|
||||||
|
headers: {
|
||||||
|
'X-Session-Id': flow?.sessionId,
|
||||||
|
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
||||||
|
'X-Tid': flow?.transactionId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res) return false;
|
||||||
|
if (res.status === 200) return res.data;
|
||||||
|
if (res.status === 204) return null;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addImageList(file: File, customerId: string, name: string) {
|
||||||
|
await api
|
||||||
|
.put(`/customer/${customerId}/image/${name}`, file, {
|
||||||
|
headers: { 'Content-Type': file.type },
|
||||||
|
onUploadProgress: (e) => console.log(e),
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteImageByName(
|
||||||
|
id: string,
|
||||||
|
name: string,
|
||||||
|
flow?: {
|
||||||
|
sessionId?: string;
|
||||||
|
refTransactionId?: string;
|
||||||
|
transactionId?: string;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const res = await api.delete(`/customer/${id}/image/${name}`, {
|
||||||
|
headers: {
|
||||||
|
'X-Session-Id': flow?.sessionId,
|
||||||
|
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
||||||
|
'X-Tid': flow?.transactionId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res) return false;
|
||||||
|
}
|
||||||
|
|
||||||
async function create(
|
async function create(
|
||||||
data: CustomerCreate,
|
data: CustomerCreate,
|
||||||
|
imgList: {
|
||||||
|
selectedImage: string;
|
||||||
|
list: { url: string; imgFile: File | null; name: string }[];
|
||||||
|
},
|
||||||
flow?: {
|
flow?: {
|
||||||
sessionId?: string;
|
sessionId?: string;
|
||||||
refTransactionId?: string;
|
refTransactionId?: string;
|
||||||
|
|
@ -291,13 +349,17 @@ const useCustomerStore = defineStore('api-customer', () => {
|
||||||
imageUrl: string;
|
imageUrl: string;
|
||||||
imageUploadUrl: string;
|
imageUploadUrl: string;
|
||||||
}
|
}
|
||||||
>('/customer', payload, {
|
>(
|
||||||
headers: {
|
'/customer',
|
||||||
'X-Session-Id': flow?.sessionId,
|
{ ...payload, selectedImage: imgList.selectedImage },
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
{
|
||||||
'X-Tid': flow?.transactionId,
|
headers: {
|
||||||
|
'X-Session-Id': flow?.sessionId,
|
||||||
|
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
||||||
|
'X-Tid': flow?.transactionId,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
);
|
||||||
|
|
||||||
// await Promise.allSettled([
|
// await Promise.allSettled([
|
||||||
// ...res.data.branch.map(async (v, i) => {
|
// ...res.data.branch.map(async (v, i) => {
|
||||||
|
|
@ -305,15 +367,23 @@ const useCustomerStore = defineStore('api-customer', () => {
|
||||||
// if (fileList)
|
// if (fileList)
|
||||||
// return await addBranchAttachment(v.id, { file: fileList });
|
// return await addBranchAttachment(v.id, { file: fileList });
|
||||||
// }),
|
// }),
|
||||||
image &&
|
// image &&
|
||||||
(await api
|
// (await api
|
||||||
.put(`/customer/${res.data.id}/image`, image, {
|
// .put(`/customer/${res.data.id}/image`, image, {
|
||||||
headers: { 'Content-Type': image?.type },
|
// 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 (imgList.list.length > 0 && res.data.id) {
|
||||||
|
for (let index = 0; index < imgList.list.length; index++) {
|
||||||
|
const imgFile = imgList.list[index].imgFile;
|
||||||
|
if (imgFile)
|
||||||
|
await addImageList(imgFile, res.data.id, imgList.list[index].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
|
|
@ -362,13 +432,13 @@ const useCustomerStore = defineStore('api-customer', () => {
|
||||||
// if (fileList)
|
// if (fileList)
|
||||||
// return await addBranchAttachment(v.id, { file: fileList });
|
// return await addBranchAttachment(v.id, { file: fileList });
|
||||||
// }),
|
// }),
|
||||||
image &&
|
// image &&
|
||||||
(await axios
|
// (await axios
|
||||||
.put(res.data.imageUploadUrl, image, {
|
// .put(res.data.imageUploadUrl, image, {
|
||||||
headers: { 'Content-Type': image.type },
|
// 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 (!res) return false;
|
if (!res) return false;
|
||||||
|
|
@ -563,6 +633,11 @@ const useCustomerStore = defineStore('api-customer', () => {
|
||||||
fetchListCustomeBranch,
|
fetchListCustomeBranch,
|
||||||
fetchById,
|
fetchById,
|
||||||
fetchList,
|
fetchList,
|
||||||
|
|
||||||
|
fetchImageListById,
|
||||||
|
addImageList,
|
||||||
|
deleteImageByName,
|
||||||
|
|
||||||
create,
|
create,
|
||||||
editById,
|
editById,
|
||||||
deleteById,
|
deleteById,
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,7 @@ export type CustomerBranchCreate = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CustomerCreate = {
|
export type CustomerCreate = {
|
||||||
|
selectedImage?: string;
|
||||||
code: string;
|
code: string;
|
||||||
customerBranch?: (CustomerBranchCreate & { id?: string })[];
|
customerBranch?: (CustomerBranchCreate & { id?: string })[];
|
||||||
customerType: CustomerType;
|
customerType: CustomerType;
|
||||||
|
|
@ -166,6 +167,7 @@ export type CustomerCreate = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CustomerUpdate = {
|
export type CustomerUpdate = {
|
||||||
|
selectedImage?: string;
|
||||||
status?: Status;
|
status?: Status;
|
||||||
customerType?: CustomerType;
|
customerType?: CustomerType;
|
||||||
customerBranch?: (CustomerBranchCreate & { id?: string })[];
|
customerBranch?: (CustomerBranchCreate & { id?: string })[];
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { ref } from 'vue';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { Pagination, Status } from '../types';
|
import { Pagination, Status } from '../types';
|
||||||
import { api } from 'src/boot/axios';
|
import { api } from 'src/boot/axios';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
RoleData,
|
RoleData,
|
||||||
User,
|
User,
|
||||||
|
|
@ -266,18 +267,83 @@ const useUserStore = defineStore('api-user', () => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function create(
|
async function fetchImageListById(
|
||||||
data: UserCreate,
|
id: string,
|
||||||
flow?: {
|
flow?: {
|
||||||
sessionId?: string;
|
sessionId?: string;
|
||||||
refTransactionId?: string;
|
refTransactionId?: string;
|
||||||
transactionId?: string;
|
transactionId?: string;
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
|
<<<<<<< HEAD
|
||||||
const { profileImage, zipCode, ...payload } = data;
|
const { profileImage, zipCode, ...payload } = data;
|
||||||
const res = await api.post<User & { profileImageUploadUrl: string }>(
|
const res = await api.post<User & { profileImageUploadUrl: string }>(
|
||||||
|
=======
|
||||||
|
const res = await api.get(`/user/${id}/profile-image`, {
|
||||||
|
headers: {
|
||||||
|
'X-Session-Id': flow?.sessionId,
|
||||||
|
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
||||||
|
'X-Tid': flow?.transactionId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res) return false;
|
||||||
|
if (res.status === 200) return res.data;
|
||||||
|
if (res.status === 204) return null;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addImageList(file: File, userId: string, name: string) {
|
||||||
|
await api
|
||||||
|
.put(`/user/${userId}/profile-image/${name}`, file, {
|
||||||
|
headers: { 'Content-Type': file.type },
|
||||||
|
onUploadProgress: (e) => console.log(e),
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteImageByName(
|
||||||
|
id: string,
|
||||||
|
name: string,
|
||||||
|
flow?: {
|
||||||
|
sessionId?: string;
|
||||||
|
refTransactionId?: string;
|
||||||
|
transactionId?: string;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const res = await api.delete(`/user/${id}/profile-image/${name}`, {
|
||||||
|
headers: {
|
||||||
|
'X-Session-Id': flow?.sessionId,
|
||||||
|
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
||||||
|
'X-Tid': flow?.transactionId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function create(
|
||||||
|
data: UserCreate,
|
||||||
|
imgList: {
|
||||||
|
selectedImage: string;
|
||||||
|
list: { url: string; imgFile: File | null; name: string }[];
|
||||||
|
},
|
||||||
|
flow?: {
|
||||||
|
sessionId?: string;
|
||||||
|
refTransactionId?: string;
|
||||||
|
transactionId?: string;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const { zipCode, ...payload } = data;
|
||||||
|
const res = await api.post<User & { profileImageUploadUrl: string }>(
|
||||||
'/user',
|
'/user',
|
||||||
payload,
|
{
|
||||||
|
...payload,
|
||||||
|
selectedImage: imgList.selectedImage || '',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
'X-Session-Id': flow?.sessionId,
|
'X-Session-Id': flow?.sessionId,
|
||||||
|
|
@ -287,13 +353,12 @@ const useUserStore = defineStore('api-user', () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (profileImage && res.data.id) {
|
if (imgList.list.length > 0 && res.data.id) {
|
||||||
await api
|
for (let index = 0; index < imgList.list.length; index++) {
|
||||||
.put(`/user/${res.data.id}/image`, profileImage, {
|
const imgFile = imgList.list[index].imgFile;
|
||||||
headers: { 'Content-Type': profileImage.type },
|
if (imgFile)
|
||||||
onUploadProgress: (e) => console.log(e),
|
await addImageList(imgFile, res.data.id, imgList.list[index].name);
|
||||||
})
|
}
|
||||||
.catch((e) => console.error(e));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
@ -310,26 +375,13 @@ const useUserStore = defineStore('api-user', () => {
|
||||||
transactionId?: string;
|
transactionId?: string;
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
const { profileImage, ...payload } = data;
|
const res = await api.put<User>(`/user/${id}`, data, {
|
||||||
const res = await api.put<User & { profileImageUploadUrl: string }>(
|
headers: {
|
||||||
`/user/${id}`,
|
'X-Session-Id': flow?.sessionId,
|
||||||
payload,
|
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
||||||
{
|
'X-Tid': flow?.transactionId,
|
||||||
headers: {
|
|
||||||
'X-Session-Id': flow?.sessionId,
|
|
||||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
|
||||||
'X-Tid': flow?.transactionId,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
});
|
||||||
|
|
||||||
if (profileImage)
|
|
||||||
await axios
|
|
||||||
.put(res.data.profileImageUploadUrl, profileImage, {
|
|
||||||
headers: { 'Content-Type': profileImage.type },
|
|
||||||
onUploadProgress: (e) => console.log(e),
|
|
||||||
})
|
|
||||||
.catch((e) => console.error(e));
|
|
||||||
|
|
||||||
if (!res) return false;
|
if (!res) return false;
|
||||||
|
|
||||||
|
|
@ -460,6 +512,10 @@ const useUserStore = defineStore('api-user', () => {
|
||||||
fetchList,
|
fetchList,
|
||||||
fetchById,
|
fetchById,
|
||||||
|
|
||||||
|
fetchImageListById,
|
||||||
|
addImageList,
|
||||||
|
deleteImageByName,
|
||||||
|
|
||||||
create,
|
create,
|
||||||
editById,
|
editById,
|
||||||
deleteById,
|
deleteById,
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { Branch } from '../branch/types';
|
||||||
import { Status } from '../types';
|
import { Status } from '../types';
|
||||||
|
|
||||||
export type User = {
|
export type User = {
|
||||||
|
selectedImage?: string;
|
||||||
subDistrict: SubDistrict | null;
|
subDistrict: SubDistrict | null;
|
||||||
district: District | null;
|
district: District | null;
|
||||||
province: Province | null;
|
province: Province | null;
|
||||||
|
|
@ -41,7 +42,6 @@ export type User = {
|
||||||
firstName: string;
|
firstName: string;
|
||||||
namePrefix?: string | null;
|
namePrefix?: string | null;
|
||||||
id: string;
|
id: string;
|
||||||
profileImageUrl: string;
|
|
||||||
code: string;
|
code: string;
|
||||||
birthDate?: Date | null;
|
birthDate?: Date | null;
|
||||||
responsibleArea: string;
|
responsibleArea: string;
|
||||||
|
|
@ -51,6 +51,7 @@ export type User = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserCreate = {
|
export type UserCreate = {
|
||||||
|
selectedImage?: string;
|
||||||
branchId: string;
|
branchId: string;
|
||||||
provinceId?: string | null;
|
provinceId?: string | null;
|
||||||
districtId?: string | null;
|
districtId?: string | null;
|
||||||
|
|
@ -82,7 +83,6 @@ export type UserCreate = {
|
||||||
userType: string;
|
userType: string;
|
||||||
username: string;
|
username: string;
|
||||||
status?: Status;
|
status?: Status;
|
||||||
profileImage?: File | null; // required but not strict
|
|
||||||
birthDate?: Date | null;
|
birthDate?: Date | null;
|
||||||
responsibleArea?: string | null;
|
responsibleArea?: string | null;
|
||||||
checkpoint?: string | null;
|
checkpoint?: string | null;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue