salix-front/src/pages/Claim/Card/ClaimPhoto.vue

347 lines
9.1 KiB
Vue

<script setup>
import axios from 'axios';
import { ref, computed } from 'vue';
import { useQuasar } from 'quasar';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { useSession } from 'composables/useSession';
import VnConfirm from 'components/ui/VnConfirm.vue';
import FetchData from 'components/FetchData.vue';
const router = useRouter();
const quasar = useQuasar();
const { t } = useI18n();
const { getTokenMultimedia } = useSession();
const token = getTokenMultimedia();
const claimId = computed(() => router.currentRoute.value.params.id);
const claimDms = ref([
{
dmsFk: claimId,
},
]);
const client = ref({});
const inputFile = ref();
const files = ref({});
const spinnerRef = ref();
const claimDmsRef = ref();
const dmsType = ref({});
const config = ref({});
const dragFile = ref(false);
const dragFileTimeout = ref();
const claimDmsFilter = ref({
include: [
{
relation: 'client',
scope: {
fields: ['id', 'name'],
},
},
{
relation: 'claimDms',
scope: {
include: {
relation: 'dms',
scope: {
fields: ['contentType'],
},
},
},
},
],
where: { id: claimId.value },
});
const multimediaDialog = ref();
const multimediaSlide = ref();
function openDialog(dmsId) {
multimediaSlide.value = dmsId;
multimediaDialog.value = true;
}
function viewDeleteDms(index) {
quasar
.dialog({
component: VnConfirm,
componentProps: {
title: t('This file will be deleted'),
icon: 'delete',
data: { index },
promise: deleteDms,
},
})
.onOk(() => claimDms.value.splice(index, 1));
}
async function deleteDms({ index }) {
const dmsId = claimDms.value[index].dmsFk;
await axios.post(`ClaimDms/${dmsId}/removeFile`);
quasar.notify({
message: t('globals.dataDeleted'),
type: 'positive',
icon: 'delete',
});
}
function setClaimDms(data) {
if (!data) return;
claimDms.value = data.claimDms.map((media) => {
media.isVideo = media.dms.contentType == 'video/mp4';
media.url = `/api/Claims/${media.dmsFk}/downloadFile?access_token=${token}`;
return media;
});
client.value = data.client;
}
async function create() {
const formData = new FormData();
const inputFiles = files.value;
for (let i = 0; i < inputFiles.length; i++)
formData.append(inputFiles[i].name, inputFiles[i]);
const query = `claims/${claimId.value}/uploadFile`;
const dms = {
hasFile: false,
hasFileAttached: false,
reference: claimId.value,
warehouseId: config.value.warehouseFk,
companyId: config.value.companyFk,
dmsTypeId: dmsType.value.id,
description: t('claim.fileDescription', {
claimId: claimId.value,
clientName: client.value.name,
clientId: client.value.id,
}).toUpperCase(),
};
spinnerRef.value.show();
await axios.post(query, formData, {
params: dms,
});
spinnerRef.value.hide();
quasar.notify({
message: t('globals.dataSaved'),
type: 'positive',
icon: 'check',
});
claimDmsRef.value.fetch();
}
function onDrop($data) {
dragFile.value = false;
files.value = $data.dataTransfer.files;
create();
}
function onDrag() {
clearTimeout(dragFileTimeout.value);
dragFileTimeout.value = setTimeout(() => (dragFile.value = false), 500);
dragFile.value = true;
}
</script>
<template>
<FetchData
url="Claims"
:filter="claimDmsFilter"
@on-fetch="([data]) => setClaimDms(data)"
limit="20"
auto-load
ref="claimDmsRef"
/>
<FetchData
url="DmsTypes/findOne"
:filter="{ where: { code: 'claim' } }"
@on-fetch="(data) => (dmsType = data)"
auto-load
/>
<FetchData
url="UserConfigs/getUserConfig"
@on-fetch="(data) => (config = data)"
auto-load
/>
<div
:class="['container', { dragFile }]"
@drop.prevent="onDrop"
@dragenter.prevent
@dragover.prevent="onDrag"
>
<div
class="flex flex-center items-center text-grey q-mt-md column"
v-if="dragFile"
>
<QIcon size="xl" name="file_download" />
<h5>
{{ t('claim.dragDrop') }}
</h5>
</div>
<div
class="text-center text-grey q-mt-md cursor-pointer"
v-if="!claimDms?.length && !dragFile"
@click="inputFile.nativeEl.click()"
>
<QIcon size="xl" name="image"></QIcon>
<QIcon size="xl" name="movie"></QIcon>
<h5>
{{ t('claim.noData') }}
</h5>
</div>
<div class="multimediaParent bg-transparent" v-if="claimDms?.length && !dragFile">
<div
v-for="(media, index) of claimDms"
:key="index"
class="relative-position"
>
<QBtn
icon="delete"
color="primary"
text-color="white"
size="md"
class="all-pointer-events absolute delete-button zindex"
@click.stop="viewDeleteDms(index)"
round
/>
<QIcon
name="play_circle"
color="primary"
size="xl"
class="absolute-center zindex"
v-if="media.isVideo"
@click.stop="openDialog(media.dmsFk)"
>
<QTooltip>Video</QTooltip>
</QIcon>
<QCard class="multimedia relative-position">
<QImg
:src="media.url"
class="rounded-borders cursor-pointer fit"
@click="openDialog(media.dmsFk)"
v-if="!media.isVideo"
>
</QImg>
<video
:src="media.url"
class="rounded-borders cursor-pointer fit"
muted="muted"
v-if="media.isVideo"
@click="openDialog(media.dmsFk)"
/>
</QCard>
</div>
</div>
</div>
<QDialog ref="spinnerRef">
<QSpinner color="primary" size="xl" />
</QDialog>
<QPageSticky position="bottom-right" :offset="[25, 25]">
<label for="fileInput">
<QBtn fab @click="inputFile.nativeEl.click()" icon="add" color="primary">
<QInput
ref="inputFile"
type="file"
style="display: none"
multiple
v-model="files"
@update:model-value="create()"
/>
<QTooltip bottom> {{ t('globals.add') }} </QTooltip>
</QBtn>
</label>
</QPageSticky>
<!-- MULTIMEDIA DIALOG START-->
<QDialog
v-model="multimediaDialog"
transition-show="slide-up"
transition-hide="slide-down"
>
<QToolbar class="absolute zindex close-button">
<QSpace />
<QBtn icon="close" color="primary" round dense v-close-popup />
</QToolbar>
<QCarousel swipeable animated v-model="multimediaSlide" arrows class="fit">
<QCarouselSlide
v-for="media of claimDms"
:key="media.dmsFk"
:name="media.dmsFk"
>
<QImg
:src="media.url"
class="fit"
fit="scale-down"
v-if="!media.isVideo"
/>
<video class="q-ma-none fit" v-if="media.isVideo" controls muted autoplay>
<source :src="media.url" type="video/mp4" />
</video>
</QCarouselSlide>
</QCarousel>
</QDialog>
<!-- MULTIMEDIA DIALOG END-->
</template>
<style lang="scss" scoped>
.container {
min-height: 80vh;
min-width: 80%;
}
.q-dialog__inner--minimized > div {
max-width: 80%;
}
.multimediaParent {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-auto-rows: auto;
grid-gap: 1rem;
}
.multimedia {
transition: all 0.5s;
opacity: 1;
height: 250px;
.q-img {
object-fit: cover;
background-color: black;
}
video {
object-fit: cover;
background-color: black;
}
}
.multimedia:hover {
opacity: 0.5;
}
.delete-button {
top: 10px;
left: 10px;
}
.close-button {
top: 1%;
right: 10%;
}
.zindex {
z-index: 1;
}
.dragFile {
border: 2px dashed $color-spacer;
}
</style>
<i18n>
es:
This file will be deleted: Este archivo va a ser borrado
</i18n>