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>