Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions frontend/src/animations/AnimatedRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Routes, Route, useLocation, Navigate } from "react-router-dom";
import "./transitions.css";

import { observer } from "mobx-react-lite";
import Account from "../Account";
import { useAuthContext } from "../context/auth/authContext";
import MainPage from "../main-page/MainPage";
import Login from "../Login";
Expand All @@ -25,12 +24,12 @@ const AnimatedRoutes = observer(() => {
<Routes location={location}>
<Route
path="/login"
element={isAuthenticated ? <Navigate to="/account" /> : <Login />}
element={isAuthenticated ? <Navigate to="/main/all-grants" /> : <Login />}
/>
<Route
path="/register"
element={
isAuthenticated ? <Navigate to="/account" /> : <Register />
isAuthenticated ? <Navigate to="/main/all-grants" /> : <Register />
}
/>
<Route
Expand All @@ -39,15 +38,11 @@ const AnimatedRoutes = observer(() => {
<RegisterLanding />
}
/>
<Route
path="/account"
element={isAuthenticated ? <Account /> : <Navigate to="/login" />}
/>
<Route path="/main/*" element={<MainPage/>} />
<Route
path="*"
element={
<Navigate to={isAuthenticated ? "/account" : "/login"} />
<Navigate to={isAuthenticated ? "/main/all-grants" : "/login"} />
}
/>
</Routes>
Expand Down
13 changes: 6 additions & 7 deletions frontend/src/custom/RingButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Button } from "@chakra-ui/react";
import "../styles/button.css";

/* Maintained with button.css */
Expand All @@ -25,28 +24,28 @@ export default function RingButton({ text, color }: RingButtonProps) {
return (
<>
{ButtonColorOption.GREEN === color && (
<Button
<div
className="green-button button-default"
style={{ width: "100%", border: "none", cursor: "default" }}
>
{text}
</Button>
</div>
)}
{ButtonColorOption.ORANGE === color && (
<Button
<div
className="orange-button button-default"
style={{ width: "100%", border: "none", cursor: "default" }}
>
{text}
</Button>
</div>
)}
{ButtonColorOption.GRAY === color && (
<Button
<div
className="gray-button button-default"
style={{ width: "100%", border: "none", cursor: "default" }}
>
{text}
</Button>
</div>
)}
</>
);
Expand Down
76 changes: 76 additions & 0 deletions frontend/src/main-page/header/AccountInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useState } from 'react';
import './styles/AccountInfo.css';
import { logoutUser,
} from "../../external/bcanSatchel/actions.ts";
import { useNavigate } from 'react-router-dom';
import { useAuthContext } from "../../context/auth/authContext";
import { createPortal } from 'react-dom';

interface AccountInfoProps {
email: string;
username: string;
role: string;
setOpenModal: (modal: string | null) => void;
}

const AccountInfo: React.FC<AccountInfoProps> = ({
email,
username,
role,
setOpenModal,
}) => {

const navigate = useNavigate();
const {user} = useAuthContext();

const [isAdmin] = useState(user?.position === 'Admin');

const handleUserListClick = () => {
navigate('users');
setOpenModal(null);
};

const handleLogoutClick = () => {
logoutUser();
setOpenModal(null);
};

return createPortal(
<div className="account-modal" onClick={(e) => e.stopPropagation()}>
<div className="account-popup">
<h1 className="popup-header">Account Info</h1>

<div className="account-info">
<div className="info-row">
<span className="info-label">E-mail:</span>
<span className="info-value">{email}</span>
</div>
<div className="info-row">
<span className="info-label">Username:</span>
<span className="info-value">{username}</span>
</div>
<div className="info-row">
<span className="info-label">Role:</span>
<span className="info-value">{role}</span>
</div>
</div>
{isAdmin &&
<div className="button-container">
<button className="user-list-btn" onClick={handleUserListClick}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 12C7 12 6 12 6 11C6 10 7 7 11 7C15 7 16 10 16 11C16 12 15 12 15 12H7ZM11 6C11.7956 6 12.5587 5.68393 13.1213 5.12132C13.6839 4.55871 14 3.79565 14 3C14 2.20435 13.6839 1.44129 13.1213 0.87868C12.5587 0.316071 11.7956 0 11 0C10.2044 0 9.44129 0.316071 8.87868 0.87868C8.31607 1.44129 8 2.20435 8 3C8 3.79565 8.31607 4.55871 8.87868 5.12132C9.44129 5.68393 10.2044 6 11 6ZM5.216 12C5.06782 11.6878 4.9939 11.3455 5 11C5 9.645 5.68 8.25 6.936 7.28C6.30918 7.08644 5.65598 6.99197 5 7C1 7 0 10 0 11C0 12 1 12 1 12H5.216ZM4.5 6C5.16304 6 5.79893 5.73661 6.26777 5.26777C6.73661 4.79893 7 4.16304 7 3.5C7 2.83696 6.73661 2.20107 6.26777 1.73223C5.79893 1.26339 5.16304 1 4.5 1C3.83696 1 3.20107 1.26339 2.73223 1.73223C2.26339 2.20107 2 2.83696 2 3.5C2 4.16304 2.26339 4.79893 2.73223 5.26777C3.20107 5.73661 3.83696 6 4.5 6Z" fill="black"/>
</svg>
User List </button>
<button className="logout-btn" onClick={handleLogoutClick}>
Logout
</button>
</div>
}
</div>
</div>,
document.body
);
};


export default AccountInfo;
73 changes: 37 additions & 36 deletions frontend/src/main-page/header/Bell.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faBell } from "@fortawesome/free-solid-svg-icons";
import { useEffect, useState } from "react";
import { useEffect } from "react";
//import { api } from "../../api"; //todo: swap out dummy data with real api fetch when backend is ready
import NotificationPopup from "../notifications/NotificationPopup";
import { setNotifications as setNotificationsAction } from "../../external/bcanSatchel/actions";
import { getAppStore } from "../../external/bcanSatchel/store";
import { observer } from "mobx-react-lite";
import { api } from "../../api";

// get current user id
// const currUserID = sessionStorage.getItem('userId');
// const currUserID = "bcanuser33";

const BellButton = observer(() => {
interface BellButtonProps {
// onClick handler to open notification popup
setOpenModal: (modal: string | null) => void;
openModal: string | null;
}

const BellButton: React.FC<BellButtonProps> = observer(({ setOpenModal, openModal }) => {
// stores notifications for the current user
const store = getAppStore();
const notifications = store.notifications ?? [];

// determines whether bell has been clicked
const [isClicked, setClicked] = useState(false);

// logs the notifications for the current user whenever they are fetched
useEffect(() => {
console.log(notifications);
Expand All @@ -27,44 +31,41 @@ const BellButton = observer(() => {
// function that handles when button is clicked and fetches notifications
const handleClick = async () => {
//temporary dummy data for now
const dummyNotifications = [
{
id: 1,
title: "Grant Deadline",
message: "Grant A deadline approaching in 3 days",
},
{ id: 2, title: "Grant Deadline", message: "Grant B deadline tomorrow!" },
{
id: 3,
title: "Grant Deadline",
message: "Grant C deadline passed yesterday!",
},
{ id: 4, title: "Grant Deadline", message: "Grant D deadline tomorrow!" },
];
//previous api logic (for later)
//const response = await api(
//`/notifications/user/${currUserID}`,
//{
//method: "GET",
//}
//);
//console.log(response);
//const currNotifications = await response.json();
setNotificationsAction(dummyNotifications);
setClicked(!isClicked);
// const dummyNotifications = [
// {
// id: 1,
// title: "Grant Deadline",
// message: "Grant A deadline approaching in 3 days",
// },
// { id: 2, title: "Grant Deadline", message: "Grant B deadline tomorrow!" },
// {
// id: 3,
// title: "Grant Deadline",
// message: "Grant C deadline passed yesterday!",
// },
// { id: 4, title: "Grant Deadline", message: "Grant D deadline tomorrow!" },
// ];
const response = await api(
`/notifications/user/${store.user?.userId}`,
{
method: "GET",
}
);
console.log(response);
const currNotifications = await response.json();
setNotificationsAction(currNotifications);
setOpenModal(openModal === "bell" ? null : "bell");
return notifications;
};

const handleClose = () => setClicked(false);

return (
<div className="bell-container">
<div
className="bell-wrapper"
style={{ position: "relative", display: "inline-block" }}
>
<button
className={`bell-button ${isClicked ? "hovered" : ""}`}
className={`bell-button ${openModal === "bell" ? "hovered" : ""}`}
onClick={handleClick}
style={{ background: "none", position: "relative" }}
>
Expand All @@ -90,12 +91,12 @@ const BellButton = observer(() => {
)}
</div>

{isClicked && (
{(openModal === "bell" ? (
<NotificationPopup
notifications={notifications}
onClose={handleClose}
setOpenModal={setOpenModal}
/>
)}
) : null)}
</div>
);
});
Expand Down
37 changes: 8 additions & 29 deletions frontend/src/main-page/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@ import {
} from "../../../../middle-layer/types/Status.ts";
import {
updateFilter,
logoutUser,
} from "../../external/bcanSatchel/actions.ts";
import { observer } from "mobx-react-lite";
import { Menu, Button } from "@chakra-ui/react";
import { FaCog } from "react-icons/fa";
import BellButton from "./Bell.tsx";
import { useLocation } from 'react-router-dom';
import UserButton from "./UserButton.tsx";
import { useState } from "react";

interface NavBarProps {
name: string;
Expand All @@ -33,6 +31,7 @@ const linkList: NavBarProps[] = [
* The cog displays a dropdown with "My Account" and "Logout" options.
*/
const Header: React.FC = observer(() => {
const [openModal, setOpenModal] = useState<string | null>(null);

function categoryClicked(
e: React.MouseEvent,
Expand All @@ -45,10 +44,7 @@ const Header: React.FC = observer(() => {
}
}

const handleLogout = () => {
logoutUser();
};


return (
<header className="header bg-pale-orange drop-shadow-md">
<div className="header-left-comp">
Expand All @@ -74,29 +70,12 @@ const Header: React.FC = observer(() => {
))}
</ul>
<div className="header-right-controls flex items-center gap-2">
<div className="bell-container">
<BellButton />
<div className="bell-container" onClick={() => setOpenModal(openModal === "bell" ? null : "bell")}>
<BellButton setOpenModal={setOpenModal} openModal={openModal} />
</div>
<div className="user-container" onClick={() => setOpenModal(openModal === "user" ? null : "user")}>
<UserButton setOpenModal={setOpenModal} openModal={openModal} />
</div>
<Menu.Root>
<Menu.Trigger asChild>
<Button variant="ghost" p={1}>
<FaCog size={24} />
</Button>
</Menu.Trigger>
<Menu.Positioner>
<Menu.Content>
<Menu.Item value="account">
<Link to="/account">My Account</Link>
</Menu.Item>
<Menu.Item value="logout">
<Link onClick={handleLogout} to="/login">
Logout
</Link>
</Menu.Item>
</Menu.Content>
</Menu.Positioner>
</Menu.Root>
<UserButton />
</div>
</div>
</header>
Expand Down
Loading