first commit
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { useRouter } from "next/navigation"
|
||||
import {
|
||||
BellIcon,
|
||||
LogOutIcon,
|
||||
SettingsIcon,
|
||||
UserIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
import { logout } from "@/lib/api/session"
|
||||
import { Avatar, AvatarFallback } from "@/components/ui/avatar"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
import { SidebarTrigger } from "@/components/ui/sidebar"
|
||||
import { GlobalCustomerSearch } from "@/components/hexa/global-customer-search"
|
||||
import { RefreshButton } from "@/components/hexa/refresh-button"
|
||||
import { ThemeToggle } from "@/components/hexa/theme-toggle"
|
||||
import { useClientProfile } from "@/components/hexa/client-profile-context"
|
||||
|
||||
interface SiteHeaderProps {
|
||||
date: Date | null
|
||||
onDateChange: (date: Date) => void
|
||||
notificationCount?: number
|
||||
onRefresh?: () => void
|
||||
demo?: boolean
|
||||
onNavigate?: (key: string) => void
|
||||
}
|
||||
|
||||
function SiteHeader({
|
||||
date,
|
||||
notificationCount = 0,
|
||||
onRefresh,
|
||||
demo = false,
|
||||
onNavigate,
|
||||
}: SiteHeaderProps) {
|
||||
const fullDate = date?.toLocaleDateString("en-LK", { month: "long", day: "numeric", year: "numeric", timeZone: "Asia/Colombo" }) ?? "Today"
|
||||
const compactDate = date?.toLocaleDateString("en-LK", { month: "short", day: "numeric", timeZone: "Asia/Colombo" }) ?? "Today"
|
||||
const router = useRouter()
|
||||
const profile = useClientProfile()
|
||||
|
||||
async function handleLogout() {
|
||||
if (demo) {
|
||||
router.push("/login")
|
||||
return
|
||||
}
|
||||
await logout()
|
||||
router.replace("/login")
|
||||
}
|
||||
|
||||
async function navigateToProfile() {
|
||||
if (onNavigate) {
|
||||
onNavigate("settings")
|
||||
return
|
||||
}
|
||||
router.push("/dashboard/settings")
|
||||
}
|
||||
|
||||
const displayName = demo ? "Demo Gym" : profile.clientName ?? profile.gymName ?? "My Gym"
|
||||
const initials =
|
||||
displayName
|
||||
.split(/\s+/)
|
||||
.filter(Boolean)
|
||||
.slice(0, 2)
|
||||
.map((w) => w[0]?.toUpperCase())
|
||||
.join("") || "G"
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-30 flex h-16 shrink-0 items-center gap-2 border-b bg-background/95 px-3 backdrop-blur supports-backdrop-filter:bg-background/80 sm:px-4">
|
||||
<SidebarTrigger className="rounded-full" />
|
||||
|
||||
<div className="ml-1 flex h-9 shrink-0 items-center rounded-full border bg-muted/30 px-3 text-sm" aria-label="Today's date">
|
||||
<span className="hidden sm:inline">{fullDate}</span>
|
||||
<span className="sm:hidden">{compactDate}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-1 justify-center px-2">
|
||||
<GlobalCustomerSearch demo={demo} />
|
||||
</div>
|
||||
|
||||
<div className="ml-auto flex items-center gap-2">
|
||||
<RefreshButton onRefresh={onRefresh} />
|
||||
<ThemeToggle />
|
||||
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger
|
||||
render={
|
||||
<Button variant="outline" size="icon" className="relative rounded-full">
|
||||
<BellIcon />
|
||||
{notificationCount > 0 && (
|
||||
<Badge className="absolute -top-1.5 -right-1.5 size-5 justify-center rounded-full p-0 text-[0.65rem]">
|
||||
{notificationCount}
|
||||
</Badge>
|
||||
)}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<DropdownMenuContent align="end" className="w-72">
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuLabel>Notifications</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem className="flex-col items-start gap-0.5">
|
||||
<span className="font-medium">New membership payment received</span>
|
||||
<span className="text-xs text-muted-foreground">2 minutes ago</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="flex-col items-start gap-0.5">
|
||||
<span className="font-medium">Staff member added</span>
|
||||
<span className="text-xs text-muted-foreground">1 hour ago</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="flex-col items-start gap-0.5">
|
||||
<span className="font-medium">Gym plan updated</span>
|
||||
<span className="text-xs text-muted-foreground">Yesterday</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger
|
||||
render={
|
||||
<button aria-label="Profile menu">
|
||||
<Avatar>
|
||||
<AvatarFallback className="bg-primary text-primary-foreground">
|
||||
{initials}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
</button>
|
||||
}
|
||||
/>
|
||||
<DropdownMenuContent align="end" className="w-56">
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuLabel>{displayName}</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={navigateToProfile}>
|
||||
<UserIcon />
|
||||
Profile
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<SettingsIcon />
|
||||
Settings
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem variant="destructive" onClick={handleLogout}>
|
||||
<LogOutIcon />
|
||||
{demo ? "Exit demo" : "Log out"}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
|
||||
export { SiteHeader }
|
||||
Reference in New Issue
Block a user