diff --git a/apps/app/src/layouts/components/AppShell.vue b/apps/app/src/layouts/components/AppShell.vue index 1e9e8ac1..81c9f574 100644 --- a/apps/app/src/layouts/components/AppShell.vue +++ b/apps/app/src/layouts/components/AppShell.vue @@ -16,11 +16,13 @@ // PrimeVue Drawer overlay. Content area renders the default slot // (a RouterView from the wrapping layout file). -import { ref } from 'vue' -import { useRouter } from 'vue-router' +import { computed, ref } from 'vue' +import { useRoute, useRouter } from 'vue-router' import Drawer from 'primevue/drawer' import Button from 'primevue/button' +import { useToast } from 'primevue/usetoast' import Icon from '@/components/Icon.vue' +import { useAuthStore } from '@/stores/useAuthStore' interface NavHeading { heading: string @@ -37,11 +39,14 @@ interface Props { title?: string } -withDefaults(defineProps(), { +const props = withDefaults(defineProps(), { title: 'Crewli', }) const router = useRouter() +const route = useRoute() +const toast = useToast() +const authStore = useAuthStore() const mobileNavOpen = ref(false) @@ -53,6 +58,54 @@ function navigate(item: NavLink) { mobileNavOpen.value = false router.push(item.to) } + +// Breadcrumb: "Organisation / Page title". Page title resolves from +// route.meta.title → matching navItems entry → humanized route name. +// Org name is omitted on portal / pre-org users (currentOrganisation +// is null) so the breadcrumb reads as just the page title there. +const orgName = computed(() => authStore.currentOrganisation?.name ?? '') + +const pageTitle = computed(() => { + const metaTitle = route.meta.title + if (typeof metaTitle === 'string' && metaTitle.length > 0) + return metaTitle + + const match = props.navItems.find( + (item): item is NavLink => 'to' in item && item.to.name === route.name, + ) + + if (match) + return match.title + + const raw = String(route.name ?? '') + if (!raw) + return '' + + return raw.charAt(0).toUpperCase() + raw.slice(1).replace(/-/g, ' ') +}) + +function onNotificationsClick() { + toast.add({ + severity: 'info', + summary: 'Notificaties', + detail: 'Notificaties komen binnenkort beschikbaar.', + life: 3000, + }) +} + +// TODO(docs-url): https://docs.crewli.app currently serves with a TLS +// cert that does not cover the host (ERR_TLS_CERT_ALTNAME_INVALID), +// so a browser hit shows a security warning instead of the docs. +// When the cert is fixed, switch this handler to: +// window.open('https://docs.crewli.app', '_blank', 'noopener,noreferrer') +function onHelpClick() { + toast.add({ + severity: 'info', + summary: 'Help', + detail: 'Documentatie komt binnenkort beschikbaar.', + life: 3000, + }) +}