feat: agencies => image upload (#67)
This commit is contained in:
parent
86a3247732
commit
4e622153ac
4 changed files with 346 additions and 50 deletions
|
|
@ -1,39 +1,70 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import DialogForm from 'src/components/DialogForm.vue';
|
import { reactive, ref, watch } from 'vue';
|
||||||
|
import { InstitutionPayload } from 'src/stores/institution/types';
|
||||||
|
import { Icon } from '@iconify/vue/dist/iconify.js';
|
||||||
|
|
||||||
|
import { useInstitution } from 'src/stores/institution';
|
||||||
|
import { baseUrl } from 'src/stores/utils';
|
||||||
|
|
||||||
import DrawerInfo from 'src/components/DrawerInfo.vue';
|
import DrawerInfo from 'src/components/DrawerInfo.vue';
|
||||||
|
import DialogForm from 'src/components/DialogForm.vue';
|
||||||
import ProfileBanner from 'src/components/ProfileBanner.vue';
|
import ProfileBanner from 'src/components/ProfileBanner.vue';
|
||||||
import SideMenu from 'src/components/SideMenu.vue';
|
import SideMenu from 'src/components/SideMenu.vue';
|
||||||
import FormBasicInfoAgencies from 'src/components/07_agencies-management/FormBasicInfoAgencies.vue';
|
import FormBasicInfoAgencies from 'src/components/07_agencies-management/FormBasicInfoAgencies.vue';
|
||||||
import AddressForm from 'src/components/form/AddressForm.vue';
|
|
||||||
import {
|
import {
|
||||||
UndoButton,
|
UndoButton,
|
||||||
SaveButton,
|
SaveButton,
|
||||||
EditButton,
|
EditButton,
|
||||||
DeleteButton,
|
DeleteButton,
|
||||||
} from 'src/components/button';
|
} from 'src/components/button';
|
||||||
import { InstitutionPayload } from 'src/stores/institution/types';
|
import AddressForm from 'src/components/form/AddressForm.vue';
|
||||||
|
import ImageUploadDialog from 'src/components/ImageUploadDialog.vue';
|
||||||
|
|
||||||
|
const institutionStore = useInstitution();
|
||||||
|
|
||||||
const model = defineModel<boolean>({ required: true, default: false });
|
const model = defineModel<boolean>({ required: true, default: false });
|
||||||
const drawerModel = defineModel<boolean>('drawerModel', {
|
const drawerModel = defineModel<boolean>('drawerModel', {
|
||||||
required: true,
|
required: true,
|
||||||
default: false,
|
default: false,
|
||||||
});
|
});
|
||||||
|
const onCreateImageList = defineModel<{
|
||||||
|
selectedImage: string;
|
||||||
|
list: { url: string; imgFile: File | null; name: string }[];
|
||||||
|
}>('onCreateImageList', { default: { selectedImage: '', list: [] } });
|
||||||
|
|
||||||
withDefaults(
|
const imageState = reactive({
|
||||||
|
imageDialog: false,
|
||||||
|
isImageEdit: false,
|
||||||
|
refreshImageState: false,
|
||||||
|
|
||||||
|
imageUrl: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const imageFile = ref<File | null>(null);
|
||||||
|
const imageList = ref<{ selectedImage: string; list: string[] }>();
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
isEdit?: boolean;
|
isEdit?: boolean;
|
||||||
|
|
||||||
|
dataId?: string;
|
||||||
}>(),
|
}>(),
|
||||||
{ readonly: false, isEdit: false },
|
{ readonly: false, isEdit: false, dataId: '' },
|
||||||
);
|
);
|
||||||
|
|
||||||
defineEmits<{
|
defineExpose({ clearImageState });
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
(e: 'submit'): void;
|
(e: 'submit'): void;
|
||||||
(e: 'close'): void;
|
(e: 'close'): void;
|
||||||
(e: 'changeStatus'): void;
|
(e: 'changeStatus'): void;
|
||||||
(e: 'drawerUndo'): void;
|
(e: 'drawerUndo'): void;
|
||||||
(e: 'drawerEdit'): void;
|
(e: 'drawerEdit'): void;
|
||||||
(e: 'drawerDelete'): void;
|
(e: 'drawerDelete'): void;
|
||||||
|
(e: 'addImage'): void;
|
||||||
|
(e: 'removeImage'): void;
|
||||||
|
(e: 'submitImage', name: string): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const data = defineModel<InstitutionPayload>('data', {
|
const data = defineModel<InstitutionPayload>('data', {
|
||||||
|
|
@ -54,8 +85,96 @@ const data = defineModel<InstitutionPayload>('data', {
|
||||||
subDistrictId: '',
|
subDistrictId: '',
|
||||||
districtId: '',
|
districtId: '',
|
||||||
provinceId: '',
|
provinceId: '',
|
||||||
|
selectedImage: '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function viewImage() {
|
||||||
|
imageState.imageDialog = true;
|
||||||
|
imageState.isImageEdit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function editImage() {
|
||||||
|
imageState.imageDialog = imageState.isImageEdit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchImageList(id: string, selectedName: string) {
|
||||||
|
const res = await institutionStore.fetchImageListById(id);
|
||||||
|
imageList.value = {
|
||||||
|
selectedImage: selectedName,
|
||||||
|
list: res.map((n: string) => `institution/${id}/image/${n}`),
|
||||||
|
};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addImage(file: File | null) {
|
||||||
|
if (!file) return;
|
||||||
|
if (!props.dataId) return;
|
||||||
|
|
||||||
|
await institutionStore.addImageList(
|
||||||
|
file,
|
||||||
|
props.dataId,
|
||||||
|
Date.now().toString(),
|
||||||
|
);
|
||||||
|
await fetchImageList(props.dataId, data.value.selectedImage || '');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeImage(name: string) {
|
||||||
|
if (!name) return;
|
||||||
|
if (!props.dataId) return;
|
||||||
|
|
||||||
|
const targetName = name.split('/').pop() || '';
|
||||||
|
await institutionStore.deleteImageByName(props.dataId, targetName);
|
||||||
|
await fetchImageList(props.dataId, data.value.selectedImage || '');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitImage(name: string) {
|
||||||
|
if (model.value) {
|
||||||
|
imageState.imageUrl = name;
|
||||||
|
imageState.imageDialog = false;
|
||||||
|
} else {
|
||||||
|
imageState.refreshImageState = true;
|
||||||
|
emit('submitImage', name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearImageState() {
|
||||||
|
imageState.imageDialog = false;
|
||||||
|
imageFile.value = null;
|
||||||
|
onCreateImageList.value = { selectedImage: '', list: [] };
|
||||||
|
imageState.refreshImageState = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => imageFile.value,
|
||||||
|
() => {
|
||||||
|
if (imageFile.value !== null) imageState.isImageEdit = true;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => data.value.selectedImage,
|
||||||
|
() => {
|
||||||
|
imageState.imageUrl = `${baseUrl}/institution/${props.dataId}/image/${data.value.selectedImage}`;
|
||||||
|
imageList.value
|
||||||
|
? (imageList.value.selectedImage = data.value.selectedImage || '')
|
||||||
|
: '';
|
||||||
|
console.log(imageState.imageUrl);
|
||||||
|
imageState.refreshImageState = false;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => drawerModel.value,
|
||||||
|
async () => {
|
||||||
|
if (drawerModel.value) {
|
||||||
|
await fetchImageList(props.dataId, data.value.selectedImage || '');
|
||||||
|
imageState.imageUrl = `${baseUrl}/institution/${props.dataId}/image/${data.value.selectedImage}`;
|
||||||
|
} else {
|
||||||
|
imageList.value = { selectedImage: '', list: [] };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<DialogForm
|
<DialogForm
|
||||||
|
|
@ -63,7 +182,13 @@ const data = defineModel<InstitutionPayload>('data', {
|
||||||
:title="$t('general.add', { text: $t('agencies.title') })"
|
:title="$t('general.add', { text: $t('agencies.title') })"
|
||||||
v-model:modal="model"
|
v-model:modal="model"
|
||||||
:submit="() => $emit('submit')"
|
:submit="() => $emit('submit')"
|
||||||
:close="() => $emit('close')"
|
:close="
|
||||||
|
() => {
|
||||||
|
imageState.imageUrl = '';
|
||||||
|
clearImageState();
|
||||||
|
$emit('close');
|
||||||
|
}
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
:class="{
|
:class="{
|
||||||
|
|
@ -72,24 +197,18 @@ const data = defineModel<InstitutionPayload>('data', {
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<ProfileBanner
|
<ProfileBanner
|
||||||
no-image-action
|
|
||||||
readonly
|
|
||||||
active
|
active
|
||||||
hide-fade
|
hide-fade
|
||||||
hide-active
|
hide-active
|
||||||
:icon="'ph-building-office'"
|
:icon="'ph-building-office'"
|
||||||
|
:img="imageState.imageUrl || null"
|
||||||
:title="data.name"
|
:title="data.name"
|
||||||
:caption="data.code"
|
:caption="data.code"
|
||||||
:color="`hsla(var(--green-8-hsl)/1)`"
|
:color="`hsla(var(--green-8-hsl)/1)`"
|
||||||
:bg-color="`hsla(var(--green-8-hsl)/0.1)`"
|
:bg-color="`hsla(var(--green-8-hsl)/0.1)`"
|
||||||
|
@view="viewImage"
|
||||||
|
@edit="editImage"
|
||||||
/>
|
/>
|
||||||
<!-- v-model:toggle-status="currentStatusGroupType"
|
|
||||||
@update:toggle-status="
|
|
||||||
() => {
|
|
||||||
currentStatusGroupType =
|
|
||||||
currentStatusGroupType === 'CREATED' ? 'INACTIVE' : 'CREATED';
|
|
||||||
}
|
|
||||||
" -->
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
@ -177,7 +296,12 @@ const data = defineModel<InstitutionPayload>('data', {
|
||||||
:title="data.name"
|
:title="data.name"
|
||||||
v-model:drawerOpen="drawerModel"
|
v-model:drawerOpen="drawerModel"
|
||||||
:submit="() => $emit('submit')"
|
:submit="() => $emit('submit')"
|
||||||
:close="() => $emit('close')"
|
:close="
|
||||||
|
() => {
|
||||||
|
clearImageState();
|
||||||
|
$emit('close');
|
||||||
|
}
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<div class="col column full-height">
|
<div class="col column full-height">
|
||||||
<div
|
<div
|
||||||
|
|
@ -187,8 +311,6 @@ const data = defineModel<InstitutionPayload>('data', {
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<ProfileBanner
|
<ProfileBanner
|
||||||
no-image-action
|
|
||||||
readonly
|
|
||||||
active
|
active
|
||||||
hide-fade
|
hide-fade
|
||||||
hide-active
|
hide-active
|
||||||
|
|
@ -197,6 +319,13 @@ const data = defineModel<InstitutionPayload>('data', {
|
||||||
:caption="data.code"
|
:caption="data.code"
|
||||||
:color="`hsla(var(${'--green-8'}-hsl)/1)`"
|
:color="`hsla(var(${'--green-8'}-hsl)/1)`"
|
||||||
:bg-color="`hsla(var(${'--green-8'}-hsl)/0.1)`"
|
:bg-color="`hsla(var(${'--green-8'}-hsl)/0.1)`"
|
||||||
|
:img="
|
||||||
|
`${baseUrl}/institution/${dataId}/image/${data.selectedImage}`.concat(
|
||||||
|
imageState.refreshImageState ? `?ts=${Date.now()}` : '',
|
||||||
|
) || null
|
||||||
|
"
|
||||||
|
@view="viewImage"
|
||||||
|
@edit="editImage"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -330,5 +459,39 @@ const data = defineModel<InstitutionPayload>('data', {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DrawerInfo>
|
</DrawerInfo>
|
||||||
|
|
||||||
|
<ImageUploadDialog
|
||||||
|
v-model:dialog-state="imageState.imageDialog"
|
||||||
|
v-model:file="imageFile"
|
||||||
|
v-model:on-create-data-list="onCreateImageList"
|
||||||
|
v-model:image-url="imageState.imageUrl"
|
||||||
|
v-model:data-list="imageList"
|
||||||
|
:on-create="model"
|
||||||
|
:hiddenFooter="!imageState.isImageEdit"
|
||||||
|
@add-image="addImage"
|
||||||
|
@remove-image="removeImage"
|
||||||
|
@submit="submitImage"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
<span v-if="!model" class="justify-center flex text-bold">
|
||||||
|
{{ $t('general.image') }}
|
||||||
|
{{ $i18n.locale === 'eng' ? data.nameEN : data.name }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #error>
|
||||||
|
<div class="full-height full-width" style="background: white">
|
||||||
|
<div
|
||||||
|
class="full-height full-width flex justify-center items-center"
|
||||||
|
style="
|
||||||
|
background: hsla(var(--green-8-hsl) / 0.1);
|
||||||
|
color: hsla(var(--green-8-hsl) / 1);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<Icon width="3rem" icon="ph-building-office" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</ImageUploadDialog>
|
||||||
</template>
|
</template>
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { storeToRefs } from 'pinia';
|
||||||
import { Icon } from '@iconify/vue/dist/iconify.js';
|
import { Icon } from '@iconify/vue/dist/iconify.js';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import { baseUrl } from 'src/stores/utils';
|
||||||
import { useNavigator } from 'src/stores/navigator';
|
import { useNavigator } from 'src/stores/navigator';
|
||||||
import { useInstitution } from 'src/stores/institution';
|
import { useInstitution } from 'src/stores/institution';
|
||||||
import { Institution, InstitutionPayload } from 'src/stores/institution/types';
|
import { Institution, InstitutionPayload } from 'src/stores/institution/types';
|
||||||
|
|
@ -95,9 +96,16 @@ const blankFormData: InstitutionPayload = {
|
||||||
subDistrictId: '',
|
subDistrictId: '',
|
||||||
districtId: '',
|
districtId: '',
|
||||||
provinceId: '',
|
provinceId: '',
|
||||||
|
selectedImage: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const refAgenciesDialog = ref();
|
||||||
const formData = ref<InstitutionPayload>(structuredClone(blankFormData));
|
const formData = ref<InstitutionPayload>(structuredClone(blankFormData));
|
||||||
const currAgenciesData = ref<Institution>();
|
const currAgenciesData = ref<Institution>();
|
||||||
|
const onCreateImageList = ref<{
|
||||||
|
selectedImage: string;
|
||||||
|
list: { url: string; imgFile: File | null; name: string }[];
|
||||||
|
}>({ selectedImage: '', list: [] });
|
||||||
|
|
||||||
function triggerDialog(type: 'add' | 'edit' | 'view') {
|
function triggerDialog(type: 'add' | 'edit' | 'view') {
|
||||||
if (type === 'add') {
|
if (type === 'add') {
|
||||||
|
|
@ -146,10 +154,11 @@ function assignFormData(data: Institution) {
|
||||||
subDistrictId: data.subDistrictId,
|
subDistrictId: data.subDistrictId,
|
||||||
districtId: data.districtId,
|
districtId: data.districtId,
|
||||||
provinceId: data.provinceId,
|
provinceId: data.provinceId,
|
||||||
|
selectedImage: data.selectedImage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submit() {
|
async function submit(opt?: { selectedImage: string }) {
|
||||||
const payload = {
|
const payload = {
|
||||||
group: undefined,
|
group: undefined,
|
||||||
code: formData.value.code,
|
code: formData.value.code,
|
||||||
|
|
@ -167,26 +176,41 @@ async function submit() {
|
||||||
districtId: formData.value.districtId,
|
districtId: formData.value.districtId,
|
||||||
provinceId: formData.value.provinceId,
|
provinceId: formData.value.provinceId,
|
||||||
};
|
};
|
||||||
|
if (
|
||||||
if (pageState.isDrawerEdit && currAgenciesData.value?.id) {
|
(pageState.isDrawerEdit && currAgenciesData.value?.id) ||
|
||||||
|
(opt?.selectedImage && currAgenciesData.value?.id)
|
||||||
|
) {
|
||||||
const ret = await institutionStore.editInstitution(
|
const ret = await institutionStore.editInstitution(
|
||||||
Object.assign(payload, { id: currAgenciesData.value.id }),
|
Object.assign(payload, {
|
||||||
|
id: currAgenciesData.value.id,
|
||||||
|
selectedImage: opt?.selectedImage || undefined,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pageState.isDrawerEdit = false;
|
pageState.isDrawerEdit = false;
|
||||||
currAgenciesData.value = ret;
|
currAgenciesData.value = ret;
|
||||||
|
formData.value.selectedImage = ret.selectedImage;
|
||||||
await fetchData();
|
await fetchData();
|
||||||
|
|
||||||
|
if (refAgenciesDialog.value && opt?.selectedImage) {
|
||||||
|
refAgenciesDialog.value.clearImageState();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
await institutionStore.createInstitution(
|
||||||
|
{
|
||||||
|
...payload,
|
||||||
|
code: formData.value.group || '',
|
||||||
|
},
|
||||||
|
onCreateImageList.value,
|
||||||
|
);
|
||||||
|
|
||||||
|
await fetchData();
|
||||||
|
pageState.addModal = false;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await institutionStore.createInstitution({
|
|
||||||
...payload,
|
|
||||||
code: formData.value.group || '',
|
|
||||||
});
|
|
||||||
|
|
||||||
await fetchData();
|
|
||||||
pageState.addModal = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function triggerChangeStatus(data?: Institution) {}
|
async function triggerChangeStatus(data?: Institution) {}
|
||||||
|
|
@ -409,7 +433,7 @@ watch(
|
||||||
|
|
||||||
<!-- SEC: body content -->
|
<!-- SEC: body content -->
|
||||||
<article
|
<article
|
||||||
v-if="false"
|
v-if="data.length === 0"
|
||||||
class="col surface-2 flex items-center justify-center"
|
class="col surface-2 flex items-center justify-center"
|
||||||
>
|
>
|
||||||
<NoData
|
<NoData
|
||||||
|
|
@ -476,14 +500,24 @@ watch(
|
||||||
</q-td>
|
</q-td>
|
||||||
<q-td v-if="fieldSelected.includes('name')">
|
<q-td v-if="fieldSelected.includes('name')">
|
||||||
<section class="row items-center no-wrap">
|
<section class="row items-center no-wrap">
|
||||||
<q-avatar
|
<q-avatar size="md">
|
||||||
size="md"
|
<q-img
|
||||||
style="
|
class="text-center"
|
||||||
background: hsla(var(--green-8-hsl) / 0.1);
|
:ratio="1"
|
||||||
color: hsla(var(--green-8-hsl) / 1);
|
:src="`${baseUrl}/institution/${props.row.id}/image/${props.row.selectedImage}?ts=${Date.now()}`"
|
||||||
"
|
>
|
||||||
>
|
<template #error>
|
||||||
<Icon icon="ph-building-office" />
|
<div
|
||||||
|
class="no-padding full-width full-height flex items-center justify-center"
|
||||||
|
style="
|
||||||
|
background: hsla(var(--green-8-hsl) / 0.1);
|
||||||
|
color: hsla(var(--green-8-hsl) / 1);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<Icon icon="ph-building-office" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-img>
|
||||||
</q-avatar>
|
</q-avatar>
|
||||||
<span class="col q-pl-md">
|
<span class="col q-pl-md">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -558,14 +592,24 @@ watch(
|
||||||
<section class="column col-12 col-md-6">
|
<section class="column col-12 col-md-6">
|
||||||
<div class="bordered col surface-1 rounded q-pa-md">
|
<div class="bordered col surface-1 rounded q-pa-md">
|
||||||
<header class="row items-center">
|
<header class="row items-center">
|
||||||
<q-avatar
|
<q-avatar size="xl">
|
||||||
size="xl"
|
<q-img
|
||||||
style="
|
class="text-center"
|
||||||
background: hsla(var(--green-8-hsl) / 0.1);
|
:ratio="1"
|
||||||
color: hsla(var(--green-8-hsl) / 1);
|
:src="`${baseUrl}/institution/${props.row.id}/image/${props.row.selectedImage}?ts=${Date.now()}`"
|
||||||
"
|
>
|
||||||
>
|
<template #error>
|
||||||
<Icon icon="ph-building-office" />
|
<div
|
||||||
|
class="no-padding full-width full-height flex items-center justify-center"
|
||||||
|
style="
|
||||||
|
background: hsla(var(--green-8-hsl) / 0.1);
|
||||||
|
color: hsla(var(--green-8-hsl) / 1);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<Icon icon="ph-building-office" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-img>
|
||||||
</q-avatar>
|
</q-avatar>
|
||||||
<span class="text-weight-bold column q-pl-md">
|
<span class="text-weight-bold column q-pl-md">
|
||||||
{{
|
{{
|
||||||
|
|
@ -697,6 +741,8 @@ watch(
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<AgenciesDialog
|
<AgenciesDialog
|
||||||
|
ref="refAgenciesDialog"
|
||||||
|
:data-id="currAgenciesData && currAgenciesData.id"
|
||||||
@change-status="triggerChangeStatus"
|
@change-status="triggerChangeStatus"
|
||||||
@drawer-delete="
|
@drawer-delete="
|
||||||
() => {
|
() => {
|
||||||
|
|
@ -707,11 +753,17 @@ watch(
|
||||||
@drawer-undo="undo"
|
@drawer-undo="undo"
|
||||||
@close="resetForm"
|
@close="resetForm"
|
||||||
@submit="submit"
|
@submit="submit"
|
||||||
|
@submit-image="
|
||||||
|
async (v) => {
|
||||||
|
if (v) await submit({ selectedImage: v });
|
||||||
|
}
|
||||||
|
"
|
||||||
:readonly="!pageState.isDrawerEdit"
|
:readonly="!pageState.isDrawerEdit"
|
||||||
:isEdit="pageState.isDrawerEdit"
|
:isEdit="pageState.isDrawerEdit"
|
||||||
v-model="pageState.addModal"
|
v-model="pageState.addModal"
|
||||||
v-model:drawer-model="pageState.viewDrawer"
|
v-model:drawer-model="pageState.viewDrawer"
|
||||||
v-model:data="formData"
|
v-model:data="formData"
|
||||||
|
v-model:on-create-image-list="onCreateImageList"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,11 @@ import { ref } from 'vue';
|
||||||
import { Institution, InstitutionPayload } from './types';
|
import { Institution, InstitutionPayload } from './types';
|
||||||
import { api } from 'src/boot/axios';
|
import { api } from 'src/boot/axios';
|
||||||
import { PaginationResult } from 'src/types';
|
import { PaginationResult } from 'src/types';
|
||||||
|
import useFlowStore from '../flow';
|
||||||
|
|
||||||
export const useInstitution = defineStore('institution-store', () => {
|
export const useInstitution = defineStore('institution-store', () => {
|
||||||
|
const flowStore = useFlowStore();
|
||||||
|
|
||||||
const data = ref<Institution[]>([]);
|
const data = ref<Institution[]>([]);
|
||||||
const page = ref<number>(1);
|
const page = ref<number>(1);
|
||||||
const pageMax = ref<number>(1);
|
const pageMax = ref<number>(1);
|
||||||
|
|
@ -33,8 +36,26 @@ export const useInstitution = defineStore('institution-store', () => {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createInstitution(data: InstitutionPayload) {
|
async function createInstitution(
|
||||||
const res = await api.post('/institution', data);
|
data: InstitutionPayload,
|
||||||
|
imgList: {
|
||||||
|
selectedImage: string;
|
||||||
|
list: { url: string; imgFile: File | null; name: string }[];
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const res = await api.post('/institution', {
|
||||||
|
...data,
|
||||||
|
selectedImage: imgList.selectedImage || '',
|
||||||
|
});
|
||||||
|
|
||||||
|
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.status < 400) {
|
if (res.status < 400) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
@ -60,6 +81,60 @@ export const useInstitution = defineStore('institution-store', () => {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchImageListById(
|
||||||
|
id: string,
|
||||||
|
flow?: {
|
||||||
|
sessionId?: string;
|
||||||
|
refTransactionId?: string;
|
||||||
|
transactionId?: string;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const res = await api.get(`/institution/${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, id: string, name: string) {
|
||||||
|
await api
|
||||||
|
.put(`/institution/${id}/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(`/institution/${id}/image/${name}`, {
|
||||||
|
headers: {
|
||||||
|
'X-Session-Id': flow?.sessionId,
|
||||||
|
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
||||||
|
'X-Tid': flow?.transactionId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res) return false;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data,
|
data,
|
||||||
page,
|
page,
|
||||||
|
|
@ -71,5 +146,9 @@ export const useInstitution = defineStore('institution-store', () => {
|
||||||
createInstitution,
|
createInstitution,
|
||||||
editInstitution,
|
editInstitution,
|
||||||
deleteInstitution,
|
deleteInstitution,
|
||||||
|
|
||||||
|
fetchImageListById,
|
||||||
|
addImageList,
|
||||||
|
deleteImageByName,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ export type Institution = {
|
||||||
group: string;
|
group: string;
|
||||||
name: string;
|
name: string;
|
||||||
nameEN: string;
|
nameEN: string;
|
||||||
|
selectedImage?: string | null;
|
||||||
|
|
||||||
addressEN: string;
|
addressEN: string;
|
||||||
address: string;
|
address: string;
|
||||||
|
|
@ -29,6 +30,7 @@ export type InstitutionPayload = {
|
||||||
name: string;
|
name: string;
|
||||||
nameEN: string;
|
nameEN: string;
|
||||||
group?: string;
|
group?: string;
|
||||||
|
selectedImage?: string | null;
|
||||||
|
|
||||||
addressEN: string;
|
addressEN: string;
|
||||||
address: string;
|
address: string;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue