From 6e7359aebf3ef8807ed4c91874f70e5223126b65 Mon Sep 17 00:00:00 2001
From: Thomas Citharel <tcit@tcit.fr>
Date: Tue, 16 Aug 2022 13:59:37 +0200
Subject: [PATCH] Homepage cards improvements

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
---
 js/src/components/Event/EventCard.vue    |  6 +-
 js/src/components/Local/CloseContent.vue | 34 ++++++-----
 js/src/components/Local/LastEvents.vue   | 76 ++++++++++++++++++++++++
 js/src/components/Local/MoreContent.vue  |  3 +-
 js/src/views/HomeView.vue                | 73 +----------------------
 js/src/views/SearchView.vue              |  2 +-
 6 files changed, 103 insertions(+), 91 deletions(-)
 create mode 100644 js/src/components/Local/LastEvents.vue

diff --git a/js/src/components/Event/EventCard.vue b/js/src/components/Event/EventCard.vue
index 069229c9c..c2c9dcfb2 100644
--- a/js/src/components/Event/EventCard.vue
+++ b/js/src/components/Event/EventCard.vue
@@ -1,9 +1,9 @@
 <template>
   <router-link
-    class="mbz-card max-w-xs"
+    class="mbz-card max-w-xs shrink-0 w-[18rem] snap-center"
     :to="{ name: RouteName.EVENT, params: { uuid: event.uuid } }"
   >
-    <div class="bg-secondary">
+    <div class="bg-secondary rounded-lg">
       <figure class="block relative pt-40">
         <lazy-image-wrapper
           :picture="event.picture"
@@ -35,7 +35,7 @@
         </div>
       </figure>
     </div>
-    <div class="h-full p-2">
+    <div class="p-2">
       <div class="relative flex flex-col h-full">
         <div class="-mt-3 h-0 flex mb-3 ltr:ml-0 rtl:mr-0 items-end self-start">
           <date-calendar-icon
diff --git a/js/src/components/Local/CloseContent.vue b/js/src/components/Local/CloseContent.vue
index d705f87c2..3a8f77b42 100644
--- a/js/src/components/Local/CloseContent.vue
+++ b/js/src/components/Local/CloseContent.vue
@@ -1,18 +1,22 @@
 <template>
   <div class="relative pt-10 px-2">
-    <div class="w-full flex flex-wrap gap-3 mb-2 items-center">
-      <h1
-        class="text-xl font-bold tracking-tight text-gray-900 dark:text-gray-100"
-      >
-        <slot name="title" />
-      </h1>
-      <button
-        v-if="suggestGeoloc && isIPLocation"
-        class="inline-flex bg-primary rounded text-white flex-initial px-4 py-2 justify-center w-full md:w-min whitespace-nowrap"
-        @click="emit('doGeoLoc')"
-      >
-        {{ t("Geolocate me") }}
-      </button>
+    <div class="mb-2">
+      <div class="w-full flex flex-wrap gap-3 items-center">
+        <h2
+          class="text-xl font-bold tracking-tight text-gray-900 dark:text-gray-100"
+        >
+          <slot name="title" />
+        </h2>
+
+        <button
+          v-if="suggestGeoloc && isIPLocation"
+          class="inline-flex bg-primary rounded text-white flex-initial px-4 py-2 justify-center w-full md:w-min whitespace-nowrap"
+          @click="emit('doGeoLoc')"
+        >
+          {{ t("Geolocate me") }}
+        </button>
+      </div>
+      <slot name="subtitle" />
     </div>
     <div class="hidden sm:block" v-show="showScrollLeftButton">
       <button
@@ -24,7 +28,7 @@
     </div>
     <div class="overflow-hidden">
       <div
