From ce629461ae2da3f12c4391865b2bbfd4686818a0 Mon Sep 17 00:00:00 2001
From: Simon Mellerin <simon.mellerin@makina-corpus.com>
Date: Tue, 24 Sep 2024 14:49:00 +0200
Subject: [PATCH] Community pages as nested routes

---
 .../OcLayoutCommunityWithTree.vue             | 40 ++++-------
 .../join.vue => [community].join.vue}         |  6 +-
 src/pages/community/[community].vue           | 21 ++++++
 src/pages/community/[community]/index.vue     | 69 +++++++++----------
 typed-router.d.ts                             |  3 +-
 5 files changed, 74 insertions(+), 65 deletions(-)
 rename src/pages/community/{[community]/join.vue => [community].join.vue} (91%)
 create mode 100644 src/pages/community/[community].vue

diff --git a/src/layout/OcLayoutCommunityWithTree/OcLayoutCommunityWithTree.vue b/src/layout/OcLayoutCommunityWithTree/OcLayoutCommunityWithTree.vue
index 1b98139..8c29fa7 100644
--- a/src/layout/OcLayoutCommunityWithTree/OcLayoutCommunityWithTree.vue
+++ b/src/layout/OcLayoutCommunityWithTree/OcLayoutCommunityWithTree.vue
@@ -2,33 +2,21 @@
   <div class="h-screen flex flex-col">
     <OcTopBar class="z-10" :is-authenticated="props.isAuthenticated" />
     <div class="flex-grow flex flex-col md:flex-row">
-      <div
-        class="relative transition-all duration-700 ease-out"
-        :class="[{ 'w-4/12': leftPanelOpened, 'w-[70px]': !leftPanelOpened }, `bg-${color}-300`]"
-      >
-        <button
-          id="toggleButton"
-          class="absolute mt-4 right-[-15px] w-[30px] h-[30px] rounded-full bg-white shadow-oc"
-          @click="leftPanelOpened = !leftPanelOpened"
-        >
-          <i
-            :class="[
-              {
-                'fa-solid fa-caret-left': leftPanelOpened,
-                'fa-solid fa-caret-right': !leftPanelOpened
-              },
-              `text-${color}-400`
-            ]"
-          />
+      <div class="relative transition-all duration-700 ease-out"
+        :class="[{ 'w-4/12': leftPanelOpened, 'w-[70px]': !leftPanelOpened }, `bg-${color}-300`]">
+        <button id="toggleButton" class="absolute mt-4 right-[-15px] w-[30px] h-[30px] rounded-full bg-white shadow-oc"
+          @click="leftPanelOpened = !leftPanelOpened">
+          <i :class="[
+            {
+              'fa-solid fa-caret-left': leftPanelOpened,
+              'fa-solid fa-caret-right': !leftPanelOpened
+            },
+            `text-${color}-400`
+          ]" />
         </button>
         <div :hidden="!leftPanelOpened">
-          <OcTreeCommunity
-            :community="community"
-            :tree-nodes="treeStore.state.data"
-            :isAuthenticated="props.isAuthenticated"
-            v-on:node-select="onNodeSelect"
-            v-on:node-expand="onNodeExpand"
-          />
+          <OcTreeCommunity :community="community" :tree-nodes="treeStore.state.data"
+            :isAuthenticated="props.isAuthenticated" v-on:node-select="onNodeSelect" v-on:node-expand="onNodeExpand" />
         </div>
       </div>
       <div class="w-full">
