first commit

This commit is contained in:
Dhananjaya99
2026-09-28 11:48:14 +05:30
commit a1b870fa8a
242 changed files with 39483 additions and 0 deletions
+165
View File
@@ -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 }