-        class="relative w-full snap-x overflow-x-auto pb-6 grid auto-rows-[1fr] gap-x-5 gap-y-8 grid-cols-[repeat(auto-fill,_minmax(250px,_1fr))]"
+        class="relative w-full snap-x snap-always snap-mandatory overflow-x-auto flex pb-6 gap-x-5 gap-y-8"
         ref="scrollContainer"
         @scroll="scrollHandler"
       >
@@ -99,7 +103,7 @@ const scrollRight = (e: Event) => {
 };
 
 const scrollHorizontalToVertical = (evt: WheelEvent) => {
-  evt.deltaY > 0 ? doScroll(evt, 600) : doScroll(evt, -600);
+  evt.deltaY > 0 ? doScroll(evt, 300) : doScroll(evt, -300);
 };
 
 onMounted(async () => {
diff --git a/js/src/components/Local/LastEvents.vue b/js/src/components/Local/LastEvents.vue
new file mode 100644
index 000000000..0001a7f34
--- /dev/null
+++ b/js/src/components/Local/LastEvents.vue
@@ -0,0 +1,76 @@
+<template>
+  <close-content
+    v-show="loadingEvents || (events && events.total > 0)"
+    :suggestGeoloc="false"
+    v-on="attrs"
+  >
+    <template #title>
+      {{ t("Last published events") }}
+    </template>
+    <template #subtitle>
+      <i18n-t
+        class="text-slate-700 dark:text-slate-300"
+        tag="p"
+        keypath="On {instance} and other federated instances"
+      >
+        <template #instance>
+          <b>{{ instanceName }}</b>
+        </template>
+      </i18n-t>
+    </template>
+    <template #content>
+      <skeleton-event-result
+        v-for="i in 6"
+        class="scroll-ml-6 snap-center shrink-0 w-[18rem] my-4"
+        :key="i"
+        v-show="loadingEvents"
+      />
+      <event-card
+        v-for="event in events.elements"
+        :event="event"
+        :key="event.uuid"
+      />
+      <more-content
+        :to="{
+          name: 'SEARCH',
+          query: {
+            contentType: 'EVENTS',
+          },
+        }"
+      >
+        {{ t("View more events") }}
+      </more-content>
+    </template>
+  </close-content>
+</template>
+
+<script lang="ts" setup>
+import MoreContent from "./MoreContent.vue";
+import CloseContent from "./CloseContent.vue";
+import { computed, useAttrs } from "vue";
+import { IEvent } from "@/types/event.model";
+import { useQuery } from "@vue/apollo-composable";
+import EventCard from "../Event/EventCard.vue";
+import { Paginate } from "@/types/paginate";
+import SkeletonEventResult from "../Event/SkeletonEventResult.vue";
+import { EventSortField, SortDirection } from "@/types/enums";
+import { FETCH_EVENTS } from "@/graphql/event";
+import { useI18n } from "vue-i18n";
+
+defineProps<{
+  instanceName: string;
+}>();
+
+const { t } = useI18n({ useScope: "global" });
+const attrs = useAttrs();
+
+const { result: resultEvents, loading: loadingEvents } = useQuery<{
+  events: Paginate<IEvent>;
+}>(FETCH_EVENTS, {
+  orderBy: EventSortField.INSERTED_AT,
+  direction: SortDirection.DESC,
+});
+const events = computed(
+  () => resultEvents.value?.events ?? { total: 0, elements: [] }
+);
+</script>
diff --git a/js/src/components/Local/MoreContent.vue b/js/src/components/Local/MoreContent.vue
index 1f13ff471..743e8fb24 100644
--- a/js/src/components/Local/MoreContent.vue
+++ b/js/src/components/Local/MoreContent.vue
@@ -60,12 +60,11 @@
 </template>
 <script lang="ts" setup>
 import { computed } from "vue";
-import { RouteLocationNormalizedLoaded } from "vue-router";
 import { CategoryPictureLicencing } from "../Categories/constants";
 
 const props = defineProps<{
   to: { name: string; query: Record<string, string> };
-  picture: CategoryPictureLicencing & { url: string };
+  picture?: CategoryPictureLicencing & { url: string };
 }>();
 
 const imageAuthor = computed(
diff --git a/js/src/views/HomeView.vue b/js/src/views/HomeView.vue
index 7c693c28b..1833f77a9 100644
--- a/js/src/views/HomeView.vue
+++ b/js/src/views/HomeView.vue
@@ -216,77 +216,9 @@
           >
         </span>
       </section>
-      <hr
-        role="presentation"
-        class="home-separator"
-        v-if="canShowFollowedGroupEvents"
-      />
 
-      <!-- Events close to you -->
-      <!-- <section class="events-close" v-if="canShowCloseEvents && radius">
-        <h2 class="title">
-          {{ $t("Events nearby") }}
-        </h2>
-        <p>
-          {{
-            $t("Within {number} kilometers of {place}", {
-              radius,
-              place: locationName,
-            }, radius)
-          }}
-          <router-link
-            :to="{ name: RouteName.PREFERENCES }"
-            :title="$t('Change')"
-          >
-            <o-icon class="clickable" icon="pencil" size="small" />
-          </router-link>
-        </p>
-        <multi-card :events="closeEvents.elements.slice(0, 4)" />
-      </section> -->
-      <hr
-        role="presentation"
-        class="home-separator"
-        v-if="canShowMyUpcomingEvents"
-      />
-      <section class="events-recent px-2">
-        <h2 class="dark:text-white text-2xl font-bold">
-          {{ $t("Last published events") }}
-        </h2>
-        <p class="mb-3">
-          <i18n-t
-            class="text-slate-700 dark:text-slate-300"
-            tag="span"
-            keypath="On {instance} and other federated instances"
-          >
-            <template #instance>
-              <b>{{ config.name }}</b>
-            </template>
-          </i18n-t>
-        </p>
-
-        <div v-if="events && events.total > 0">
-          <multi-card :events="events.elements.slice(0, 8)" />
-          <span
-            class="block mt-2 text-right underline text-slate-700 dark:text-slate-300"
-          >
-            <router-link
-              :to="{ name: RouteName.SEARCH }"
-              class="hover:text-slate-800 hover:dark:text-slate-400"
-              >{{ $t("View everything") }} >></router-link
-            >
-          </span>
-        </div>
-        <o-notification v-else variant="danger"
-          >{{ $t("No events found") }}<br />
-          <div v-if="goingToEvents.size > 0">
-            <InformationOutline :size="16" />
-            <small>{{
-              $t("The events you created are not shown here.")
-            }}</small>
-          </div>
-        </o-notification>
-      </section>
-      <close-events @doGeoLoc="performGeoLocation()" />
+      <CloseEvents @doGeoLoc="performGeoLocation()" />
+      <LastEvents :instanceName="config.name" class="mb-10" />
     </div>
   </div>
 </template>
@@ -314,6 +246,7 @@ import { CONFIG } from "../graphql/config";
 import { IConfig } from "../types/config.model";
 // import { IFollowedGroupEvent } from "../types/followedGroupEvent.model";
 import CloseEvents from "@/components/Local/CloseEvents.vue";
+import LastEvents from "@/components/Local/LastEvents.vue";
 import { computed, onMounted, reactive, watch } from "vue";
 import { useMutation, useQuery } from "@vue/apollo-composable";
 import { useRouter } from "vue-router";
diff --git a/js/src/views/SearchView.vue b/js/src/views/SearchView.vue
index e3c19e49c..ef97def1e 100644
--- a/js/src/views/SearchView.vue
+++ b/js/src/views/SearchView.vue
@@ -540,7 +540,7 @@ const searchVariables = reactive({
   groupPage: groupPage,
   limit: EVENT_PAGE_LIMIT,
   type: type.value === "" ? undefined : type,
-  eventCategory: eventCategory,
+  category: eventCategory,
 });
 
 const {