jws-frontend/src/components/upload-file/UploadFileSection.vue
Methapon Metanipat 0ef389c69b
feat: quotation attachment (#49)
* fix: i18n

* fix: 18n

* feat: file upload component

* feat: quotation attachment

---------

Co-authored-by: puriphatt <puriphat@frappet.com>
2024-11-01 17:18:24 +07:00

108 lines
2.4 KiB
Vue

<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { QFile } from 'quasar';
import { baseUrl } from 'stores/utils';
import UploadFileCard from './UploadFileCard.vue';
const props = withDefaults(
defineProps<{
readonly?: boolean;
label?: string;
multiple?: boolean;
transformUrl?: (url: string) => string | Promise<string>;
}>(),
{
label: 'Upload',
readonly: false,
multiple: false,
},
);
defineEmits<{
(e: 'close', name: string): void;
(e: 'update:file', file: File): void;
}>();
const fileData = defineModel<
{
name: string;
progress: number;
loaded: number;
total: number;
url?: string;
}[]
>('fileData', { required: true });
const file = ref<File[]>([]);
const refQFile = ref<InstanceType<typeof QFile>>();
async function triggerViewSlip(url: string) {
window.open(
props.transformUrl ? await props.transformUrl(url) : `${baseUrl}/${url}`,
'_blank',
);
}
function pickFile() {
if (!refQFile.value) return;
refQFile.value.pickFiles();
}
</script>
<template>
<div>
<div
class="upload-section column rounded q-py-md full-height items-center justify-center no-wrap surface-2"
>
<q-img src="/images/upload.png" width="150px" />
{{ label }}
<q-btn
v-if="!readonly"
unelevated
:label="$t('general.upload')"
rounded
class="app-bg-info q-mt-sm"
@click.stop="() => pickFile()"
/>
<q-file
ref="refQFile"
:multiple
v-show="false"
v-model="file"
@update:model-value="(f) => $emit('update:file', f)"
/>
</div>
<!-- upload card -->
<section class="row">
<div
v-for="(d, j) in fileData"
:key="j"
class="col-12"
:class="{
'q-pt-md': j === 0,
'q-pt-sm': j > 0,
}"
>
<UploadFileCard
:name="d.name"
:progress="d.progress"
:uploading="{ loaded: d.loaded, total: d.total }"
:url="d.url"
icon="mdi-file-image-outline"
color="hsl(var(--text-mute))"
clickable
:closeable="!readonly"
@click="triggerViewSlip(d.url || '')"
@close="$emit('close', d.name)"
/>
</div>
</section>
</div>
</template>
<style scoped>
.upload-section {
border: 3px solid var(--border-color);
border-style: dashed;
}
</style>