details view image component refactor
All checks were successful
/ Make image (push) Successful in 39s

This commit is contained in:
nquidox 2025-10-19 17:30:22 +03:00
parent 9d80345b77
commit bb40d17e6b
5 changed files with 118 additions and 39 deletions

View file

@ -20,12 +20,27 @@
justify-content: center; justify-content: center;
} }
.center-button-container { .button-container-center {
display: flex; display: flex;
justify-content: center; justify-content: center;
margin-top: 10px; margin-top: 10px;
} }
.button-container-evenly {
display: flex;
justify-content: space-between !important;
margin-top: 10px;
}
.button-container-evenly .n-button {
flex: 1;
min-width: 0;
}
.button-gap {
gap: 10px;
}
.center-button { .center-button {
min-width: 320px; min-width: 320px;
} }
@ -137,3 +152,17 @@ body,
.main-content { .main-content {
flex: 1; flex: 1;
} }
.image-preview-modal {
width: 80%;
max-width: 800px;
}
.image-preview-modal .n-card__content {
padding: 0;
text-align: center;
}
.preview-modal-image {
max-width: 99%;
max-height: 70vh;
object-fit: contain;
}

View file

@ -190,7 +190,7 @@ onMounted(() => {
</n-card> </n-card>
<div v-else>Not found</div> <div v-else>Not found</div>
<div class="center-button-container"> <div class="button-container-center">
<n-button type="error" class="center-button" @click="onDelete">Delete</n-button> <n-button type="error" class="center-button" @click="onDelete">Delete</n-button>
</div> </div>

View file

@ -31,8 +31,27 @@ function onModalClose() {
previewImageUrl.value = '' previewImageUrl.value = ''
} }
function beforeUpload({ fileList: newFileList }) { const fileInput = ref(null)
return newFileList.length <= 1
function triggerFileInput() {
fileInput.value?.click()
}
function onFileInputChange(event) {
const files = event.target.files
if (!files || files.length === 0) return
const file = files[0]
handleUpload({
fileList: [
{
file,
name: file.name,
status: 'pending',
},
],
})
event.target.value = ''
} }
async function handleUpload({ fileList: newFileList }) { async function handleUpload({ fileList: newFileList }) {
@ -100,37 +119,31 @@ const cancelDelete = () => {
<template> <template>
<div> <div>
<n-upload <div v-if="fileList.length === 0" class="upload-wrapper" @click="triggerFileInput">
v-model:file-list="fileList" <BoxIcon class="upload-icon" />
:default-upload="false" <span class="upload-text">Click to Upload</span>
list-type="image-card" </div>
:max="1"
:before-upload="beforeUpload"
@before-preview="handlePreview"
@change="handleUpload"
@remove="deleteImageHandler"
>
<div class="upload-trigger" v-if="fileList.length === 0">
<BoxIcon class="upload-icon" />
<span class="upload-text">Click to Upload</span>
</div>
</n-upload>
<n-modal <div v-else class="preview-container clickable-image">
v-model:show="showModal" <div>
preset="card" <img
style="width: 600px" :src="fileList[0].url"
title="Preview" alt="Preview"
@after-leave="onModalClose" class="preview-image"
> @click="triggerFileInput"
<img />
:src="previewImageUrl" </div>
style="width: 100%; max-height: 600px; object-fit: contain" <div class="button-container-evenly button-gap">
alt="Preview" <n-button type="primary" @click="handlePreview(fileList[0])">Preview</n-button>
/> <n-button type="error" @click="deleteImageHandler">Delete</n-button>
</n-modal> </div>
</div>
</div> </div>
<n-modal v-model:show="showModal" preset="card" title="Preview" @after-leave="onModalClose" class="image-preview-modal">
<img :src="previewImageUrl" alt="Preview" class="preview-modal-image"/>
</n-modal>
<n-modal v-model:show="showConfirmDelete" preset="dialog" title="Confirmation"> <n-modal v-model:show="showConfirmDelete" preset="dialog" title="Confirmation">
<template #default> <template #default>
<p>Confirm delete image</p> <p>Confirm delete image</p>
@ -140,13 +153,22 @@ const cancelDelete = () => {
<n-button @click="cancelDelete">Cancel</n-button> <n-button @click="cancelDelete">Cancel</n-button>
</template> </template>
</n-modal> </n-modal>
<input
ref="fileInput"
type="file"
accept="image/*"
style="display: none"
@change="onFileInputChange"
/>
</template> </template>
<style scoped> <style scoped>
.upload-trigger { .upload-wrapper {
width: 300px; width: 300px;
max-height: 600px; max-width: 300px;
min-height: 180px; height: 300px;
max-height: 300px;
border: 1px dashed #ccc; border: 1px dashed #ccc;
border-radius: 8px; border-radius: 8px;
background-color: #fafafa; background-color: #fafafa;
@ -160,14 +182,16 @@ const cancelDelete = () => {
border-color 0.2s ease; border-color 0.2s ease;
} }
.upload-trigger:hover { .upload-wrapper:hover {
border-color: #18a058; border-color: #18a058;
background-color: #f0fdf4; background-color: #f0fdf4;
} }
.upload-icon { .upload-icon {
width: 150px; width: 150px;
max-width: 150px;
height: 150px; height: 150px;
max-height: 150px;
opacity: 0.6; opacity: 0.6;
} }
@ -175,6 +199,32 @@ const cancelDelete = () => {
margin-top: 8px; margin-top: 8px;
font-size: 14px; font-size: 14px;
color: #555; color: #555;
background-color: rgba(24, 160, 88, 0.4);
padding: 6px 12px;
border-radius: 6px;
display: inline-block;
} }
.preview-container {
display: block;
width: 100%;
max-width: 400px;
margin: 0 auto;
}
.preview-image {
width: 100%;
height: auto;
display: block;
max-width: 100%;
object-fit: contain;
}
.clickable-image {
cursor: pointer;
transition: opacity 0.2s;
}
.clickable-image:hover {
opacity: 0.9;
}
</style> </style>

View file

@ -108,7 +108,7 @@ const insertAutoCompletedLink = () => {
</script> </script>
<template> <template>
<div v-if="props.origin === 'mandarake'" class="center-button-container mb-10"> <div v-if="props.origin === 'mandarake'" class="button-container-center mb-10">
<n-button type="warning" class="center-button" @click="insertAutoCompletedLink" <n-button type="warning" class="center-button" @click="insertAutoCompletedLink"
>Insert auto-completed link</n-button >Insert auto-completed link</n-button
> >
@ -127,7 +127,7 @@ const insertAutoCompletedLink = () => {
<n-button size="small" type="primary" :loading="loading" @click="save">Save</n-button> <n-button size="small" type="primary" :loading="loading" @click="save">Save</n-button>
<n-button size="small" @click="cancel">Cancel</n-button> <n-button size="small" @click="cancel">Cancel</n-button>
</div> </div>
<div class="center-button-container"> <div class="button-container-center">
<n-button type="error" class="center-button" @click="clearLink">Clear link</n-button> <n-button type="error" class="center-button" @click="clearLink">Clear link</n-button>
</div> </div>

View file

@ -48,7 +48,7 @@ const onLogout = () => {
{{ formattedDate }} {{ formattedDate }}
</n-thing> </n-thing>
</n-list-item> </n-list-item>
<div class="center-button-container"> <div class="button-container-center">
<n-button type="info" class="center-button" @click="onLogout">Log out</n-button> <n-button type="info" class="center-button" @click="onLogout">Log out</n-button>
</div> </div>
</n-list> </n-list>