main
vue 108 lines 2.93 KB
Raw
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 </Provider>
22 </template>
23
24 <script lang="ts" setup>
25 import type { Component } from "vue"
26 import type { RouteLocationNormalized } from "vue-router"
27 import type { Layout, RouterTransition, ThemeNameEnum } from "@/types/theme"
28 import { computed, onBeforeMount, ref, watch } from "vue"
29 import { useRoute, useRouter } from "vue-router"
30 import Blank from "@/app-layouts/Blank"
31 import Provider from "@/app-layouts/common/Provider.vue"
32 import SplashScreen from "@/app-layouts/common/SplashScreen.vue"
33 import HorizontalNav from "@/app-layouts/HorizontalNav"
34 import { useMainStore } from "@/stores/main"
35 import { useThemeStore } from "@/stores/theme"
36 import { usePortalSettingsStore } from "./stores/portalSettings"
37 import { updateFavicon } from "./utils"
38
39 const layoutComponents = {
40 HorizontalNav,
41 Blank
42 }
43
44 const router = useRouter()
45 const route = useRoute()
46 const loading = ref(true)
47
48 const portalSettingsStore = usePortalSettingsStore()
49 const themeStore = useThemeStore()
50 const mainStore = useMainStore()
51
52 const routeName = computed<string>(() => route?.name?.toString() || "")
53 const forceRefresh = computed<number>(() => mainStore.forceRefresh)
54 const forceLayout = ref<Layout | null>(null)
55 const layout = computed<Layout>(() => themeStore.layout)
56 const layoutComponentName = computed<Layout>(() => forceLayout.value || layout.value)
57 const layoutComponent = computed<Component>(() => layoutComponents[layoutComponentName.value])
58 const routerTransition = computed<RouterTransition>(() => themeStore.routerTransition)
59 const themeName = computed<ThemeNameEnum>(() => themeStore.themeName)
60
61 function checkThemeOverrides(currentRoute: RouteLocationNormalized) {
62 if (currentRoute.meta?.theme?.layout !== undefined) {
63 forceLayout.value = currentRoute.meta.theme.layout
64 } else {
65 forceLayout.value = null
66 }
67 }
68
69 // Watch for logo changes and update favicon
70 watch(
71 () => portalSettingsStore.portalLogo,
72 newLogo => {
73 if (newLogo) {
74 updateFavicon(newLogo)
75 }
76 },
77 { immediate: true }
78 )
79
80 // Watch for title changes and update document title
81 watch(
82 () => portalSettingsStore.portalTitle,
83 newTitle => {
84 if (newTitle) {
85 document.title = newTitle
86 }
87 },
88 { immediate: true }
89 )
90
91 watch(layoutComponentName, () => {
92 loading.value = false
93 })
94
95 router.afterEach(currentRoute => {
96 checkThemeOverrides(currentRoute)
97 })
98
99 onBeforeMount(async () => {
100 await portalSettingsStore.fetchSettings()
101
102 checkThemeOverrides(route)
103
104 setTimeout(() => {
105 loading.value = false
106 }, 500)
107 })
108 </script>