branch crud and intergration
This commit is contained in:
@@ -32,6 +32,7 @@ import {
|
||||
LineChart,
|
||||
ListTree,
|
||||
Lock,
|
||||
MapPin,
|
||||
Menu,
|
||||
Package,
|
||||
PackageCheck,
|
||||
@@ -212,6 +213,7 @@ const navItems: {
|
||||
icon: Settings,
|
||||
chevron: true,
|
||||
children: [
|
||||
{ title: "Branches", code: "settings.branches", href: "/dashboard/settings/branches", icon: MapPin },
|
||||
{ title: "Roles", code: "settings.roles", href: "/dashboard/settings/roles", icon: ShieldCheck },
|
||||
{ title: "Users", code: "settings.users", href: "/dashboard/settings/users", icon: Users },
|
||||
{ title: "Configuration", code: "products.configuration", href: "/dashboard/settings/configuration", icon: SlidersHorizontal },
|
||||
|
||||
@@ -3,12 +3,15 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import Link from "next/link"
|
||||
import { usePathname, useRouter } from "next/navigation"
|
||||
import { ArrowLeft, Bell, LogOut, Settings, User } from "lucide-react"
|
||||
import { ArrowLeft, Bell, Building2, LogOut, Settings, User } from "lucide-react"
|
||||
|
||||
import { authApi } from "@/lib/api/auth"
|
||||
import { clearStoredUser, displayName, getStoredUser } from "@/lib/auth-session"
|
||||
import { branchesHrmApi } from "@/lib/api/hrm-masters"
|
||||
import { AuthUser } from "@/types/auth"
|
||||
import { Branch } from "@/types/hrm"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { useAuth } from "@/components/auth/AuthProvider"
|
||||
import { ThemeToggle } from "@/components/theme-toggle"
|
||||
import { Avatar, AvatarFallback } from "@/components/ui/avatar"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
@@ -20,6 +23,7 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
|
||||
/** Avatar initials from a display name: "ERP Admin" -> "EA", "erpadmin" -> "ER". */
|
||||
function initials(name: string): string {
|
||||
@@ -166,9 +170,27 @@ export function Header() {
|
||||
const router = useRouter()
|
||||
const title = titleFromPath(pathname)
|
||||
const showBackButton = pathname !== "/dashboard"
|
||||
const { isAdmin, branchName, activeBranchId, activeBranchName, setActiveBranch, branchingEnabled } = useAuth()
|
||||
const branchLabel = isAdmin ? (activeBranchName ?? "All Branches") : branchName
|
||||
const [notifications, setNotifications] = useState(initialNotifications)
|
||||
const unreadCount = notifications.filter((n) => n.unread).length
|
||||
|
||||
const [branches, setBranches] = useState<Branch[]>([])
|
||||
useEffect(() => {
|
||||
if (!isAdmin || !branchingEnabled) return
|
||||
branchesHrmApi.list({ pageSize: 200, status: "Active" }).then((r) => setBranches(r.items)).catch(() => setBranches([]))
|
||||
}, [isAdmin, branchingEnabled])
|
||||
|
||||
const ALL_BRANCHES = "__all__"
|
||||
function handleBranchChange(value: string | null) {
|
||||
if (!value || value === ALL_BRANCHES) {
|
||||
setActiveBranch(null, null)
|
||||
return
|
||||
}
|
||||
const branch = branches.find((b) => String(b.branchId) === value)
|
||||
setActiveBranch(branch?.branchId ?? null, branch?.name ?? null)
|
||||
}
|
||||
|
||||
// Read after mount so the first client render matches the server render.
|
||||
const [user, setUser] = useState<AuthUser | null>(null)
|
||||
|
||||
@@ -213,6 +235,36 @@ export function Header() {
|
||||
</div>
|
||||
|
||||
<div className="flex shrink-0 items-center gap-1.5 sm:gap-3">
|
||||
{branchingEnabled && (isAdmin ? (
|
||||
<Select value={activeBranchId ? String(activeBranchId) : ALL_BRANCHES} onValueChange={handleBranchChange}>
|
||||
<SelectTrigger
|
||||
className="hidden h-8! shrink-0 gap-1.5 rounded-full border-transparent bg-muted px-2.5 text-xs font-medium text-muted-foreground hover:bg-muted/70 sm:flex"
|
||||
aria-label="Switch branch"
|
||||
>
|
||||
<Building2 className="size-3.5" />
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value={ALL_BRANCHES}>All Branches</SelectItem>
|
||||
{branches.map((b) => (
|
||||
<SelectItem key={b.branchId} value={String(b.branchId)}>
|
||||
{b.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
) : (
|
||||
branchLabel && (
|
||||
<Badge
|
||||
variant="outline"
|
||||
className="hidden shrink-0 items-center gap-1.5 border-transparent bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground sm:flex"
|
||||
>
|
||||
<Building2 className="size-3.5" />
|
||||
{branchLabel}
|
||||
</Badge>
|
||||
)
|
||||
))}
|
||||
|
||||
<ThemeToggle />
|
||||
|
||||
<Popover>
|
||||
@@ -298,6 +350,12 @@ export function Header() {
|
||||
{user ? displayName(user) : "Signed in"}
|
||||
</p>
|
||||
{user?.email && <p className="text-sm font-normal text-muted-foreground">{user.email}</p>}
|
||||
{branchLabel && (
|
||||
<p className="mt-1 flex items-center gap-1.5 text-sm font-normal text-muted-foreground">
|
||||
<Building2 className="size-3.5" />
|
||||
{branchLabel}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
|
||||
Reference in New Issue
Block a user