@@ -72,7 +60,7 @@ onBeforeMount(() => treeStore.fetchIfEmpty())
 
 function onNodeSelect(node: TreeNode) {
   if (node.uri === homeNodeUri) {
-    router.push({ name: '/:lang/community/[community]', params: { lang: locale.value, community: props.community?.name } })
+    router.push({ name: '/:lang/community/[community]/', params: { lang: locale.value, community: props.community?.name } })
   } else {
     router.push({ name: '/:lang/community/[community]/resource/[identifier]', params: { lang: locale.value, community: props.community?.name, identifier: node.key } })
   }
diff --git a/src/pages/community/[community]/join.vue b/src/pages/community/[community].join.vue
similarity index 91%
rename from src/pages/community/[community]/join.vue
rename to src/pages/community/[community].join.vue
index 3f0305f..416fa1e 100644
--- a/src/pages/community/[community]/join.vue
+++ b/src/pages/community/[community].join.vue
@@ -14,7 +14,9 @@
       </div>
 
       <div class="flex justify-center">
-        <Button rounded severity="secondary" class="">{{ t('connection.continueAsGuest') }}</Button>
+        <Button :as="OcLink" :to="'/community/' + communityName" severity="secondary" rounded>
+          {{ t('connection.continueAsGuest') }}
+        </Button>
       </div>
 
     </div>
@@ -23,7 +25,7 @@
         <i class="fa-solid fa-circle-check text-6xl text-center text-primary mb-6"></i>
         <p class="text-center mb-6">{{ t('community.askJoin.confirmation.1') }}</p>
         <p class="text-center mb-6">{{ t('community.askJoin.confirmation.2') }}</p>
-        <Button :as="OcLink" to="" severity="secondary" rounded>
+        <Button :as="OcLink" :to="'/community/' + communityName" severity="secondary" rounded>
           {{ t('connection.continueAsGuest') }}
         </Button>
       </div>
diff --git a/src/pages/community/[community].vue b/src/pages/community/[community].vue
new file mode 100644
index 0000000..f49cfb7
--- /dev/null
+++ b/src/pages/community/[community].vue
@@ -0,0 +1,21 @@
+<template>
+  <OcLayoutCommunityWithTree v-if="community" :community="community" :is-authenticated="accountStore.isAuthenticated">
+    <router-view />
+  </OcLayoutCommunityWithTree>
+</template>
+
+<script setup lang="ts">
+import OcLayoutCommunityWithTree from '@/layout/OcLayoutCommunityWithTree/OcLayoutCommunityWithTree.vue';
+import { useAccountStore } from '@/stores/account';
+import { useCommunityStore } from '@/stores/community';
+import { computed, onMounted } from 'vue';
+import { useRoute } from 'vue-router';
+
+const route = useRoute()
+const communityStore = useCommunityStore()
+const accountStore = useAccountStore()
+
+onMounted(() => communityStore.fetchIfEmpty())
+
+const community = computed(() => communityStore.getByName(route.params.community as string))
+</script>
\ No newline at end of file
diff --git a/src/pages/community/[community]/index.vue b/src/pages/community/[community]/index.vue
index f5d4c0e..67a7cb7 100644
--- a/src/pages/community/[community]/index.vue
+++ b/src/pages/community/[community]/index.vue
@@ -1,47 +1,44 @@
 <template>
-  <OcLayoutCommunityWithTree v-if="community" :community="community" :is-authenticated="accountStore.isAuthenticated">
-    <div class="p-4 pl-8 w-11/12 md:w-10/12 xl:w-9/12 m-auto">
-      <h1 :class="`font-title text-4xl uppercase font-bold mb-4 text-[--p-primary-color]`">{{ title }}</h1>
-      <h3 class="text-2xl mb-2">{{ t('community.homepage.presentationLabel') }}</h3>
-      <div class="flex flex-row gap-8">
-        <p class="text-justify w-full">{{ abstract }}</p>
-        <img v-if="logoUrl" :src="logoUrl" alt="" class="max-w-[200px] max-h-[200px] w-fit h-fit object-cover">
-      </div>
-
-      <IconField class="w-full mt-8 mb-4">
-        <InputText id="search" class="rounded-md border-none bg-[--p-primary-color] text-white w-full" size="large"
-          :placeholder="t('community.homepage.searchBarPlaceholder')" />
-        <InputIcon class="fa-solid fa-magnifying-glass text-white" />
-      </IconField>
+  <div class="p-4 pl-8 w-11/12 md:w-10/12 xl:w-9/12 m-auto">
+    <h1 :class="`font-title text-4xl uppercase font-bold mb-4 text-[--p-primary-color]`">{{ title }}</h1>
+    <h3 class="text-2xl mb-2">{{ t('community.homepage.presentationLabel') }}</h3>
+    <div class="flex flex-row gap-8">
+      <p class="text-justify w-full">{{ abstract }}</p>
+      <img v-if="logoUrl" :src="logoUrl" alt="" class="max-w-[200px] max-h-[200px] w-fit h-fit object-cover">
+    </div>
 
-      <h3 class="text-xl font-bold">
-        {{ t('community.homepage.searchBarLegend') }}
-      </h3>
-      <hr class="mt-4">
+    <IconField class="w-full mt-8 mb-4">
+      <InputText id="search" class="rounded-md border-none bg-[--p-primary-color] text-white w-full" size="large"
+        :placeholder="t('community.homepage.searchBarPlaceholder')" />
+      <InputIcon class="fa-solid fa-magnifying-glass text-white" />
+    </IconField>
 
-      <div class="flex justify-center">
-        <Button v-if="!accountStore.isAuthenticated" :as="OcLink" to="/connection" size="large"
-          :class="`bg-${color}-300 text-white border-0 mt-4 p-4 rounded-md m-auto`">
-          {{ t('community.homepage.connectButtonLabel', { communityName: title }) }}
-        </Button>
-        <Button v-else-if="!isMemberOfCurrentCommunity" :as="OcLink" :to="'/community/' + name + '/join'" size="large"
-          :class="`bg-${color}-300 text-white border-0 mt-4 p-4 rounded-md m-auto`">
-          {{ t('community.homepage.joinButtonLabel', { communityName: title }) }}
-        </Button>
-      </div>
+    <h3 class="text-xl font-bold">
+      {{ t('community.homepage.searchBarLegend') }}
+    </h3>
+    <hr class="mt-4">
 
-      <h3 v-if="!!accountStore.isAuthenticated && isMemberOfCurrentCommunity" class="text-2xl mt-8 mb-8">
-        {{ t('community.homepage.yourServices') }}
-      </h3>
-      <OcHomeActions class="mt-4"></OcHomeActions>
+    <div class="flex justify-center">
+      <Button v-if="!accountStore.isAuthenticated" :as="OcLink" to="/connection" size="large"
+        :class="`bg-${color}-300 text-white border-0 mt-4 p-4 rounded-md m-auto`">
+        {{ t('community.homepage.connectButtonLabel', { communityName: title }) }}
+      </Button>
+      <Button v-else-if="!isMemberOfCurrentCommunity" :as="OcLink" :to="'/community/' + name + '/join'" size="large"
+        :class="`bg-${color}-300 text-white border-0 mt-4 p-4 rounded-md m-auto`">
+        {{ t('community.homepage.joinButtonLabel', { communityName: title }) }}
+      </Button>
     </div>
-  </OcLayoutCommunityWithTree>
+
+    <h3 v-if="!!accountStore.isAuthenticated && isMemberOfCurrentCommunity" class="text-2xl mt-8 mb-8">
+      {{ t('community.homepage.yourServices') }}
+    </h3>
+    <OcHomeActions class="mt-4"></OcHomeActions>
+  </div>
 </template>
 <script setup lang="ts">
 
 import { useRoute } from 'vue-router'
-import OcLayoutCommunityWithTree from '@/layout/OcLayoutCommunityWithTree/OcLayoutCommunityWithTree.vue'
-import { onBeforeMount, computed } from 'vue'
+import { computed, onMounted } from 'vue'
 import { useAccountStore } from '@/stores/account'
 import { useCommunityStore } from '@/stores/community'
 import { useI18n } from 'vue-i18n'
@@ -62,7 +59,7 @@ const accountStore = useAccountStore()
 
 const communityStore = useCommunityStore()
 
-onBeforeMount(() => communityStore.fetchIfEmpty())
+onMounted(() => communityStore.fetchIfEmpty())
 
 const community = computed(() => communityStore.getByName(route.params.community as string))
 
diff --git a/typed-router.d.ts b/typed-router.d.ts
index 40688e6..4c43f9f 100644
--- a/typed-router.d.ts
+++ b/typed-router.d.ts
@@ -20,9 +20,10 @@ declare module 'vue-router/auto-routes' {
   export interface RouteNamedMap {
     '/:lang/': RouteRecordInfo<'/:lang/', '/:lang', Record<never, never>, Record<never, never>>,
     '/:lang/[...path]': RouteRecordInfo<'/:lang/[...path]', '/:lang/:path(.*)', { path: ParamValue<true> }, { path: ParamValue<false> }>,
+    '/:lang/community/[community]': RouteRecordInfo<'/:lang/community/[community]', '/:lang/community/:community', { community: ParamValue<true> }, { community: ParamValue<false> }>,
     '/:lang/community/[community]/': RouteRecordInfo<'/:lang/community/[community]/', '/:lang/community/:community', { community: ParamValue<true> }, { community: ParamValue<false> }>,
-    '/:lang/community/[community]/join': RouteRecordInfo<'/:lang/community/[community]/join', '/:lang/community/:community/join', { community: ParamValue<true> }, { community: ParamValue<false> }>,
     '/:lang/community/[community]/resource/[identifier]': RouteRecordInfo<'/:lang/community/[community]/resource/[identifier]', '/:lang/community/:community/resource/:identifier', { community: ParamValue<true>, identifier: ParamValue<true> }, { community: ParamValue<false>, identifier: ParamValue<false> }>,
+    '/:lang/community/[community].join': RouteRecordInfo<'/:lang/community/[community].join', '/:lang/community/:community/join', { community: ParamValue<true> }, { community: ParamValue<false> }>,
     '/:lang/connection': RouteRecordInfo<'/:lang/connection', '/:lang/connection', Record<never, never>, Record<never, never>>,
     '/:lang/logout': RouteRecordInfo<'/:lang/logout', '/:lang/logout', Record<never, never>, Record<never, never>>,
     '/:lang/profile': RouteRecordInfo<'/:lang/profile', '/:lang/profile', Record<never, never>, Record<never, never>>,
-- 
GitLab