first commit
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
<script setup lang="ts">
|
||||
import { Head, Link, usePage } from '@inertiajs/vue3';
|
||||
import { ref, watch } from 'vue';
|
||||
import TheNavbar from '@/components/TheNavbar.vue';
|
||||
import TheSidebar from '@/components/TheSidebar.vue';
|
||||
import ConfirmHost from '@/components/ui/ConfirmHost.vue';
|
||||
import ToastHost from '@/components/ui/ToastHost.vue';
|
||||
import { useToast } from '@/composables/useToast';
|
||||
import { useTranslations } from '@/composables/useVanguard';
|
||||
import type { SharedProps } from '@/types';
|
||||
|
||||
defineProps<{
|
||||
title?: string;
|
||||
heading?: string;
|
||||
breadcrumbs?: Array<{ label: string; href?: string }>;
|
||||
}>();
|
||||
|
||||
const page = usePage<SharedProps>();
|
||||
const toast = useToast();
|
||||
const { __ } = useTranslations();
|
||||
const sidebarOpen = ref(false);
|
||||
|
||||
/**
|
||||
* Flash messages arrive as a shared prop and are surfaced as toasts on every
|
||||
* navigation.
|
||||
*/
|
||||
watch(
|
||||
() => page.props.flash,
|
||||
(flash) => {
|
||||
for (const message of [flash?.success ?? []].flat().filter(Boolean)) {
|
||||
toast.add({ severity: 'success', summary: String(message), life: 3000 });
|
||||
}
|
||||
|
||||
for (const message of [flash?.error ?? []].flat().filter(Boolean)) {
|
||||
toast.add({ severity: 'error', summary: String(message), life: 5000 });
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head :title="title" />
|
||||
|
||||
<TheNavbar :heading="heading" @toggle-sidebar="sidebarOpen = !sidebarOpen">
|
||||
<template #breadcrumbs>
|
||||
<ol
|
||||
v-if="breadcrumbs?.length"
|
||||
:aria-label="__('Breadcrumb')"
|
||||
class="hidden items-center gap-2 text-sm font-light text-slate-500 md:flex"
|
||||
>
|
||||
<li>
|
||||
<Link :href="route('dashboard')" class="text-slate-400 hover:text-primary-600">
|
||||
<i class="fa fa-home" />
|
||||
</Link>
|
||||
</li>
|
||||
<li v-for="crumb in breadcrumbs" :key="crumb.label" class="flex items-center gap-2">
|
||||
<span class="text-slate-300">/</span>
|
||||
<Link v-if="crumb.href" :href="crumb.href" class="hover:text-primary-600">
|
||||
{{ crumb.label }}
|
||||
</Link>
|
||||
<span v-else>{{ crumb.label }}</span>
|
||||
</li>
|
||||
</ol>
|
||||
</template>
|
||||
</TheNavbar>
|
||||
|
||||
<TheSidebar :open="sidebarOpen" />
|
||||
|
||||
<div
|
||||
v-if="sidebarOpen"
|
||||
class="fixed inset-0 z-[9] bg-black/40 md:hidden"
|
||||
:aria-label="__('Close navigation')"
|
||||
@click="sidebarOpen = false"
|
||||
/>
|
||||
|
||||
<main class="mt-(--spacing-navbar) px-4 py-6 md:ml-(--spacing-sidebar)">
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
<ToastHost />
|
||||
<ConfirmHost />
|
||||
</template>
|
||||
Reference in New Issue
Block a user