161 lines
4.2 KiB
Vue
161 lines
4.2 KiB
Vue
<script setup>
|
|
import EmbeddedMap from "components/map/EmbeddedMap.vue";
|
|
import {computed, onMounted, ref} from "vue";
|
|
import {formatDatetime} from "src/composables/datetimeUtils";
|
|
import 'vue-inner-image-zoom/lib/vue-inner-image-zoom.css'
|
|
|
|
const props = defineProps({
|
|
photos: {
|
|
type: Array,
|
|
required: false,
|
|
default: () => []
|
|
},
|
|
openedIndex: {
|
|
type: Number,
|
|
required: false,
|
|
},
|
|
modelValue: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: false
|
|
}
|
|
});
|
|
|
|
const emit = defineEmits(["update:modelValue"])
|
|
|
|
|
|
const open = computed({
|
|
get() {
|
|
return props.modelValue;
|
|
},
|
|
set(newVal) {
|
|
emit("update:modelValue", newVal);
|
|
}
|
|
})
|
|
|
|
const photoIndex = ref(null);
|
|
onMounted(() => {
|
|
photoIndex.value = props.openedIndex
|
|
});
|
|
|
|
const photo = computed(() => props.photos[photoIndex.value]);
|
|
|
|
const nextPhoto = () => {
|
|
if (photoIndex.value < props.photos.length - 1)
|
|
photoIndex.value++
|
|
}
|
|
|
|
const prevPhoto = () => {
|
|
if (photoIndex.value > 0) photoIndex.value--;
|
|
}
|
|
|
|
const showExtra = ref(false);
|
|
</script>
|
|
|
|
<template>
|
|
<q-dialog
|
|
v-model="open"
|
|
full-width
|
|
>
|
|
<q-card
|
|
v-touch-swipe.mouse.left="prevPhoto"
|
|
v-touch-swipe.mouse.right="nextPhoto"
|
|
@keyup.left="prevPhoto"
|
|
@keyup.right="nextPhoto"
|
|
>
|
|
<q-card-section>
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="text-center">
|
|
<inner-image-zoom move-type="pan" :zoomScale="0.75" :hide-hint="true" :src="photo.url"/>
|
|
</div>
|
|
|
|
<q-btn
|
|
class="absolute all-pointer-events"
|
|
round
|
|
flat
|
|
icon="info"
|
|
:text-color="showExtra ? 'primary' : 'white'"
|
|
style="background: rgba(0, 0, 0, 0.25); top: 8px; right: 8px"
|
|
@click="showExtra = !showExtra"
|
|
/>
|
|
<q-btn
|
|
class="absolute all-pointer-events"
|
|
style="background: rgba(0, 0, 0, 0.25); top: 50%; left: 8px;"
|
|
@click="prevPhoto"
|
|
v-if="photoIndex > 0"
|
|
icon="chevron_left"
|
|
text-color="white"
|
|
flat
|
|
rounded
|
|
>
|
|
</q-btn>
|
|
<q-btn
|
|
class="absolute all-pointer-events"
|
|
style="background: rgba(0, 0, 0, 0.25); top: 50%; right: 8px;"
|
|
@click="nextPhoto"
|
|
v-if="photoIndex < photos.length - 1"
|
|
icon-right="chevron_right"
|
|
text-color="white"
|
|
flat
|
|
rounded
|
|
>
|
|
</q-btn>
|
|
<strong v-if="photo.name !== ''">{{ photo.name }}</strong>
|
|
<p v-if="photo.description !== ''">{{ photo.description }}</p>
|
|
</div>
|
|
|
|
<div class="col-12 q-my-md" v-if="showExtra">
|
|
<EmbeddedMap
|
|
v-if="photo.gpsLatitude && photo.gpsLongitude"
|
|
class="q-mx-sm"
|
|
:gps-latitude="photo.gpsLatitude"
|
|
:gps-longitude="photo.gpsLongitude"
|
|
/>
|
|
|
|
<q-list dense>
|
|
<q-item v-if="photo.pointOfInterest">
|
|
<q-item-section avatar>
|
|
<q-avatar icon="marker"></q-avatar>
|
|
</q-item-section>
|
|
<q-item-section>
|
|
{{ formatDatetime(photo.exposedAt) }}
|
|
</q-item-section>
|
|
</q-item>
|
|
<q-item v-if="photo.exposedAt">
|
|
<q-item-section avatar>
|
|
<q-avatar icon="photo_camera"></q-avatar>
|
|
</q-item-section>
|
|
<q-item-section>
|
|
{{ formatDatetime(photo.exposedAt) }}
|
|
</q-item-section>
|
|
</q-item>
|
|
|
|
<q-item v-if="photo.gpsAltitude">
|
|
<q-item-section avatar>
|
|
<q-avatar icon="height"/>
|
|
</q-item-section>
|
|
<q-item-section>
|
|
{{ photo.gpsAltitude }} m
|
|
</q-item-section>
|
|
</q-item>
|
|
</q-list>
|
|
</div>
|
|
</div>
|
|
</q-card-section>
|
|
</q-card>
|
|
</q-dialog>
|
|
</template>
|
|
|
|
<style>
|
|
.iiz {
|
|
width: 100%;
|
|
height: 90vh;
|
|
}
|
|
|
|
.iiz__img {
|
|
max-height: 90vh !important;
|
|
margin: 0 auto;
|
|
}
|
|
</style>
|