chore(photos): simplify photo components
This commit is contained in:
@@ -35,7 +35,7 @@
|
||||
@end="handleReorder"
|
||||
>
|
||||
<template #item="{ element, index }">
|
||||
<div class="photo-wrapper">
|
||||
<div class="photo-wrapper" @click.stop="toggleMobileControls(index)">
|
||||
<div class="index-bubble">{{ index + 1 }}</div>
|
||||
<img :src="element.url" :alt="'Image ' + (index + 1)" />
|
||||
<!-- Processing spinner overlay -->
|
||||
@@ -52,20 +52,23 @@
|
||||
<button @click.stop="moveImage(index, 'up')"
|
||||
class="action-btn left-btn"
|
||||
:disabled="index === 0"
|
||||
:title="t('moveUp')">
|
||||
:title="t('moveUp')"
|
||||
:class="{'mobile-active': activePhotoIndex === index}">
|
||||
<v-icon>mdi-arrow-left</v-icon>
|
||||
</button>
|
||||
<!-- Right arrow -->
|
||||
<button @click.stop="moveImage(index, 'down')"
|
||||
class="action-btn right-btn"
|
||||
:disabled="index === localImages.length - 1"
|
||||
:title="t('moveDown')">
|
||||
:title="t('moveDown')"
|
||||
:class="{'mobile-active': activePhotoIndex === index}">
|
||||
<v-icon>mdi-arrow-right</v-icon>
|
||||
</button>
|
||||
<!-- Delete button -->
|
||||
<button @click.stop="deleteImage(index)"
|
||||
class="action-btn delete-btn"
|
||||
:title="t('delete')">
|
||||
:title="t('delete')"
|
||||
:class="{'mobile-active': activePhotoIndex === index}">
|
||||
<v-icon>mdi-delete</v-icon>
|
||||
</button>
|
||||
</div>
|
||||
@@ -77,7 +80,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ref, onMounted, onUnmounted } from "vue";
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import draggable from 'vuedraggable';
|
||||
|
||||
@@ -93,6 +96,7 @@ const emit = defineEmits(['update:images']);
|
||||
const { t } = useI18n();
|
||||
const fileInput = ref(null);
|
||||
const localImages = ref([]);
|
||||
const activePhotoIndex = ref(null); // Track which photo is currently active for mobile
|
||||
|
||||
onMounted(() => {
|
||||
// Initialize local images with IDs and states
|
||||
@@ -103,8 +107,32 @@ onMounted(() => {
|
||||
isUploading: false,
|
||||
file: null // Store the actual file for upload
|
||||
}));
|
||||
|
||||
// Add event listener to close active controls when clicking outside
|
||||
document.addEventListener('click', closeActiveControls);
|
||||
});
|
||||
|
||||
// Close active controls when component is unmounted
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('click', closeActiveControls);
|
||||
});
|
||||
|
||||
// Function to handle mobile control visibility
|
||||
function toggleMobileControls(index) {
|
||||
// If clicking the same photo, toggle the controls
|
||||
if (activePhotoIndex.value === index) {
|
||||
activePhotoIndex.value = null;
|
||||
} else {
|
||||
// Otherwise, set this photo as active
|
||||
activePhotoIndex.value = index;
|
||||
}
|
||||
}
|
||||
|
||||
// Close active controls when clicking outside
|
||||
function closeActiveControls() {
|
||||
activePhotoIndex.value = null;
|
||||
}
|
||||
|
||||
// Trigger file input click
|
||||
function triggerFileInput() {
|
||||
fileInput.value.click();
|
||||
@@ -161,11 +189,13 @@ function handleFileUpload(event) {
|
||||
// Delete an image
|
||||
function deleteImage(index) {
|
||||
localImages.value.splice(index, 1);
|
||||
activePhotoIndex.value = null; // Reset active photo
|
||||
emit('update:images', localImages.value.map(img => img.url));
|
||||
}
|
||||
|
||||
// Handle reorder after drag and drop
|
||||
function handleReorder() {
|
||||
activePhotoIndex.value = null; // Reset active photo
|
||||
emit('update:images', localImages.value.map(img => img.url));
|
||||
}
|
||||
|
||||
@@ -176,6 +206,7 @@ function moveImage(index, direction) {
|
||||
const temp = localImages.value[index];
|
||||
localImages.value[index] = localImages.value[newIndex];
|
||||
localImages.value[newIndex] = temp;
|
||||
activePhotoIndex.value = newIndex; // Keep the moved image active
|
||||
emit('update:images', localImages.value.map(img => img.url));
|
||||
}
|
||||
}
|
||||
@@ -229,6 +260,7 @@ function moveImage(index, direction) {
|
||||
@apply rounded-lg;
|
||||
@apply overflow-hidden;
|
||||
@apply bg-gray-100;
|
||||
@apply cursor-pointer;
|
||||
}
|
||||
|
||||
.photo-wrapper img {
|
||||
@@ -253,7 +285,15 @@ function moveImage(index, direction) {
|
||||
@apply z-10;
|
||||
}
|
||||
|
||||
.photo-wrapper:hover .action-btn {
|
||||
/* Show buttons on hover for desktop */
|
||||
@media (hover: hover) {
|
||||
.photo-wrapper:hover .action-btn {
|
||||
@apply opacity-100;
|
||||
}
|
||||
}
|
||||
|
||||
/* For mobile, show buttons when photo is active */
|
||||
.action-btn.mobile-active {
|
||||
@apply opacity-100;
|
||||
}
|
||||
|
||||
@@ -325,52 +365,4 @@ function moveImage(index, direction) {
|
||||
.loading-overlay.uploading {
|
||||
@apply bg-opacity-75;
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n>
|
||||
{
|
||||
"en": {
|
||||
"upload": "Upload Photos",
|
||||
"delete": "Delete",
|
||||
"dropzoneText": "Click or drag photos here to upload",
|
||||
"moveUp": "Move Left",
|
||||
"moveDown": "Move Right",
|
||||
"uploading": "Uploading...",
|
||||
"creator": {
|
||||
"sections": {
|
||||
"album": {
|
||||
"title": "Photos"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fr": {
|
||||
"upload": "Télécharger des photos",
|
||||
"delete": "Supprimer",
|
||||
"dropzoneText": "Cliquez ou glissez-déposez les photos ici",
|
||||
"moveUp": "Déplacer à gauche",
|
||||
"moveDown": "Déplacer à droite",
|
||||
"creator": {
|
||||
"sections": {
|
||||
"album": {
|
||||
"title": "Photos"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"es": {
|
||||
"upload": "Subir fotos",
|
||||
"delete": "Eliminar",
|
||||
"dropzoneText": "Haga clic o arrastre las fotos aquí",
|
||||
"moveUp": "Mover a la izquierda",
|
||||
"moveDown": "Mover a la derecha",
|
||||
"creator": {
|
||||
"sections": {
|
||||
"album": {
|
||||
"title": "Fotos"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
</style>
|
||||
Reference in New Issue
Block a user