Update modal and image viewer with simpler carousel
This commit is contained in:
parent
ffe6bd4409
commit
5347bf0023
|
|
@ -1,34 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col items-center justify-center h-full">
|
<div class="flex flex-col h-full">
|
||||||
<div class="relative w-full flex-1 flex items-center justify-center min-h-0 p-4">
|
<div class="relative h-[60vh] w-full flex items-center justify-center">
|
||||||
<!-- Previous button -->
|
|
||||||
<button
|
|
||||||
v-if="gallery.length > 1"
|
|
||||||
@click="prev"
|
|
||||||
class="absolute left-2 z-10 p-2 bg-gray-600 rounded-full text-white hover:bg-gray-700"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:chevron-left" class="w-6 h-6" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Image -->
|
<!-- Image -->
|
||||||
<NuxtImg
|
<NuxtImg
|
||||||
v-if="gallery[currentIndex]"
|
v-if="gallery[currentIndex]"
|
||||||
:src="'/' + bucket + '/' + gallery[currentIndex].image"
|
:src="'/' + bucket + '/' + gallery[currentIndex].image"
|
||||||
class="max-w-full max-h-[60vh] object-contain"
|
class="max-w-full max-h-full object-contain"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Next button -->
|
|
||||||
<button
|
|
||||||
v-if="gallery.length > 1"
|
|
||||||
@click="next"
|
|
||||||
class="absolute right-2 z-10 p-2 bg-gray-600 rounded-full text-white hover:bg-gray-700"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:chevron-right" class="w-6 h-6" />
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Dots indicator -->
|
<!-- Dots indicator -->
|
||||||
<div v-if="gallery.length > 1" class="flex gap-2 py-2">
|
<div v-if="gallery.length > 1" class="flex gap-2 py-2 justify-center">
|
||||||
<button
|
<button
|
||||||
v-for="(img, index) in gallery"
|
v-for="(img, index) in gallery"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
|
@ -52,11 +34,7 @@ const props = defineProps({
|
||||||
|
|
||||||
const currentIndex = ref(props.initialIndex)
|
const currentIndex = ref(props.initialIndex)
|
||||||
|
|
||||||
const next = () => {
|
watch(() => props.initialIndex, (newVal) => {
|
||||||
currentIndex.value = (currentIndex.value + 1) % props.gallery.length
|
currentIndex.value = newVal
|
||||||
}
|
})
|
||||||
|
|
||||||
const prev = () => {
|
|
||||||
currentIndex.value = (currentIndex.value - 1 + props.gallery.length) % props.gallery.length
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ provide('modal', api)
|
||||||
leave-to="opacity-0 scale-95"
|
leave-to="opacity-0 scale-95"
|
||||||
>
|
>
|
||||||
<DialogPanel
|
<DialogPanel
|
||||||
class="w-full transform overflow-hidden bg-white text-left align-middle shadow-xl transition-all"
|
class="w-full transform overflow-hidden bg-white text-left align-middle shadow-xl transition-all py-4"
|
||||||
:class="{
|
:class="{
|
||||||
'h-screen': fullscreen,
|
'h-screen': fullscreen,
|
||||||
'max-w-[min(85vw,1200px)] rounded-lg': !fullscreen,
|
'max-w-[min(85vw,1200px)] rounded-lg': !fullscreen,
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,17 @@
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<Modal v-model="modalStore.isOpen" :maxHeight="modalStore.type === 'image' && modalStore.soundcloudUrl ? 'calc(85vh + 60px)' : '85vh'">
|
<Modal v-model="modalStore.isOpen" :maxHeight="modalStore.type === 'image' && modalStore.soundcloudUrl ? 'calc(85vh + 60px)' : '85vh'">
|
||||||
<div class="flex flex-col h-full overflow-hidden">
|
<div class="flex flex-col h-full overflow-hidden relative">
|
||||||
|
<!-- Navigation buttons for images - fixed to modal -->
|
||||||
|
<template v-if="modalStore.type === 'image' && modalStore.gallery && modalStore.gallery.length > 1">
|
||||||
|
<button @click="prevImage" class="absolute left-2 top-1/2 -translate-y-1/2 z-20 text-gray-600 hover:text-gray-900">
|
||||||
|
<Icon name="mdi:chevron-left" class="w-10 h-10" />
|
||||||
|
</button>
|
||||||
|
<button @click="nextImage" class="absolute right-2 top-1/2 -translate-y-1/2 z-20 text-gray-600 hover:text-gray-900">
|
||||||
|
<Icon name="mdi:chevron-right" class="w-10 h-10" />
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
<div v-if="modalStore.type === 'image'" class="flex-1 flex items-center justify-center min-h-0">
|
<div v-if="modalStore.type === 'image'" class="flex-1 flex items-center justify-center min-h-0">
|
||||||
<ImageViewer :bucket="modalStore.bucket" :gallery="modalStore.gallery" :initialIndex="modalStore.initialIndex"></ImageViewer>
|
<ImageViewer :bucket="modalStore.bucket" :gallery="modalStore.gallery" :initialIndex="modalStore.initialIndex"></ImageViewer>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -108,7 +118,7 @@
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="modalStore.type === 'pdf' || modalStore.type === 'image' || modalStore.type === 'document'" class="absolute bottom-2 right-2 z-10">
|
<div v-if="modalStore.type === 'pdf' || modalStore.type === 'image' || modalStore.type === 'document'" class="absolute bottom-0 right-0 p-4 z-10">
|
||||||
<a :href="modalStore.type === 'pdf' ? modalStore.pdfUrl : modalStore.type === 'image' ? '/' + modalStore.bucket + '/' + modalStore.gallery[0]?.image : modalStore.type === 'document' ? modalStore.iframeUrl : undefined" target="_blank" rel="noopener noreferrer" class="p-2 bg-gray-600 rounded-lg inline-flex items-center justify-center pointer-events-auto">
|
<a :href="modalStore.type === 'pdf' ? modalStore.pdfUrl : modalStore.type === 'image' ? '/' + modalStore.bucket + '/' + modalStore.gallery[0]?.image : modalStore.type === 'document' ? modalStore.iframeUrl : undefined" target="_blank" rel="noopener noreferrer" class="p-2 bg-gray-600 rounded-lg inline-flex items-center justify-center pointer-events-auto">
|
||||||
<Icon name="mdi:open-in-new" class="w-5 h-5 text-white" />
|
<Icon name="mdi:open-in-new" class="w-5 h-5 text-white" />
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -121,10 +131,32 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useAudioPlayerStore } from "@/stores/AudioPlayerStore"
|
import { useAudioPlayerStore } from "@/stores/AudioPlayerStore"
|
||||||
import { useModalStore } from "@/stores/ModalStore"
|
import { useModalStore } from "@/stores/ModalStore"
|
||||||
import { onMounted, computed } from "vue"
|
import { onMounted, computed, ref } from "vue"
|
||||||
|
|
||||||
const audioPlayerStore = useAudioPlayerStore()
|
const audioPlayerStore = useAudioPlayerStore()
|
||||||
const modalStore = useModalStore()
|
const modalStore = useModalStore()
|
||||||
|
|
||||||
|
const currentImageIndex = ref(0)
|
||||||
|
|
||||||
|
const prevImage = () => {
|
||||||
|
if (modalStore.gallery && modalStore.gallery.length > 0) {
|
||||||
|
currentImageIndex.value = (currentImageIndex.value - 1 + modalStore.gallery.length) % modalStore.gallery.length
|
||||||
|
modalStore.initialIndex = currentImageIndex.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextImage = () => {
|
||||||
|
if (modalStore.gallery && modalStore.gallery.length > 0) {
|
||||||
|
currentImageIndex.value = (currentImageIndex.value + 1) % modalStore.gallery.length
|
||||||
|
modalStore.initialIndex = currentImageIndex.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => modalStore.isOpen, (isOpen) => {
|
||||||
|
if (isOpen) {
|
||||||
|
currentImageIndex.value = modalStore.initialIndex || 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue