Skip to content

Commit e0a34d5

Browse files
authored
130 Complete navbar element (#170)
* navbar component * fixing ci error * add ts-node as dev dependency
1 parent b579677 commit e0a34d5

8 files changed

Lines changed: 336 additions & 42 deletions

File tree

apps/frontend/package-lock.json

Lines changed: 9 additions & 36 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"jest": "^30.2.0",
3333
"jest-environment-jsdom": "^30.2.0",
3434
"tailwindcss": "^4",
35+
"ts-node": "^10.9.2",
3536
"typescript": "^5"
3637
}
3738
}
9.33 KB
Loading

apps/frontend/public/leaves-bg.png

286 KB
Loading
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
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;

apps/frontend/src/app/page.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
import Header from "./components/Header";
1+
"use client";
2+
3+
import NavBar from "./components/Navbar";
24

35
export default function Home() {
46
return (
5-
<div className="min-h-screen bg-gray-50 font-sans">
6-
{/* 1. Default Header - Verify this matches Figma */}
7-
<Header />
7+
<div style={{ display: "flex", minHeight: "100vh" }}>
8+
<NavBar role="admin" />
9+
<main style={{ flex: 1, backgroundColor: "#f9fafb" }}>
10+
{/* page content goes here */}
11+
</main>
812
</div>
913
);
10-
}
14+
}

apps/frontend/src/app/components/Header.test.tsx renamed to apps/frontend/test/components/Header.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { render, screen } from '@testing-library/react';
22
import '@testing-library/jest-dom'; // Add this line to fix the error
3-
import Header from './Header';
3+
import Header from '../../src/app/components/Header';
44

55
describe('Header Component', () => {
66
it('renders the default title when no props are provided', () => {

0 commit comments

Comments
 (0)