From 0bc7e794e91b3bad6c5b835b3ad08b28ebfd2166 Mon Sep 17 00:00:00 2001 From: xcexec <hattori.hansa@protonmail.com> Date: Tue, 22 Oct 2024 08:40:37 +0200 Subject: [PATCH] EventImageModal feature --- src/components/Event/EventImageModal.vue | 65 +++++++++++++++++++ src/components/Event/EventMetadataSidebar.vue | 53 ++++++++++++++- 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/components/Event/EventImageModal.vue diff --git a/src/components/Event/EventImageModal.vue b/src/components/Event/EventImageModal.vue new file mode 100644 index 000000000..5aafc3b6d --- /dev/null +++ b/src/components/Event/EventImageModal.vue @@ -0,0 +1,65 @@ +<template> + <div class="modal-overlay" @click.self="closeModal"> + <div class="modal-content"> + <img :src="image" alt="Full-size event banner" /> + <button class="close-button" @click="closeModal">X</button> + </div> + </div> + </template> + + <script setup lang="ts"> + const props = defineProps<{ + image: string; + }>(); + + const emit = defineEmits(['close']); + + const closeModal = () => { + emit('close'); + }; + </script> + + <style> + .modal-overlay { + position: fixed !important; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.8); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000000 !important; + } + + .modal-content { + position: relative; + max-width: 90%; + max-height: 90%; + } + + @media (max-width: 600px) { + .modal-content { + max-width: 80%; + max-height: 80%; + } +} + + .modal-content img { + width: 100%; + height: auto; + object-fit: contain; + } + + .close-button { + position: absolute; + top: 10px; + right: 10px; + background-color: transparent; + border: none; + color: white; + font-size: 24px; + cursor: pointer; + } + </style> \ No newline at end of file diff --git a/src/components/Event/EventMetadataSidebar.vue b/src/components/Event/EventMetadataSidebar.vue index 051943a0b..49234989a 100644 --- a/src/components/Event/EventMetadataSidebar.vue +++ b/src/components/Event/EventMetadataSidebar.vue @@ -154,13 +154,32 @@ > <span v-else>{{ extra.value }}</span> </event-metadata-block> + <event-metadata-block + v-if="isUserUploadedImage" + :title="t('Title Picture')" + > + <!-- Event Banner Component, only displayed if user uploaded image --> + <div class="clickable-banner" @click="showBannerFullScreen"> + <event-banner :picture="event.picture" /> + </div> + </event-metadata-block> + + <!-- Modal to display full-screen image --> + <Teleport to=body> + <event-image-modal + v-if="showFullScreen" + :image="event.picture.url" + @close="showFullScreen = false" + /> + </Teleport> </div> </template> + <script lang="ts" setup> import { Address, addressToPoiInfos } from "@/types/address.model"; import { EventMetadataKeyType, EventMetadataType } from "@/types/enums"; import { IEvent } from "@/types/event.model"; -import { computed } from "vue"; +import { computed, ref } from "vue"; import RouteName from "../../router/name"; import { usernameWithDomain } from "../../types/actor"; import EventMetadataBlock from "./EventMetadataBlock.vue"; @@ -174,6 +193,8 @@ import { useI18n } from "vue-i18n"; import Earth from "vue-material-design-icons/Earth.vue"; import Calendar from "vue-material-design-icons/Calendar.vue"; import Link from "vue-material-design-icons/Link.vue"; +import EventBanner from "@/components/Event/EventBanner.vue"; +import EventImageModal from "@/components/Event/EventImageModal.vue"; const props = withDefaults( defineProps<{ @@ -242,7 +263,22 @@ const accountURL = (extra: IEventMetadataDescription): string | undefined => { const userTimezone = computed((): string | undefined => { return props.user?.settings?.timezone; }); + +/** Define the default image URL */ +const DEFAULT_CARD_URL = "/img/mobilizon_default_card.png"; + +/** Computed property to check if the image is a user-uploaded image */ +const isUserUploadedImage = computed(() => { + return props.event.picture?.url && props.event.picture.url !== DEFAULT_CARD_URL; +}); + +/** Handle click to show banner in full-screen */ +const showFullScreen = ref(false); +const showBannerFullScreen = () => { + showFullScreen.value = true; // Open full-screen modal +}; </script> + <style lang="scss" scoped> :deep(.metadata-organized-by) { .v-popover.popover .trigger { @@ -272,4 +308,19 @@ div.address-wrapper { } } } + +.clickable-banner { + max-width: 150px; + height: auto; + max-height: 150px; /* Constrain image size */ + overflow: hidden; + cursor: pointer; + object-fit: contain; + + img { + width: 100%; + height: auto; + object-fit: cover; /* Ensure the image fits within the constrained area */ + } +} </style>