Nyavokevin 9e5cc5ab1a
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
add dark theme
2025-09-18 20:34:07 +03:00

218 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import AppLogo from '@/components/AppLogo.vue';
import AppLogoIcon from '@/components/AppLogoIcon.vue';
import Breadcrumbs from '@/components/Breadcrumbs.vue';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
import { NavigationMenu, NavigationMenuItem, NavigationMenuList, navigationMenuTriggerStyle } from '@/components/ui/navigation-menu';
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import UserMenuContent from '@/components/UserMenuContent.vue';
import { getInitials } from '@/composables/useInitials';
import type { BreadcrumbItem, NavItem } from '@/types';
import { InertiaLinkProps, Link, usePage } from '@inertiajs/vue3';
import { BookOpen, Folder } from 'lucide-vue-next';
import { computed } from 'vue';
interface Props {
breadcrumbs?: BreadcrumbItem[];
}
const props = withDefaults(defineProps<Props>(), {
breadcrumbs: () => [],
});
const page = usePage();
const auth = computed(() => page.props.auth);
const isCurrentRoute = computed(() => (url: NonNullable<InertiaLinkProps['href']>) => page.url === (typeof url === 'string' ? url : url.url));
const activeItemStyles = computed(
() => (url: NonNullable<InertiaLinkProps['href']>) =>
isCurrentRoute.value(typeof url === 'string' ? url : url.url)
? 'text-primary dark:bg-card dark:text-primary-foreground'
: 'text-foreground hover:bg-muted',
);
const mainNavItems: NavItem[] = [
{
title: 'Accueil',
href: '/', // Example route
},
{
title: 'Tirage doracle',
href: '/oracle-draw', // Example route
},
{
title: 'Consultations',
href: '/consultations', // Example route
},
{
title: 'Services',
href: '/services', // Example route
},
{
title: 'Contact',
href: '/contact', // Example route
},
];
const rightNavItems: NavItem[] = [
{
title: 'Repository',
href: 'https://github.com/your-repo',
icon: Folder,
},
{
title: 'Documentation',
href: 'https://your-docs.com',
icon: BookOpen,
},
];
</script>
<template>
<div>
<div class="border-b border-border/80">
<div class="mx-auto flex h-16 items-center px-4 md:max-w-7xl">
<div class="lg:hidden">
<Sheet>
<SheetTrigger :as-child="true">
<Button variant="ghost" size="icon" class="mr-2 h-9 w-9">
<Menu class="h-5 w-5" />
</Button>
</SheetTrigger>
<SheetContent side="left" class="w-[300px] bg-background p-6">
<SheetTitle class="sr-only">Navigation Menu</SheetTitle>
<SheetHeader class="flex justify-start text-left">
<AppLogoIcon class="size-6 fill-current text-primary dark:text-primary" />
</SheetHeader>
<div class="flex h-full flex-1 flex-col justify-between space-y-4 py-6">
<nav class="-mx-3 space-y-1">
<Link
v-for="item in mainNavItems"
:key="item.title"
:href="item.href"
class="flex items-center gap-x-3 rounded-lg px-3 py-2 font-body text-sm hover:bg-muted"
:class="isCurrentRoute(item.href) ? 'font-semibold text-primary' : 'text-foreground'"
>
{{ item.title }}
</Link>
</nav>
<div class="flex flex-col space-y-4">
<a
v-for="item in rightNavItems"
:key="item.title"
:href="typeof item.href === 'string' ? item.href : item.href?.url"
target="_blank"
rel="noopener noreferrer"
class="flex items-center space-x-2 font-body text-sm text-foreground"
>
<component v-if="item.icon" :is="item.icon" class="h-5 w-5" />
<span>{{ item.title }}</span>
</a>
</div>
</div>
</SheetContent>
</Sheet>
</div>
<Link href="/" class="flex items-center gap-x-2">
<AppLogo />
</Link>
<div class="hidden h-full lg:flex lg:flex-1">
<NavigationMenu class="ml-10 flex h-full items-stretch">
<NavigationMenuList class="flex h-full items-stretch space-x-2">
<NavigationMenuItem v-for="(item, index) in mainNavItems" :key="index" class="relative flex h-full items-center">
<Link
:class="[navigationMenuTriggerStyle(), activeItemStyles(item.href), 'h-9 cursor-pointer px-3 font-body']"
:href="item.href"
>
{{ item.title }}
</Link>
<div
v-if="isCurrentRoute(item.href)"
class="bg-subtle-gold dark:bg-subtle-gold absolute bottom-0 left-0 h-0.5 w-full translate-y-px"
></div>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
</div>
<div class="ml-auto flex items-center space-x-2">
<div class="relative flex items-center space-x-1">
<TooltipProvider :delay-duration="0">
<Tooltip>
<TooltipTrigger>
<Button variant="ghost" size="icon" as-child class="group h-9 w-9 cursor-pointer">
<a href="#" class="flex items-center justify-center">
<span class="sr-only">Rechercher</span>
<Search class="size-5 opacity-80 group-hover:opacity-100" />
</a>
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Rechercher</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<div class="hidden space-x-1 lg:flex">
<template v-for="item in rightNavItems" :key="item.title">
<TooltipProvider :delay-duration="0">
<Tooltip>
<TooltipTrigger>
<Button variant="ghost" size="icon" as-child class="group h-9 w-9 cursor-pointer">
<a
:href="typeof item.href === 'string' ? item.href : item.href?.url"
target="_blank"
rel="noopener noreferrer"
>
<span class="sr-only">{{ item.title }}</span>
<component :is="item.icon" class="size-5 opacity-80 group-hover:opacity-100" />
</a>
</Button>
</TooltipTrigger>
<TooltipContent>
<p>{{ item.title }}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</template>
</div>
</div>
<DropdownMenu>
<DropdownMenuTrigger :as-child="true">
<Button
variant="ghost"
size="icon"
class="focus-within:ring-subtle-gold relative size-10 w-auto rounded-full p-1 focus-within:ring-2"
>
<Avatar class="size-8 overflow-hidden rounded-full">
<AvatarImage v-if="auth.user.avatar" :src="auth.user.avatar" :alt="auth.user.name" />
<AvatarFallback
class="bg-linen dark:bg-spiritual-earth dark:text-pure-white rounded-lg font-semibold text-foreground"
>
{{ getInitials(auth.user?.name) }}
</AvatarFallback>
</Avatar>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" class="w-56">
<UserMenuContent :user="auth.user" />
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
</div>
<div v-if="props.breadcrumbs.length > 1" class="flex w-full border-b border-border/70">
<div class="mx-auto flex h-12 w-full items-center justify-start px-4 text-muted-foreground md:max-w-7xl">
<Breadcrumbs :breadcrumbs="breadcrumbs" />
</div>
</div>
</div>
</template>