feat: image upload dialog

This commit is contained in:
Methapon2001 2024-08-01 14:20:13 +07:00
parent 355a30074c
commit 50329871f0

View file

@ -0,0 +1,155 @@
<script lang="ts" setup>
import { ref } from 'vue';
import AppBox from './app/AppBox.vue';
const imageUrl = defineModel<string>('imageUrl', {
required: false,
default: '',
});
const fallbackUrl = defineModel<string>('fallbackUrl', {
required: false,
default: '',
});
const dialogState = defineModel<boolean>('dialogState', {
required: false,
default: true,
});
const reader = new FileReader();
const inputFile = ref<HTMLInputElement>();
reader.addEventListener('load', () => {
if (typeof reader.result === 'string') imageUrl.value = reader.result;
});
function change(e: Event) {
const element = e.target as HTMLInputElement | null;
const file = element?.files?.[0];
if (file) reader.readAsDataURL(file);
}
</script>
<template>
<q-dialog v-model="dialogState">
<AppBox class="dialog-content">
<div class="row items-center q-py-sm q-px-md bordered-b">
<div style="flex: 1"><slot name="title" /></div>
<div>
<q-btn
round
flat
icon="mdi-close"
padding="xs"
class="close-btn"
:class="{ dark: $q.dark.isActive }"
v-close-popup
/>
</div>
</div>
<div class="dialog-body">
<input
type="file"
accept="image/*"
ref="inputFile"
@change="change"
hidden
/>
<img
:src="imageUrl"
v-if="imageUrl"
class="image-container"
style="object-fit: contain"
@error="imageUrl = fallbackUrl || ''"
/>
<div class="image-container" v-if="!imageUrl">
<slot name="error" v-if="!imageUrl"></slot>
</div>
<div style="position: fixed; padding: var(--size-2)">
<q-btn
class="upload-image-btn"
icon="mdi-camera"
size="md"
unelevated
round
@click="inputFile?.click()"
></q-btn>
</div>
</div>
<div class="row items-center justify-end q-py-sm q-px-md bordered-t">
<q-btn
dense
unelevated
color="grey-4"
text-color="grey-10"
:label="$t('cancel')"
@click="inputFile && (inputFile.value = '')"
class="q-px-md q-mr-sm"
v-close-popup
/>
<q-btn
dense
unelevated
id="submit-btn"
type="submit"
color="primary"
class="q-px-md"
@click="$emit('save', inputFile?.files?.[0] || null)"
:label="$t('save')"
/>
</div>
</AppBox>
</q-dialog>
</template>
<style scoped>
.dialog-content {
padding: 0;
border-radius: var(--radius-2);
flex-wrap: nowrap;
width: 100%;
max-width: 80%;
}
@media (min-width: 768px) {
.dialog-content {
max-width: 60%;
}
}
.dialog-body {
overflow-y: auto;
background-color: var(--surface-2) !important;
position: relative;
display: flex;
flex-direction: column;
flex: 1;
height: calc(100vh - 300px);
}
.upload-image-btn {
transition: 0.3s background-color ease-in-out;
background-color: hsla(0 0% 0% / 0.2);
backdrop-filter: blur(1px);
&:not(:hover) {
color: hsla(0 0% 40% / 1);
background-color: hsla(0 0% 0% / 0.2);
}
}
.image-container {
width: 100%;
height: calc(100vh - 300px);
min-height: 480px;
& :deep(*) {
height: 100%;
width: 100%;
}
}
.image-container > :deep(*:not(:first-child)) {
display: none;
}
</style>