Yaltopia-FIFA/components/layout/DashboardShell.tsx
Kirubel-Kibru-Yaltopia 89440985f1
Some checks failed
Deploy to Cloudflare Workers / deploy (push) Has been cancelled
x
2026-05-24 21:46:10 +03:00

157 lines
5.5 KiB
TypeScript

"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { cn } from "@/lib/utils";
import { YaltopiaFooter } from "./YaltopiaFooter";
import type { LucideIcon } from "lucide-react";
import {
Bell,
Search,
Settings,
Trophy,
LogOut,
} from "lucide-react";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { createClient } from "@/lib/supabase/client";
import { useRouter } from "next/navigation";
export type NavItem = { href: string; label: string; icon: LucideIcon };
export function DashboardShell({
brand,
navItems,
user,
children,
}: {
brand: string;
navItems: NavItem[];
user: { name: string; email: string };
children: React.ReactNode;
}) {
const pathname = usePathname();
const router = useRouter();
const initials = user.name
.split(" ")
.map((n) => n[0])
.join("")
.slice(0, 2)
.toUpperCase();
async function signOut() {
const supabase = createClient();
await supabase.auth.signOut();
router.push("/");
router.refresh();
}
return (
<div className="retro-grid flex min-h-screen bg-background">
<aside className="hidden w-64 shrink-0 flex-col border-r border-border/80 bg-card/80 backdrop-blur-md md:flex">
<div className="flex h-14 items-center gap-2 border-b border-border/80 px-4">
<div className="flex h-9 w-9 items-center justify-center rounded-xl bg-primary shadow-[0_0_20px_-4px_var(--neon)]">
<Trophy className="h-4 w-4 text-primary-foreground" />
</div>
<div className="min-w-0">
<p className="font-display truncate text-sm font-bold uppercase tracking-wide">
Yaltopia FIFA
</p>
<p className="truncate text-[10px] uppercase tracking-wider text-neon-muted">
{brand}
</p>
</div>
</div>
<nav className="flex-1 space-y-0.5 p-3">
<p className="font-display px-3 pb-2 text-[10px] font-bold uppercase tracking-[0.2em] text-muted-foreground">
Menu
</p>
{navItems.map(({ href, label, icon: Icon }) => {
const active =
pathname === href ||
(href !== "/" && pathname.startsWith(href + "/"));
return (
<Link
key={href}
href={href}
className={cn(
"flex items-center gap-3 rounded-xl px-3 py-2.5 text-sm font-medium transition-all",
active
? "border border-neon/25 bg-neon/10 text-foreground shadow-[inset_3px_0_0_0_var(--neon)]"
: "text-muted-foreground hover:bg-secondary/80 hover:text-foreground"
)}
>
<Icon
className={cn(
"h-4 w-4 shrink-0",
active ? "text-neon" : "opacity-70"
)}
/>
{label}
</Link>
);
})}
</nav>
<div className="border-t border-border/80 p-3">
<div className="flex items-center gap-3 rounded-xl px-2 py-2">
<Avatar className="h-9 w-9 border border-border">
<AvatarFallback className="bg-secondary text-xs font-bold">
{initials}
</AvatarFallback>
</Avatar>
<div className="min-w-0 flex-1">
<p className="truncate text-sm font-semibold">{user.name}</p>
<p className="truncate text-xs text-muted-foreground">
{user.email}
</p>
</div>
</div>
<Button
variant="ghost"
size="sm"
className="mt-1 w-full justify-start text-muted-foreground"
onClick={() => void signOut()}
>
<LogOut className="mr-2 h-4 w-4" />
Sign out
</Button>
</div>
</aside>
<div className="flex min-w-0 flex-1 flex-col">
<header className="sticky top-0 z-30 flex h-14 items-center gap-4 border-b border-border/80 bg-background/80 px-4 backdrop-blur-md lg:px-6">
<div className="relative max-w-md flex-1">
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<Input
placeholder="Search…"
className="h-9 rounded-full border-border bg-muted/40 pl-9"
readOnly
/>
</div>
<div className="ml-auto flex items-center gap-1">
<Button variant="ghost" size="icon" className="rounded-full text-muted-foreground">
<Bell className="h-4 w-4" />
</Button>
<Button variant="ghost" size="icon" className="rounded-full text-muted-foreground">
<Settings className="h-4 w-4" />
</Button>
<div className="mx-1 h-6 w-px bg-border" aria-hidden />
<Avatar className="h-8 w-8 border border-border md:hidden">
<AvatarFallback className="text-[10px]">{initials}</AvatarFallback>
</Avatar>
</div>
</header>
<main className="flex-1 p-4 lg:p-6">{children}</main>
<div className="border-t border-border/80 px-6 py-3">
<YaltopiaFooter />
</div>
</div>
</div>
);
}