1+ "use client" ;
2+ import Image from "next/image" ;
3+ import React , { useState } from "react" ;
4+ import Link from "next/link" ;
5+ import { usePathname } from "next/navigation" ;
6+ import { PT_Sans } from "next/font/google" ;
7+
8+ const ptSans = PT_Sans ( { subsets : [ "latin" ] , weight : [ "400" , "700" ] } ) ;
9+
10+ // ─── Types & Definitions ──────────────────────────────────────────────────────
11+
12+ export type UserRole = "admin" | "standard" | "limited" ;
13+ interface NavItem { label : string ; href : string ; roles ?: UserRole [ ] ; }
14+
15+ const NAV_ITEMS : NavItem [ ] = [
16+ { label : "Dashboard" , href : "/dashboard" } ,
17+ { label : "Projects" , href : "/projects" } ,
18+ { label : "Donors" , href : "/donors" } ,
19+ { label : "Donations" , href : "/donations" } ,
20+ { label : "Expenses" , href : "/expenses" , roles : [ "admin" ] } ,
21+ { label : "Reports" , href : "/reports" , roles : [ "admin" ] } ,
22+ { label : "Accounts" , href : "/accounts" , roles : [ "admin" ] } ,
23+ { label : "Profile" , href : "/profile" } ,
24+ { label : "Log Out" , href : "/logout" } ,
25+ ] ;
26+
27+ const COLORS = {
28+ white : "#FFFFFF" ,
29+ brandGreen : "#2E6038" ,
30+ menuOverlay : "rgba(46, 96, 56, 0.75)" ,
31+ hoverBg : "rgba(255, 255, 255, 0.2)" ,
32+ } ;
33+
34+ export const NavBar : React . FC < { role ?: UserRole ; activePath ?: string } > = ( {
35+ role = "admin" ,
36+ activePath
37+ } ) => {
38+ const pathname = usePathname ?.( ) ?? "/dashboard" ;
39+ const currentPath = activePath ?? pathname ;
40+
41+ const [ hoveredIndex , setHoveredIndex ] = useState < number | null > ( null ) ;
42+
43+ const visibleItems = NAV_ITEMS . filter ( item => ! item . roles || item . roles . includes ( role ) ) ;
44+ const isActive = ( href : string ) => currentPath === href || ( href !== "/" && currentPath . startsWith ( href ) ) ;
45+
46+ return (
47+ < nav
48+ className = "branch-sidebar"
49+ style = { {
50+ width : 181 ,
51+ minHeight : "100vh" ,
52+ backgroundColor : COLORS . brandGreen ,
53+ display : "flex" ,
54+ flexDirection : "column" ,
55+ fontFamily : ptSans . style . fontFamily ,
56+ position : "relative" ,
57+ overflow : "hidden" ,
58+ } }
59+ >
60+ { /* Background Image Layer */ }
61+ < div style = { { position : "absolute" , inset : 0 , zIndex : 0 } } >
62+ < Image
63+ src = "/leaves-bg.png"
64+ alt = ""
65+ fill
66+ style = { { objectFit : "cover" } }
67+ />
68+ </ div >
69+
70+ { /* Logo Section */ }
71+ < div style = { {
72+ position : "relative" ,
73+ zIndex : 1 ,
74+ padding : "45px 0 25px" ,
75+ display : "flex" ,
76+ flexDirection : "column" ,
77+ alignItems : "center" ,
78+ } } >
79+ < Image src = "/branch-logo.png" alt = "Branch" width = { 75 } height = { 75 } />
80+ < div style = { {
81+ color : COLORS . white ,
82+ fontSize : 18 ,
83+ marginTop : 8 ,
84+ fontWeight : 400 ,
85+ letterSpacing : "0.05em" ,
86+ } } >
87+ BRANCH
88+ </ div >
89+ </ div >
90+
91+ { /* Nav Overlay Section */ }
92+ < div style = { {
93+ position : "relative" ,
94+ zIndex : 2 ,
95+ backgroundColor : COLORS . menuOverlay ,
96+ flexGrow : 1 ,
97+ paddingTop : "4px" ,
98+ } } >
99+ < ul style = { { listStyle : "none" , margin : 0 , padding : 0 } } >
100+ { visibleItems . map ( ( item , index ) => {
101+ const active = isActive ( item . href ) ;
102+ const isHovered = hoveredIndex === index ;
103+
104+ return (
105+ < li
106+ key = { item . href }
107+ onMouseEnter = { ( ) => setHoveredIndex ( index ) }
108+ onMouseLeave = { ( ) => setHoveredIndex ( null ) }
109+ >
110+ < Link
111+ href = { item . href }
112+ style = { {
113+ display : "block" ,
114+ padding : "12px 24px" ,
115+ fontSize : "15px" ,
116+ textDecoration : "none" ,
117+ transition : "background-color 0.2s ease" ,
118+ backgroundColor : active
119+ ? COLORS . white
120+ : ( isHovered ? COLORS . hoverBg : "transparent" ) ,
121+ color : active ? COLORS . brandGreen : COLORS . white ,
122+ fontWeight : active ? 700 : 400 ,
123+ } }
124+ >
125+ { item . label }
126+ </ Link >
127+ </ li >
128+ ) ;
129+ } ) }
130+ </ ul >
131+ </ div >
132+
133+ { /* Bottom spacer */ }
134+ < div style = { { height : "40px" , backgroundColor : COLORS . menuOverlay , zIndex : 2 } } />
135+ </ nav >
136+ ) ;
137+ } ;
138+
139+ export default NavBar ;
0 commit comments