| 1 | <template> |
| 2 | <Provider> |
| 3 | <component |
| 4 | :is="layoutComponent" |
| 5 | id="app-layout" |
| 6 | :class="[ |
| 7 | `theme-${themeName}`, |
| 8 | `layout-${layoutComponentName}`, |
| 9 | `route-${routeName}`, |
| 10 | { 'opacity-0': loading } |
| 11 | ]" |
| 12 | > |
| 13 | <RouterView v-slot="{ Component: RouterComponent }"> |
| 14 | <transition :name="`router-${routerTransition}`" mode="out-in" appear> |
| 15 | <component :is="RouterComponent" id="app-page" :key="routeName + forceRefresh" /> |
| 16 | </transition> |
| 17 | </RouterView> |
| 18 | </component> |
| 19 | |
| 20 | <SplashScreen :show="loading" /> |
| 21 | <SearchDialog v-if="isLogged" /> |
| 22 | <ChatButton v-if="isLogged" /> |
| 23 | </Provider> |
| 24 | </template> |
| 25 | |
| 26 | <script lang="ts" setup> |
| 27 | import type { Component } from "vue" |
| 28 | import type { RouteLocationNormalized } from "vue-router" |
| 29 | import type { Layout, RouterTransition, ThemeNameEnum } from "@/types/theme.d" |
| 30 | import { computed, onBeforeMount, ref, watch } from "vue" |
| 31 | import { useRoute, useRouter } from "vue-router" |
| 32 | import Blank from "@/app-layouts/Blank" |
| 33 | import Provider from "@/app-layouts/common/Provider.vue" |
| 34 | import SplashScreen from "@/app-layouts/common/SplashScreen.vue" |
| 35 | import VerticalNav from "@/app-layouts/VerticalNav" |
| 36 | import ChatButton from "@/components/aiChatbot/ChatButton.vue" |
| 37 | import SearchDialog from "@/components/common/SearchDialog.vue" |
| 38 | import { useAuthStore } from "@/stores/auth" |
| 39 | import { useMainStore } from "@/stores/main" |
| 40 | import { useThemeStore } from "@/stores/theme" |
| 41 | |
| 42 | const layoutComponents = { |
| 43 | VerticalNav, |
| 44 | Blank |
| 45 | } |
| 46 | |
| 47 | const router = useRouter() |
| 48 | const route = useRoute() |
| 49 | const loading = ref(true) |
| 50 | |
| 51 | const themeStore = useThemeStore() |
| 52 | const mainStore = useMainStore() |
| 53 | const authStore = useAuthStore() |
| 54 | |
| 55 | const routeName = computed<string>(() => route?.name?.toString() || "") |
| 56 | const forceRefresh = computed<number>(() => mainStore.forceRefresh) |
| 57 | const forceLayout = ref<Layout | null>(null) |
| 58 | const layout = computed<Layout>(() => themeStore.layout) |
| 59 | const layoutComponentName = computed<Layout>(() => forceLayout.value || layout.value) |
| 60 | const layoutComponent = computed<Component>(() => layoutComponents[layoutComponentName.value]) |
| 61 | const routerTransition = computed<RouterTransition>(() => themeStore.routerTransition) |
| 62 | const themeName = computed<ThemeNameEnum>(() => themeStore.themeName) |
| 63 | const isLogged = computed(() => authStore.isLogged) |
| 64 | |
| 65 | function checkThemeOverrides(currentRoute: RouteLocationNormalized) { |
| 66 | if (currentRoute.meta?.theme?.layout !== undefined) { |
| 67 | forceLayout.value = currentRoute.meta.theme.layout |
| 68 | } else { |
| 69 | forceLayout.value = null |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | watch(layoutComponentName, () => { |
| 74 | loading.value = false |
| 75 | }) |
| 76 | |
| 77 | router.afterEach(currentRoute => { |
| 78 | checkThemeOverrides(currentRoute) |
| 79 | }) |
| 80 | |
| 81 | onBeforeMount(() => { |
| 82 | checkThemeOverrides(route) |
| 83 | |
| 84 | setTimeout(() => { |
| 85 | loading.value = false |
| 86 | }, 500) |
| 87 | }) |
| 88 | </script> |