feat: institution attachment
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 5s
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 5s
This commit is contained in:
parent
da52bfbcbd
commit
b977f86de9
6 changed files with 179 additions and 2 deletions
|
|
@ -1,6 +1,10 @@
|
|||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import SelectInput from '../shared/SelectInput.vue';
|
||||
import useOptionStore from 'src/stores/options';
|
||||
import { Icon } from '@iconify/vue/dist/iconify.js';
|
||||
import { useInstitution } from 'src/stores/institution';
|
||||
|
||||
const optionStore = useOptionStore();
|
||||
|
||||
|
|
@ -10,6 +14,11 @@ defineProps<{
|
|||
readonly?: boolean;
|
||||
onDrawer?: boolean;
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'deleteAttachment', name: string): void;
|
||||
}>();
|
||||
|
||||
const attachmentRef = ref();
|
||||
|
||||
const group = defineModel('group', { default: '' });
|
||||
const name = defineModel('name', { default: '' });
|
||||
|
|
@ -17,8 +26,19 @@ const nameEn = defineModel('nameEn', { default: '' });
|
|||
const contactName = defineModel('contactName', { default: '' });
|
||||
const email = defineModel('email', { default: '' });
|
||||
const contactTel = defineModel('contactTel', { default: '' });
|
||||
const attachment = defineModel<File[]>('attachment');
|
||||
const attachmentList =
|
||||
defineModel<{ name: string; url: string }[]>('attachmentList');
|
||||
|
||||
type Options = { label: string; value: string };
|
||||
|
||||
function openNewTab(url: string) {
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
|
||||
function deleteAttachment(name: string) {
|
||||
emit('deleteAttachment', name);
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div class="row col-12">
|
||||
|
|
@ -162,6 +182,77 @@ type Options = { label: string; value: string };
|
|||
/>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-file
|
||||
ref="attachmentRef"
|
||||
for="input-attachment"
|
||||
dense
|
||||
outlined
|
||||
:readonly="readonly"
|
||||
multiple
|
||||
append
|
||||
:label="$t('personnel.form.attachment')"
|
||||
class="col"
|
||||
v-model="attachment"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<Icon
|
||||
icon="material-symbols:attach-file"
|
||||
width="20px"
|
||||
style="color: var(--brand-1)"
|
||||
/>
|
||||
</template>
|
||||
<template v-slot:file="file">
|
||||
<div class="row full-width items-center">
|
||||
<span class="col ellipsis">
|
||||
{{ file.file.name }}
|
||||
</span>
|
||||
<q-btn
|
||||
dense
|
||||
rounded
|
||||
flat
|
||||
padding="2 2"
|
||||
class="app-text-muted"
|
||||
icon="mdi-close-circle"
|
||||
@click.stop="attachmentRef.removeAtIndex(file.index)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</q-file>
|
||||
|
||||
<div v-if="attachmentList && attachmentList?.length > 0" class="col-12">
|
||||
<q-list bordered separator class="rounded" style="padding: 0">
|
||||
<q-item
|
||||
id="attachment-file"
|
||||
for="attachment-file"
|
||||
v-for="item in attachmentList"
|
||||
clickable
|
||||
:key="item.url"
|
||||
class="items-center row"
|
||||
@click="() => openNewTab(item.url)"
|
||||
>
|
||||
<q-item-section>
|
||||
<div class="row items-center justify-between">
|
||||
<div class="col">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<q-btn
|
||||
v-if="!readonly"
|
||||
id="delete-file"
|
||||
rounded
|
||||
flat
|
||||
dense
|
||||
unelevated
|
||||
size="md"
|
||||
icon="mdi-trash-can-outline"
|
||||
class="app-text-negative"
|
||||
@click.stop="deleteAttachment(item.name)"
|
||||
/>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -928,6 +928,7 @@ export default {
|
|||
contactName: 'Contact Person',
|
||||
contactTel: 'Contact Number',
|
||||
bankInfo: 'Bank Information',
|
||||
attachment: 'Attachment',
|
||||
},
|
||||
|
||||
requestList: {
|
||||
|
|
|
|||
|
|
@ -925,6 +925,7 @@ export default {
|
|||
contactName: 'ชื่อผู้ติดต่อ',
|
||||
contactTel: 'เบอร์โทรผู้ติดต่อ',
|
||||
bankInfo: 'ข้อมูลธนาคาร',
|
||||
attachment: 'เอกสารเพิ่มเติม',
|
||||
},
|
||||
|
||||
requestList: {
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ const emit = defineEmits<{
|
|||
(e: 'addImage'): void;
|
||||
(e: 'removeImage'): void;
|
||||
(e: 'submitImage', name: string): void;
|
||||
(e: 'deleteAttachment', name: string): void;
|
||||
}>();
|
||||
|
||||
const data = defineModel<InstitutionPayload>('data', {
|
||||
|
|
@ -121,6 +122,9 @@ const formBankBook = defineModel<BankBook[]>('formBankBook', {
|
|||
},
|
||||
],
|
||||
});
|
||||
const attachment = defineModel<File[]>('attachment');
|
||||
const attachmentList =
|
||||
defineModel<{ name: string; url: string }[]>('attachmentList');
|
||||
|
||||
function viewImage() {
|
||||
imageState.imageDialog = true;
|
||||
|
|
@ -348,6 +352,7 @@ watch(
|
|||
v-model:contact-name="data.contactName"
|
||||
v-model:email="data.contactEmail"
|
||||
v-model:contact-tel="data.contactTel"
|
||||
v-model:attachment="attachment"
|
||||
/>
|
||||
<AddressForm
|
||||
id="agencies-form-address-info"
|
||||
|
|
@ -550,6 +555,9 @@ watch(
|
|||
v-model:contact-name="data.contactName"
|
||||
v-model:email="data.contactEmail"
|
||||
v-model:contact-tel="data.contactTel"
|
||||
v-model:attachment="attachment"
|
||||
:attachment-list="attachmentList"
|
||||
@delete-attachment="(name) => $emit('deleteAttachment', name)"
|
||||
/>
|
||||
<AddressForm
|
||||
id="agencies-address-info"
|
||||
|
|
|
|||
|
|
@ -115,6 +115,8 @@ const blankFormData: InstitutionPayload = {
|
|||
],
|
||||
};
|
||||
|
||||
const attachment = ref<File[]>([]);
|
||||
const attachmentList = ref<{ name: string; url: string }[]>([]);
|
||||
const statusFilter = ref<'all' | 'statusACTIVE' | 'statusINACTIVE'>('all');
|
||||
const refAgenciesDialog = ref();
|
||||
const formData = ref<InstitutionPayload>(structuredClone(blankFormData));
|
||||
|
|
@ -145,6 +147,8 @@ function resetForm() {
|
|||
pageState.addModal = false;
|
||||
pageState.viewDrawer = false;
|
||||
currAgenciesData.value = undefined;
|
||||
attachment.value = [];
|
||||
attachmentList.value = [];
|
||||
formData.value = structuredClone(blankFormData);
|
||||
}
|
||||
|
||||
|
|
@ -154,7 +158,7 @@ function undo() {
|
|||
pageState.isDrawerEdit = false;
|
||||
}
|
||||
|
||||
function assignFormData(data: Institution) {
|
||||
async function assignFormData(data: Institution) {
|
||||
currAgenciesData.value = data;
|
||||
formData.value = {
|
||||
group: data.group,
|
||||
|
|
@ -187,6 +191,8 @@ function assignFormData(data: Institution) {
|
|||
bankUrl: `${baseUrl}/institution/${data.id}/bank-qr/${v.id}?ts=${Date.now()}`,
|
||||
})),
|
||||
};
|
||||
|
||||
await fetchAttachment();
|
||||
}
|
||||
|
||||
async function submit(opt?: { selectedImage: string }) {
|
||||
|
|
@ -228,18 +234,29 @@ async function submit(opt?: { selectedImage: string }) {
|
|||
);
|
||||
|
||||
if (ret) {
|
||||
attachment.value.forEach(async (file) => {
|
||||
await institutionStore.putAttachment({
|
||||
parentId: ret.id || '',
|
||||
name: file.name,
|
||||
file: file,
|
||||
});
|
||||
});
|
||||
pageState.isDrawerEdit = false;
|
||||
currAgenciesData.value = ret;
|
||||
formData.value.selectedImage = ret.selectedImage;
|
||||
await fetchData($q.screen.xs);
|
||||
attachment.value = [];
|
||||
|
||||
if (refAgenciesDialog.value && opt?.selectedImage) {
|
||||
refAgenciesDialog.value.clearImageState();
|
||||
}
|
||||
setTimeout(async () => {
|
||||
await fetchAttachment();
|
||||
}, 300);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
await institutionStore.createInstitution(
|
||||
const res = await institutionStore.createInstitution(
|
||||
{
|
||||
...payload,
|
||||
code: formData.value.group || '',
|
||||
|
|
@ -247,6 +264,16 @@ async function submit(opt?: { selectedImage: string }) {
|
|||
imageListOnCreate.value,
|
||||
);
|
||||
|
||||
if (!res) return;
|
||||
|
||||
attachment.value.forEach(async (file) => {
|
||||
await institutionStore.putAttachment({
|
||||
parentId: res.id || '',
|
||||
name: file.name,
|
||||
file: file,
|
||||
});
|
||||
});
|
||||
|
||||
await fetchData($q.screen.xs);
|
||||
pageState.addModal = false;
|
||||
return;
|
||||
|
|
@ -346,6 +373,49 @@ async function changeStatus(id?: string) {
|
|||
}
|
||||
}
|
||||
|
||||
async function deleteAttachment(attachmentName: string) {
|
||||
dialog({
|
||||
color: 'negative',
|
||||
icon: 'mdi-trash-can-outline',
|
||||
title: t('dialog.title.confirmDelete', {
|
||||
msg: t('personnel.form.attachment'),
|
||||
}),
|
||||
actionText: t('general.delete'),
|
||||
persistent: true,
|
||||
message: t('dialog.message.confirmDelete'),
|
||||
action: async () => {
|
||||
if (!currAgenciesData.value?.id) return;
|
||||
institutionStore.delAttachment({
|
||||
parentId: currAgenciesData.value?.id,
|
||||
name: attachmentName,
|
||||
});
|
||||
setTimeout(async () => {
|
||||
await fetchAttachment();
|
||||
}, 300);
|
||||
},
|
||||
cancel: () => {},
|
||||
});
|
||||
}
|
||||
|
||||
async function fetchAttachment() {
|
||||
const resAttachment = await institutionStore.listAttachment({
|
||||
parentId: currAgenciesData.value.id,
|
||||
});
|
||||
|
||||
if (!resAttachment) return;
|
||||
|
||||
attachmentList.value = await Promise.all(
|
||||
resAttachment.map(async (f) => ({
|
||||
name: f,
|
||||
url: await institutionStore.getAttachment({
|
||||
parentId: currAgenciesData.value.id,
|
||||
name: f,
|
||||
download: false,
|
||||
}),
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
navigatorStore.current.title = 'agencies.title';
|
||||
navigatorStore.current.path = [{ text: 'agencies.caption', i18n: true }];
|
||||
|
|
@ -976,6 +1046,7 @@ watch(
|
|||
}
|
||||
"
|
||||
@change-status="triggerChangeStatus"
|
||||
@delete-attachment="deleteAttachment"
|
||||
:readonly="!pageState.isDrawerEdit"
|
||||
:isEdit="pageState.isDrawerEdit"
|
||||
:hide-action="!canAccess('agencies', 'edit')"
|
||||
|
|
@ -985,6 +1056,8 @@ watch(
|
|||
v-model:form-bank-book="formData.bank"
|
||||
v-model:image-list-on-create="imageListOnCreate"
|
||||
v-model:deletes-status-qr-code-bank-imag="deletesStatusQrCodeBankImag"
|
||||
v-model:attachment="attachment"
|
||||
:attachment-list="attachmentList"
|
||||
/>
|
||||
</template>
|
||||
<style scoped>
|
||||
|
|
|
|||
|
|
@ -5,9 +5,11 @@ import { api } from 'src/boot/axios';
|
|||
import { PaginationResult } from 'src/types';
|
||||
import useFlowStore from '../flow';
|
||||
import { Status } from '../types';
|
||||
import { baseUrl, manageAttachment, manageFile, manageMeta } from '../utils';
|
||||
|
||||
export const useInstitution = defineStore('institution-store', () => {
|
||||
const flowStore = useFlowStore();
|
||||
const attachmentManager = manageAttachment(api, 'institution');
|
||||
|
||||
const data = ref<Institution[]>([]);
|
||||
const page = ref<number>(1);
|
||||
|
|
@ -200,6 +202,7 @@ export const useInstitution = defineStore('institution-store', () => {
|
|||
}
|
||||
|
||||
return {
|
||||
...attachmentManager,
|
||||
data,
|
||||
page,
|
||||
pageMax,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue