156 lines
5.7 KiB
TypeScript
156 lines
5.7 KiB
TypeScript
import { useState } from "react";
|
|
import { Search, Bell, ChevronDown, Moon, Sun } from "lucide-react";
|
|
import { Input } from "./ui/input";
|
|
import { Avatar, AvatarFallback } from "./ui/avatar";
|
|
import { Button } from "./ui/button";
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuLabel,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger,
|
|
} from "./ui/dropdown-menu";
|
|
import { Badge } from "./ui/badge";
|
|
|
|
interface TopNavBarProps {
|
|
userName: string;
|
|
userEmail: string;
|
|
currentTenant: string;
|
|
tenants: { id: string; name: string; role: string }[];
|
|
onTenantSwitch: (tenantId: string) => void;
|
|
notificationCount?: number;
|
|
theme: "light" | "dark";
|
|
onThemeToggle: () => void;
|
|
}
|
|
|
|
export function TopNavBar({
|
|
userName,
|
|
userEmail,
|
|
currentTenant,
|
|
tenants,
|
|
onTenantSwitch,
|
|
notificationCount = 0,
|
|
theme,
|
|
onThemeToggle,
|
|
}: TopNavBarProps) {
|
|
const [searchOpen, setSearchOpen] = useState(false);
|
|
|
|
const initials = userName
|
|
.split(" ")
|
|
.map((n) => n[0])
|
|
.join("")
|
|
.toUpperCase();
|
|
|
|
return (
|
|
<div className="sticky top-0 z-50 w-full border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
|
<div className="container mx-auto px-4 lg:px-8">
|
|
<div className="flex h-16 items-center justify-between gap-4">
|
|
{/* Logo */}
|
|
<div className="flex items-center gap-2">
|
|
<div className="w-8 h-8 rounded-[10px] bg-primary flex items-center justify-center">
|
|
<span className="text-primary-foreground">H</span>
|
|
</div>
|
|
<span className="hidden sm:inline">Hello Jewellers</span>
|
|
</div>
|
|
|
|
{/* Search */}
|
|
<div className="flex-1 max-w-md hidden md:block">
|
|
<div className="relative">
|
|
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
|
|
<Input
|
|
placeholder="Global search..."
|
|
className="pl-10"
|
|
onFocus={() => setSearchOpen(true)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Right side */}
|
|
<div className="flex items-center gap-2">
|
|
{/* Tenant Switcher */}
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button variant="ghost" className="hidden lg:flex items-center gap-2">
|
|
<span className="text-[14px] max-w-[150px] truncate">{currentTenant}</span>
|
|
<ChevronDown className="w-4 h-4 text-muted-foreground" />
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end" className="w-[280px]">
|
|
<DropdownMenuLabel>Switch Tenant</DropdownMenuLabel>
|
|
<DropdownMenuSeparator />
|
|
{tenants.map((tenant) => (
|
|
<DropdownMenuItem
|
|
key={tenant.id}
|
|
onClick={() => onTenantSwitch(tenant.id)}
|
|
className="flex items-center justify-between"
|
|
>
|
|
<div className="flex flex-col gap-1">
|
|
<span className="text-[14px]">{tenant.name}</span>
|
|
<span className="text-[12px] text-muted-foreground">{tenant.role}</span>
|
|
</div>
|
|
{tenant.name === currentTenant && (
|
|
<Badge variant="secondary" className="text-[10px]">
|
|
Active
|
|
</Badge>
|
|
)}
|
|
</DropdownMenuItem>
|
|
))}
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
|
|
{/* Theme Toggle */}
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
onClick={onThemeToggle}
|
|
className="hidden sm:flex"
|
|
>
|
|
{theme === "light" ? (
|
|
<Moon className="w-5 h-5" />
|
|
) : (
|
|
<Sun className="w-5 h-5" />
|
|
)}
|
|
</Button>
|
|
|
|
{/* Notifications */}
|
|
<Button variant="ghost" size="icon" className="relative">
|
|
<Bell className="w-5 h-5" />
|
|
{notificationCount > 0 && (
|
|
<span className="absolute -top-1 -right-1 w-5 h-5 bg-destructive text-destructive-foreground rounded-full flex items-center justify-center text-[10px]">
|
|
{notificationCount > 9 ? "9+" : notificationCount}
|
|
</span>
|
|
)}
|
|
</Button>
|
|
|
|
{/* User Menu */}
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button variant="ghost" className="flex items-center gap-2">
|
|
<Avatar className="w-8 h-8">
|
|
<AvatarFallback>{initials}</AvatarFallback>
|
|
</Avatar>
|
|
<ChevronDown className="w-4 h-4 text-muted-foreground hidden sm:block" />
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end" className="w-[240px]">
|
|
<DropdownMenuLabel>
|
|
<div className="flex flex-col gap-1">
|
|
<span>{userName}</span>
|
|
<span className="text-[12px] text-muted-foreground">{userEmail}</span>
|
|
</div>
|
|
</DropdownMenuLabel>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem>Profile Settings</DropdownMenuItem>
|
|
<DropdownMenuItem>Preferences</DropdownMenuItem>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem className="text-destructive">Sign Out</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|