From b7cb85d7fac36d8d0b6a041d41269ad7669b8a23 Mon Sep 17 00:00:00 2001 From: lyannne Date: Mon, 9 Feb 2026 21:29:37 -0500 Subject: [PATCH 01/16] placeholder cash flow page --- frontend/src/main-page/MainPage.tsx | 3 ++- frontend/src/main-page/cash-flow/CashFlowPage.tsx | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 frontend/src/main-page/cash-flow/CashFlowPage.tsx diff --git a/frontend/src/main-page/MainPage.tsx b/frontend/src/main-page/MainPage.tsx index 5c96ac0f..922ec4d9 100644 --- a/frontend/src/main-page/MainPage.tsx +++ b/frontend/src/main-page/MainPage.tsx @@ -4,7 +4,7 @@ import GrantPage from "./grants/GrantPage"; import Header from "./header/Header"; import Users from "./users/Users"; import RestrictedPage from "./restricted/RestrictedPage"; - +import CashFlowPage from "./cash-flow/CashFlowPage"; function MainPage() { @@ -18,6 +18,7 @@ function MainPage() { } /> } /> } /> + } /> {/* fallback route */} } /> diff --git a/frontend/src/main-page/cash-flow/CashFlowPage.tsx b/frontend/src/main-page/cash-flow/CashFlowPage.tsx new file mode 100644 index 00000000..cc9a5114 --- /dev/null +++ b/frontend/src/main-page/cash-flow/CashFlowPage.tsx @@ -0,0 +1,10 @@ +function CashFlowPage() { + return ( +
+

PLACEHOLDER

+ {/* Add more content and components related to cash flow here */} +
+ ); +} + +export default CashFlowPage; \ No newline at end of file From d5902c2bfa31c538b773d8db3898d8ee06cdac4c Mon Sep 17 00:00:00 2001 From: lyannne Date: Wed, 11 Feb 2026 11:02:00 -0500 Subject: [PATCH 02/16] basic starting point for side nav bar in place, put notifications in upper right corner of grant page --- frontend/src/main-page/MainPage.tsx | 8 +-- frontend/src/main-page/grants/GrantPage.tsx | 5 ++ .../{header => navbar}/AccountInfo.tsx | 2 +- .../src/main-page/{header => navbar}/Bell.tsx | 10 ++-- .../{header/Header.tsx => navbar/NavBar.tsx} | 50 +++++++++---------- .../{header => navbar}/UserButton.tsx | 0 .../{header => navbar}/styles/AccountInfo.css | 0 .../{header => navbar}/styles/Header.css | 0 .../notifications/NotificationPopup.tsx | 4 +- frontend/src/styles/notification.css | 2 +- 10 files changed, 44 insertions(+), 37 deletions(-) rename frontend/src/main-page/{header => navbar}/AccountInfo.tsx (97%) rename frontend/src/main-page/{header => navbar}/Bell.tsx (88%) rename frontend/src/main-page/{header/Header.tsx => navbar/NavBar.tsx} (52%) rename frontend/src/main-page/{header => navbar}/UserButton.tsx (100%) rename frontend/src/main-page/{header => navbar}/styles/AccountInfo.css (100%) rename frontend/src/main-page/{header => navbar}/styles/Header.css (100%) diff --git a/frontend/src/main-page/MainPage.tsx b/frontend/src/main-page/MainPage.tsx index 922ec4d9..f03ed9ba 100644 --- a/frontend/src/main-page/MainPage.tsx +++ b/frontend/src/main-page/MainPage.tsx @@ -1,7 +1,7 @@ import { Routes, Route } from "react-router-dom"; import Dashboard from "./dashboard/Dashboard"; import GrantPage from "./grants/GrantPage"; -import Header from "./header/Header"; +import NavBar from "./navbar/NavBar"; import Users from "./users/Users"; import RestrictedPage from "./restricted/RestrictedPage"; import CashFlowPage from "./cash-flow/CashFlowPage"; @@ -10,8 +10,9 @@ function MainPage() { return ( -
-
+
+ +
} /> } /> @@ -22,6 +23,7 @@ function MainPage() { {/* fallback route */} } /> +
); } diff --git a/frontend/src/main-page/grants/GrantPage.tsx b/frontend/src/main-page/grants/GrantPage.tsx index a50c8c74..46a4f805 100644 --- a/frontend/src/main-page/grants/GrantPage.tsx +++ b/frontend/src/main-page/grants/GrantPage.tsx @@ -20,6 +20,7 @@ import { toJS } from "mobx"; import { fetchGrants } from "./filter-bar/processGrantData.ts"; import { UserStatus } from "../../../../middle-layer/types/UserStatus.ts"; import { Navigate } from "react-router-dom"; +import BellButton from "../navbar/Bell.tsx"; interface GrantPageProps { showOnlyMyGrants?: boolean; //if true, filters grants by user email @@ -29,6 +30,7 @@ function GrantPage({ showOnlyMyGrants = false }: GrantPageProps) { const [showNewGrantModal, setShowNewGrantModal] = useState(false); const [wasGrantSubmitted, setWasGrantSubmitted] = useState(false); const [selectedGrant, setSelectedGrant] = useState(null); + const [openModal, setOpenModal] = useState(false); const { user } = useAuthContext(); //gets current logged in user const userObj = toJS(user); @@ -60,6 +62,9 @@ function GrantPage({ showOnlyMyGrants = false }: GrantPageProps) {
setShowNewGrantModal(true)} /> +
setOpenModal(!openModal)}> + +
diff --git a/frontend/src/main-page/header/AccountInfo.tsx b/frontend/src/main-page/navbar/AccountInfo.tsx similarity index 97% rename from frontend/src/main-page/header/AccountInfo.tsx rename to frontend/src/main-page/navbar/AccountInfo.tsx index 066c736b..f53d4504 100644 --- a/frontend/src/main-page/header/AccountInfo.tsx +++ b/frontend/src/main-page/navbar/AccountInfo.tsx @@ -3,7 +3,7 @@ import './styles/AccountInfo.css'; import { logoutUser, } from "../../external/bcanSatchel/actions.ts"; import { useNavigate } from 'react-router-dom'; -import { useAuthContext } from "../../context/auth/authContext"; +import { useAuthContext } from "../../context/auth/authContext.tsx"; import { createPortal } from 'react-dom'; interface AccountInfoProps { diff --git a/frontend/src/main-page/header/Bell.tsx b/frontend/src/main-page/navbar/Bell.tsx similarity index 88% rename from frontend/src/main-page/header/Bell.tsx rename to frontend/src/main-page/navbar/Bell.tsx index ed8f0b3f..81f2dc0b 100644 --- a/frontend/src/main-page/header/Bell.tsx +++ b/frontend/src/main-page/navbar/Bell.tsx @@ -13,8 +13,8 @@ import { api } from "../../api"; interface BellButtonProps { // onClick handler to open notification popup - setOpenModal: (modal: string | null) => void; - openModal: string | null; + setOpenModal: (open: boolean) => void; + openModal: boolean; } const BellButton: React.FC = observer(({ setOpenModal, openModal }) => { @@ -38,7 +38,7 @@ const BellButton: React.FC = observer(({ setOpenModal, openModa console.log(response); const currNotifications = await response.json(); setNotificationsAction(currNotifications); - setOpenModal(openModal === "bell" ? null : "bell"); + setOpenModal(!openModal); return notifications; }; @@ -48,7 +48,7 @@ const BellButton: React.FC = observer(({ setOpenModal, openModa className="bell-wrapper inline-block relative p-2 hover:bg-primary-700 rounded-md" >
- {(openModal === "bell" ? ( + {(openModal ? ( diff --git a/frontend/src/main-page/header/Header.tsx b/frontend/src/main-page/navbar/NavBar.tsx similarity index 52% rename from frontend/src/main-page/header/Header.tsx rename to frontend/src/main-page/navbar/NavBar.tsx index 3c2766f8..06cceca9 100644 --- a/frontend/src/main-page/header/Header.tsx +++ b/frontend/src/main-page/navbar/NavBar.tsx @@ -22,16 +22,15 @@ interface NavBarProps { const linkList: NavBarProps[] = [ { name: "Dashboard", linkTo: "/main/dashboard" }, - { name: "All Grants", linkTo: "/main/all-grants" }, - { name: "My Grants", linkTo: "/main/my-grants" }, + { name: "Grants", linkTo: "/main/all-grants" }, + { name: "Cash Flow", linkTo: "/main/cash-flow" }, ]; /** * Header component provides the main navigation along with a settings cog. * The cog displays a dropdown with "My Account" and "Logout" options. */ -const Header: React.FC = observer(() => { - const [openModal, setOpenModal] = useState(null); +const NavBar: React.FC = observer(() => { function categoryClicked( e: React.MouseEvent, @@ -46,40 +45,41 @@ const Header: React.FC = observer(() => { return ( -
-
- BCAN Logo +
+ ); }); -export default Header; +export default NavBar; diff --git a/frontend/src/main-page/header/UserButton.tsx b/frontend/src/main-page/navbar/UserButton.tsx similarity index 100% rename from frontend/src/main-page/header/UserButton.tsx rename to frontend/src/main-page/navbar/UserButton.tsx diff --git a/frontend/src/main-page/header/styles/AccountInfo.css b/frontend/src/main-page/navbar/styles/AccountInfo.css similarity index 100% rename from frontend/src/main-page/header/styles/AccountInfo.css rename to frontend/src/main-page/navbar/styles/AccountInfo.css diff --git a/frontend/src/main-page/header/styles/Header.css b/frontend/src/main-page/navbar/styles/Header.css similarity index 100% rename from frontend/src/main-page/header/styles/Header.css rename to frontend/src/main-page/navbar/styles/Header.css diff --git a/frontend/src/main-page/notifications/NotificationPopup.tsx b/frontend/src/main-page/notifications/NotificationPopup.tsx index ca7e4661..65b5b83e 100644 --- a/frontend/src/main-page/notifications/NotificationPopup.tsx +++ b/frontend/src/main-page/notifications/NotificationPopup.tsx @@ -8,7 +8,7 @@ import { getAppStore } from "../../external/bcanSatchel/store"; import { observer } from 'mobx-react-lite'; interface NotificationPopupProps { - setOpenModal: (value: string | null) => void; + setOpenModal: (open: boolean) => void; } const NotificationPopup: React.FC = observer(({ @@ -54,7 +54,7 @@ const NotificationPopup: React.FC = observer(({

Alerts

-
diff --git a/frontend/src/styles/notification.css b/frontend/src/styles/notification.css index 2fbd93fa..a63bb537 100644 --- a/frontend/src/styles/notification.css +++ b/frontend/src/styles/notification.css @@ -1,6 +1,6 @@ .notification-popup { position: absolute; - right: 7.5rem; + right: 3rem; top: 75px; width: min(340px, 70%); background-color: white; From 91f7366e048c95c8e6ef600b2ea04326670d4ecc Mon Sep 17 00:00:00 2001 From: lyannne Date: Thu, 12 Feb 2026 00:39:50 -0500 Subject: [PATCH 03/16] refined nav bar --- frontend/src/main-page/MainPage.tsx | 2 + frontend/src/main-page/navbar/NavBar.tsx | 78 +++++++++++++++---- .../src/main-page/settings/SettingsPage.tsx | 10 +++ 3 files changed, 74 insertions(+), 16 deletions(-) create mode 100644 frontend/src/main-page/settings/SettingsPage.tsx diff --git a/frontend/src/main-page/MainPage.tsx b/frontend/src/main-page/MainPage.tsx index f03ed9ba..2a6f0cef 100644 --- a/frontend/src/main-page/MainPage.tsx +++ b/frontend/src/main-page/MainPage.tsx @@ -5,6 +5,7 @@ import NavBar from "./navbar/NavBar"; import Users from "./users/Users"; import RestrictedPage from "./restricted/RestrictedPage"; import CashFlowPage from "./cash-flow/CashFlowPage"; +import SettingsPage from "./settings/SettingsPage"; function MainPage() { @@ -20,6 +21,7 @@ function MainPage() { } /> } /> } /> + } /> {/* fallback route */} } /> diff --git a/frontend/src/main-page/navbar/NavBar.tsx b/frontend/src/main-page/navbar/NavBar.tsx index 06cceca9..48c6428b 100644 --- a/frontend/src/main-page/navbar/NavBar.tsx +++ b/frontend/src/main-page/navbar/NavBar.tsx @@ -1,4 +1,4 @@ -import { Link } from "react-router-dom"; +import { Link, useNavigate } from "react-router-dom"; import "./styles/Header.css"; import logo from "../../images/logo.svg"; import { @@ -6,31 +6,36 @@ import { stringToStatus, } from "../../../../middle-layer/types/Status.ts"; import { + logoutUser, updateFilter, } from "../../external/bcanSatchel/actions.ts"; import { observer } from "mobx-react-lite"; -import BellButton from "./Bell.tsx"; import { useLocation } from 'react-router-dom'; -import UserButton from "./UserButton.tsx"; -import { useState } from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faChartLine, faFileInvoiceDollar, faMoneyBillWave, faGear, faRightFromBracket, faUsers } from "@fortawesome/free-solid-svg-icons"; +import { getAppStore } from "../../external/bcanSatchel/store"; +import { UserStatus } from "../../../../middle-layer/types/UserStatus"; interface NavBarProps { name: string; linkTo?: string; filter?: Status; + icon?: any; } const linkList: NavBarProps[] = [ - { name: "Dashboard", linkTo: "/main/dashboard" }, - { name: "Grants", linkTo: "/main/all-grants" }, - { name: "Cash Flow", linkTo: "/main/cash-flow" }, + { name: "Dashboard", linkTo: "/main/dashboard", icon: faChartLine }, + { name: "Grants", linkTo: "/main/all-grants", icon: faFileInvoiceDollar }, + { name: "Cash Flow", linkTo: "/main/cash-flow", icon: faMoneyBillWave }, ]; /** - * Header component provides the main navigation along with a settings cog. - * The cog displays a dropdown with "My Account" and "Logout" options. + * Sidebar component provides the main navigation. */ const NavBar: React.FC = observer(() => { + const navigate = useNavigate(); + const user = getAppStore().user; + const isAdmin = user?.position === UserStatus.Admin; function categoryClicked( e: React.MouseEvent, @@ -43,39 +48,80 @@ const NavBar: React.FC = observer(() => { } } + const handleLogout = () => { + logoutUser(); + navigate("/login"); + }; + return ( -