mackenzii/projects/frontend/src/main.vue

188 lines
4.7 KiB
Vue

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { getCurrentRoute } from 'src/utilities/vuetils'
import { injectStylesheet } from 'src/utilities/dom'
import { storage } from './utilities/fetch'
import { useRouteStore } from 'src/routes'
import type { Link, RoutedWindow, WarningModal } from '@goldenwere/static-web-templates-types'
import HeaderLink from 'src/components/shared/header-link.vue'
import ThemePicker from 'src/components/shared/theme-picker.vue'
import WarningPrompt from 'src/components/shared/warning-prompt.vue'
declare const window: RoutedWindow
const router = useRouter()
const routeStore = useRouteStore()
const globalConfig = routeStore._globals
let currentRoute = getCurrentRoute()
let routeConfig = routeStore._routes[currentRoute.path]
let rememberWarning = false
const ready = ref(false)
const firstInit = ref(false)
const acknowledged = ref(false)
const storageId = ref('')
const routeId = ref('')
const warning = ref({} as WarningModal)
const breadcrumbs = computed({
get() { return routeStore._breadcrumbs },
set() {}
})
const determineWarning = () => {
if (!routeConfig.warning || routeStore.doesRouteRememberWarning(currentRoute.path)) {
acknowledged.value = true
return
}
rememberWarning = storage.read(`${storageId.value}::rememberWarning`) || false
if (rememberWarning) {
acknowledged.value = true
routeStore.rememberRouteWarning(currentRoute.path)
return
}
warning.value = routeConfig.warning === true
? globalConfig.warning
: routeConfig.warning
}
const determineStylesheets = (stylesheetUrls?: string[]) => {
const staleStylesheets = document.head.querySelectorAll('link.page-stylesheet[rel="stylesheet"]')
staleStylesheets.forEach(stylesheet => {
document.head.removeChild(stylesheet)
})
stylesheetUrls?.forEach(stylesheet => {
injectStylesheet(stylesheet, 'page-stylesheet')
})
}
const determineGlobalStylesheets = () => {
globalConfig.stylesheetUrls.forEach(stylesheet => {
injectStylesheet(stylesheet, 'global-stylesheet')
})
}
const determineScript = async () => {
if (!!routeConfig.scriptUrl) {
const { callbacks } = await import(/* @vite-ignore */ routeConfig.scriptUrl)
if (!!callbacks.onPageLoaded) {
callbacks.onPageLoaded();
}
}
return null
}
const refresh = async () => {
ready.value = false
acknowledged.value = false
currentRoute = getCurrentRoute()
routeConfig = routeStore._routes[currentRoute.path]
storageId.value = `${globalConfig.id}::${currentRoute.path}`
routeId.value = routeStore._routes[currentRoute.path].id
window.routeConfig = {...routeConfig}
routeStore.setBreadcrumbs(currentRoute)
determineWarning()
determineStylesheets(routeConfig.stylesheetUrls)
scrollTo({
top: 0,
})
setTimeout(() => ready.value = true)
}
const onAcknowledgedWarning = () => {
acknowledged.value = true
routeStore.rememberRouteWarning(currentRoute.path)
}
const onRouteLoaded = async () => {
await determineScript()
}
const handlePageClosed = async (scriptUrl?: string) => {
if (!!scriptUrl) {
const { callbacks } = await import(/* @vite-ignore */ scriptUrl)
if (!!callbacks.onPageClosed) {
callbacks.onPageClosed()
}
}
}
onMounted(async () => {
await refresh()
firstInit.value = true
determineGlobalStylesheets()
router.afterEach(async (to, from) => {
const oldUrl = routeConfig.scriptUrl
await refresh()
await handlePageClosed(oldUrl)
})
})
</script>
<template lang="pug">
#main-container
header(
v-if='firstInit && !!globalConfig.header'
)
nav#header-nav
ul
HeaderLink(
v-for='entry in globalConfig.header'
:entry='entry'
)
nav#header-breadcrumb(
v-if='breadcrumbs.length > 0'
)
span.breadcrumb(
v-for='(breadcrumb, i) in breadcrumbs'
)
span(
v-if='breadcrumbs.length === 1 || i === breadcrumbs.length - 1'
) {{ breadcrumb.caption }}
span(
v-else
)
router-link(
:to='{ path: breadcrumb.href }'
) {{ breadcrumb.caption }}
span /
#header-controls
ThemePicker
main(
v-if='ready'
)
#main-entry(
v-if='acknowledged'
)
router-view(
v-slot='{ Component }'
@loaded='onRouteLoaded'
)
Transition
component(
:id='routeId'
:is='Component'
)
#main-entry(
v-else
)
Transition
WarningPrompt(
:storageId='storageId'
:warning='warning'
@acknowledged='onAcknowledgedWarning()'
)
</template>
<style scoped lang="sass">
</style>