Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge to Prod #171

Open
wants to merge 21 commits into
base: prod
Choose a base branch
from
Open
Changes from 1 commit
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
Prev Previous commit
Next Next commit
137 Bugfixes and Chapter Managment (#141)
* implemented add volunteer modal and its operation success popup, fixed operation success sizing issue

* fixed live dropdowns to handle selection changes for certain edge cases

* fixed pagination

* fixed pendingApprovals not updating correctly, added conditional notif bubble

* approve and deny success popups implemented

* added all success popups for volunteer actions, added refreshUsers to add volunteer

* correctly rename variables

* implemented success popup for editing account

* implemented success popup for editing account

* Fix formatting with rows and unecessary commas

---------

Co-authored-by: Johannes Qian <[email protected]>
ND68 and johannesq23 authored Nov 3, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit be387683d5764dcd9687ae1d08244afdb10f4637
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Brain Exercise Initative 🧠

## About
Brain Exercise Initative is a nonprofit focused on preventing memory loss through brain exercise. Through innovative research in Japan, it was found that doing simple math and reading exercises aloud caused improvements in cognitive function. Brain Exercise Initiative builds off of this research, holding brain exercise programs at retirement homes.

Brain Exercise Initative is a nonprofit focused on preventing memory loss through brain exercise. Through innovative research in Japan, it was found that doing simple math and reading exercises aloud caused improvements in cognitive function. Brain Exercise Initiative builds off of this research, holding brain exercise programs at retirement homes.

## Getting Started

@@ -20,7 +20,6 @@ yarn install

Install [MongoDB Community Server](https://www.mongodb.com/docs/manual/administration/install-community/) to host a local instance of MongoDB. It may also be helpful to download [MongoDB Compass](https://www.mongodb.com/try/download/compass#compass) to view the state of your database.


### Environment Variables

In the root directory, run one of these commands based on your OS:
6 changes: 5 additions & 1 deletion src/app/(management-portal)/chapter/[name]/page.tsx
Original file line number Diff line number Diff line change
@@ -139,7 +139,11 @@ export default function Page({ params }: { params: { name: string } }) {
<LoadingBox />
</Modal>
<div className={classes(styles["profile-container"])}>
<ChapterInfo chapter={chapter} chapterPresident={chapterPresident} />
<ChapterInfo
chapter={chapter}
chapterPresident={chapterPresident}
refreshUsers={fetchUsers}
/>
<Divider />
</div>
<div className={classes(styles["search-container"])}>
5 changes: 5 additions & 0 deletions src/app/(management-portal)/layout.module.css
Original file line number Diff line number Diff line change
@@ -26,3 +26,8 @@
width: 85%;
height: 85%;
}

.operationSuccessModal {
width: 35%;
height: 23%;
}
13 changes: 12 additions & 1 deletion src/app/(management-portal)/layout.tsx
Original file line number Diff line number Diff line change
@@ -11,10 +11,12 @@ import useAuth from "@src/hooks/useAuth";
import { RootState } from "@src/redux/rootReducer";

import Modal from "@src/components/Modal/Modal";
import OperationSuccessModal from "@src/components/OperationSuccessModal/OperationSuccessModal";
import styles from "./layout.module.css";

export default function Layout({ children }: { children: React.ReactNode }) {
const [showModal, setShowModal] = useState(false);
const [showSuccessModal, setShowSuccessModal] = useState(false);
const dispatch = useDispatch();
const { email } = useSelector((state: RootState) => state.auth);
const { logout } = useAuth();
@@ -50,7 +52,16 @@ export default function Layout({ children }: { children: React.ReactNode }) {
</div>
<div className={styles["rest-of-page"]}>
<Modal showModal={showModal} setShowModal={setShowModal}>
<AccountEditModal className={styles.accountEditModalContent} />
<AccountEditModal
className={styles.accountEditModalContent}
setShowSuccessModal={setShowSuccessModal}
/>
</Modal>
<Modal showModal={showSuccessModal} setShowModal={setShowSuccessModal}>
<OperationSuccessModal
className={styles.operationSuccessModal}
subtitle="Account Successfully Updated"
/>
</Modal>
{children}
</div>
2 changes: 1 addition & 1 deletion src/app/(management-portal)/volunteer/approval/page.tsx
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ export default function Page() {
}).then((res) => {
setPageCount(res?.numPages ?? 0);
setFilteredUsers(res?.data ?? []);
dispatch(update({ pendingApprovals: res?.numRecords }));
dispatch(update({ pendingApprovals: res?.numRecords ?? 0 }));
setLoading(false);
});
}, [
5 changes: 5 additions & 0 deletions src/app/(management-portal)/volunteer/search/page.module.css
Original file line number Diff line number Diff line change
@@ -63,3 +63,8 @@
width: 100%;
height: 100%;
}

.operationSuccessModal {
width: 35%;
height: 23%;
}
9 changes: 7 additions & 2 deletions src/components/AccountEditModal/AccountEditModal.tsx
Original file line number Diff line number Diff line change
@@ -15,9 +15,10 @@ const enum Page {
interface Props {
className?: string;
style?: CSSProperties;
setShowSuccessModal: (args: boolean) => void;
}

const Modal = ({ className, style }: Props) => {
const Modal = ({ className, style, setShowSuccessModal }: Props) => {
const [page, setPage] = useState<Page>(Page.PROFILE);
const { logout } = useAuth();
const router = useRouter();
@@ -51,7 +52,11 @@ const Modal = ({ className, style }: Props) => {
<div className={styles.vl}></div>
<div className={styles.info}>
{/* <span onClick={closeModal}>&times;</span> */}
{page === Page.PROFILE ? <Profile /> : <Password />}
{page === Page.PROFILE ? (
<Profile setShowSuccessModal={setShowSuccessModal} />
) : (
<Password setShowSuccessModal={setShowSuccessModal} />
)}
</div>
</div>
);
7 changes: 6 additions & 1 deletion src/components/AccountEditModal/Password.tsx
Original file line number Diff line number Diff line change
@@ -9,7 +9,11 @@ import {
import styles from "./AccountEditModal.module.css";
import InputField from "../InputField/InputField";

export default function Password() {
interface Props {
setShowSuccessModal: (args: boolean) => void;
}

export default function Password({ setShowSuccessModal }: Props) {
const [oldPassword, setOldPassword] = useState<string>("");
const [newPassword, setNewPassword] = useState<string>("");
const [confirmNewPassword, setConfirmNewPassword] = useState<string>("");
@@ -74,6 +78,7 @@ export default function Password() {
}

await updatePassword(getAuth().currentUser!, newPassword);
setShowSuccessModal(true);
reset();
};

8 changes: 6 additions & 2 deletions src/components/AccountEditModal/Profile.tsx
Original file line number Diff line number Diff line change
@@ -13,7 +13,11 @@ import { HttpMethod, IUser } from "@/common_utils/types";
import styles from "./AccountEditModal.module.css";
import Chip from "../Chip/Chip";

export default function Profile() {
interface Props {
setShowSuccessModal: (args: boolean) => void;
}

export default function Profile({ setShowSuccessModal }: Props) {
const [edit, setEdit] = useState<boolean>(false);
const dispatch = useDispatch();
const router = useRouter();
@@ -146,7 +150,6 @@ export default function Profile() {
});

setTempImageLink(null);

// Logout user if email is changed so they can reauthenticate
if (updatedEmail !== email) {
await logout();
@@ -156,6 +159,7 @@ export default function Profile() {
dispatch(update(updatedUser));
setUnupdatedBirthDate(updatedBirthDate);
setEdit(false);
setShowSuccessModal(true);
}, [
dispatch,
logout,
2 changes: 2 additions & 0 deletions src/components/AddChapterModal/AddChapterModal.tsx
Original file line number Diff line number Diff line change
@@ -123,6 +123,8 @@ const AddChapterModal = ({
type ChangeHandler = React.ChangeEventHandler<HTMLInputElement>;
const handleChange: ChangeHandler = (e) => {
const { target } = e;
setChapterPresidentObject(null);

if (!target.value.trim()) return setFilteredVolunteers([]);

const filteredValue = volunteers?.filter((volunteer) =>
32 changes: 10 additions & 22 deletions src/components/AddVolunteerModal/AddVolunteerModal.module.css
Original file line number Diff line number Diff line change
@@ -36,8 +36,17 @@
font-style: normal;
font-weight: 600;
line-height: normal;
margin-bottom: -1%;
}

.inputSubheader {
color: var(--Dark-Blue-Grey, #9ca5c2);
/* H2 */
font-size: 22px;
font-style: normal;
font-weight: 600;
line-height: normal;
margin-bottom: 2%;
gap: 1fr;
}

.inputField {
@@ -55,27 +64,6 @@
font-size: 12px;
}

.locationField {
display: flex;
flex-direction: column;
}

.cityStateFields {
display: flex;
column-gap: 10px;
}

.cityStateFields > * {
/* flex: 1 */
width: calc((70% - 10px) / 2);
}

@media (max-width: 1000px) {
.cityStateFields {
flex-direction: column;
}
}

.nonEditable {
background-color: #e7eeff;
padding-left: 15px;
384 changes: 146 additions & 238 deletions src/components/AddVolunteerModal/AddVolunteerModal.tsx

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion src/components/ChapterGrid/Row/Row.tsx
Original file line number Diff line number Diff line change
@@ -39,7 +39,9 @@ export function Row({ chapter }: Props) {
styles.nameCellContainer,
)}
>
{`${chapter.location.state}, ${chapter.location.country}`}
{chapter.location.state
? `${chapter.location.state}, ${chapter.location.country}`
: chapter.location.country}
</div>
</td>

10 changes: 8 additions & 2 deletions src/components/ChapterInfo/ChapterInfo.module.css
Original file line number Diff line number Diff line change
@@ -65,9 +65,15 @@
}

.addVolunteerModalContent {
width: 60%;
height: 70%;
width: 50%;
height: 45%;
}

.addVolunteerOperationSuccessModal {
width: 35%;
height: 30%;
}

/* .backButton {
flex-direction: row;
color:#2b3674;
16 changes: 16 additions & 0 deletions src/components/ChapterInfo/ChapterInfo.tsx
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ import TransferChapterModal from "../TransferChapterModal/TransferChapterModal";
interface ChapterInfoProps {
chapter: IChapter;
chapterPresident: string;
refreshUsers: () => void;
}

export default function ChapterInfo(params: ChapterInfoProps) {
@@ -44,6 +45,8 @@ export default function ChapterInfo(params: ChapterInfoProps) {
useState(false);

const [showAddVolunteerModal, setShowAddVolunteerModal] = useState(false);
const [showAddVolunteerSuccessModal, setShowAddVolunteerSuccessModal] =
useState(false);

const chapterProfile = useMemo<CellProps[]>(() => {
return [
@@ -222,6 +225,19 @@ export default function ChapterInfo(params: ChapterInfoProps) {
<AddVolunteerModal
className={styles.addVolunteerModalContent}
setShowModal={setShowAddVolunteerModal}
setShowSuccessModal={setShowAddVolunteerSuccessModal}
chapter={params.chapter}
refreshUsers={params.refreshUsers}
/>
</Modal>
<Modal
showModal={showAddVolunteerSuccessModal}
setShowModal={setShowAddVolunteerSuccessModal}
>
<OperationSuccessModal
className={styles.addVolunteerOperationSuccessModal}
subtitle="You have successfully added a volunteer to"
title={params.chapter.name}
/>
</Modal>
</div>
5 changes: 5 additions & 0 deletions src/components/ChapterVolunteerGrid/VolunteerGrid.module.css
Original file line number Diff line number Diff line change
@@ -93,3 +93,8 @@
.atLimit {
visibility: hidden;
}

.operationSuccessModal {
width: 35%;
height: 23%;
}
10 changes: 10 additions & 0 deletions src/components/ChapterVolunteerGrid/VolunteerGrid.tsx
Original file line number Diff line number Diff line change
@@ -10,6 +10,8 @@ import TwoVolunteersIcon from "@src/app/icons/TwoVolunteersIcon";
import styles from "./VolunteerGrid.module.css";
import Popup from "./Popup/Popup";
import { Row } from "./Row/Row";
import Modal from "../Modal/Modal";
import OperationSuccessModal from "../OperationSuccessModal/OperationSuccessModal";

interface VolunteerGridProps {
data: IUser[];
@@ -64,6 +66,7 @@ export default function VolunteerGrid(params: VolunteerGridProps) {
const [removeVolunteerEmail, setRemoveVolunteerEmail] = useState<
string | null
>(null);
const [showSuccessModal, setShowSuccessModal] = useState(false);

const handleConfirmDelete = async () => {
if (removeVolunteerEmail !== null) {
@@ -82,6 +85,7 @@ export default function VolunteerGrid(params: VolunteerGridProps) {
params.refreshUsers();
}
setPopupOpen(false);
setShowSuccessModal(true);
};

const handleClosePopup = useCallback(() => {
@@ -125,6 +129,12 @@ export default function VolunteerGrid(params: VolunteerGridProps) {
pageCount={params.pageCount}
currentPage={params.currentPage}
/>
<Modal showModal={showSuccessModal} setShowModal={setShowSuccessModal}>
<OperationSuccessModal
className={styles.operationSuccessModal}
subtitle="Volunteer Successfully Removed"
/>
</Modal>
</div>
);
}
4 changes: 3 additions & 1 deletion src/components/NavigationPanel/NavigationPanel.tsx
Original file line number Diff line number Diff line change
@@ -228,7 +228,9 @@ const NavigationPanel = ({ onClick }: Props) => {
<div className={styles["overall-metrics"]}>
<span>Pending Approval</span>
</div>
<div className={styles["red-bubble"]}>{pendingApprovals}</div>
{pendingApprovals > 0 && (
<div className={styles["red-bubble"]}>{pendingApprovals}</div>
)}
</Link>
</div>
</>
Original file line number Diff line number Diff line change
@@ -16,8 +16,10 @@
}

.checkCircle {
width: 38px;
height: 38px;
width: 45px;
height: 45px;
min-width: 38px;
min-height: 38px;
}

.bigText {
3 changes: 2 additions & 1 deletion src/components/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -10,9 +10,10 @@ interface DataParams {
const Pagination = (params: DataParams) => {
const pages = useMemo(() => {
const forwardPages: number[] = [];
const numForwardPages = params.currentPage === 0 ? 4 : 3;
for (
let i = params.currentPage + 1;
i <= params.pageCount && forwardPages.length !== 4;
i <= params.pageCount && forwardPages.length !== numForwardPages;
i += 1
) {
forwardPages.push(i);
2 changes: 2 additions & 0 deletions src/components/TransferChapterModal/TransferChapterModal.tsx
Original file line number Diff line number Diff line change
@@ -85,6 +85,8 @@ const TransferChapterModal = ({
type ChangeHandler = React.ChangeEventHandler<HTMLInputElement>;
const handleChange: ChangeHandler = (e) => {
const { target } = e;
setChapterPresidentObject(null);

if (!target.value.trim()) return setFilteredVolunteers([]);

const filteredValue = volunteers?.filter((volunteer) =>
16 changes: 15 additions & 1 deletion src/components/VolunteerApprovalGrid/Row/Row.tsx
Original file line number Diff line number Diff line change
@@ -26,6 +26,8 @@ import styles from "./Row.module.css";
interface Props {
volunteer: IUser;
refreshUsers: () => void;
setShowModal: (arg: boolean) => void;
setSuccessMessage: (arg: string) => void;
}

function ExpandedRow({ row }: { row: IUser }) {
@@ -103,7 +105,12 @@ function ExpandedRow({ row }: { row: IUser }) {
);
}

export function Row({ volunteer, refreshUsers }: Props) {
export function Row({
volunteer,
refreshUsers,
setShowModal,
setSuccessMessage,
}: Props) {
const [view, setView] = useState<boolean>(false);
const handleClick = useCallback(() => setView((v) => !v), []);
// Role of user corresponding to the given row
@@ -136,6 +143,13 @@ export function Row({ volunteer, refreshUsers }: Props) {
},
});
refreshUsers();
if (approvalStatus) {
setSuccessMessage("Volunteer Successfully Approved");
setShowModal(true);
} else {
setSuccessMessage("Volunteer Successfully Denied");
setShowModal(true);
}
};

return (
Original file line number Diff line number Diff line change
@@ -55,3 +55,8 @@
.atLimit {
visibility: hidden;
}

.operationSuccessModal {
width: 35%;
height: 23%;
}
15 changes: 14 additions & 1 deletion src/components/VolunteerApprovalGrid/VolunteerApprovalGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import React from "react";
import React, { useState } from "react";
import DataGrid from "@src/components/DataGrid/DataGrid";
import Pagination from "@src/components/Pagination/Pagination";
import { IUser, SortField } from "@/common_utils/types";
@@ -9,6 +9,8 @@ import TwoVolunteersIcon from "@src/app/icons/TwoVolunteersIcon";

import { Row } from "./Row/Row";
import styles from "./VolunteerApprovalGrid.module.css";
import Modal from "../Modal/Modal";
import OperationSuccessModal from "../OperationSuccessModal/OperationSuccessModal";

interface VolunteerApprovalGridProps {
data: IUser[];
@@ -52,13 +54,18 @@ function Header() {
export default function VolunteerApprovalGrid(
params: VolunteerApprovalGridProps,
) {
const [showSuccessModal, setShowSuccessModal] = useState(false);
const [successMessage, setSuccessMessage] = useState("");

// Construct Rows from the volunteers
const Rows = params.data.map((volunteer) => {
return (
<Row
key={`volunteer-${volunteer._id}`}
volunteer={volunteer}
refreshUsers={params.refreshUsers}
setShowModal={setShowSuccessModal}
setSuccessMessage={setSuccessMessage}
/>
);
});
@@ -80,6 +87,12 @@ export default function VolunteerApprovalGrid(
pageCount={params.pageCount}
currentPage={params.currentPage}
/>
<Modal showModal={showSuccessModal} setShowModal={setShowSuccessModal}>
<OperationSuccessModal
className={styles.operationSuccessModal}
subtitle={successMessage}
/>
</Modal>
</div>
);
}
2 changes: 1 addition & 1 deletion src/components/VolunteerGrid/Popup/Popup.tsx
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ const Popup = ({
return (
<div className={styles.popupOverlay}>
<div className={styles.popup}>
<div className={styles.popupTitle}>Remove from Chapter</div>
<div className={styles.popupTitle}>Delete Account</div>
<div className={styles.popupContent}>
Deleting this account will remove all of this user&apos;s information
from the database. This cannot be undone.
5 changes: 5 additions & 0 deletions src/components/VolunteerGrid/VolunteerGrid.module.css
Original file line number Diff line number Diff line change
@@ -93,3 +93,8 @@
.atLimit {
visibility: hidden;
}

.operationSuccessModal {
width: 35%;
height: 23%;
}
10 changes: 10 additions & 0 deletions src/components/VolunteerGrid/VolunteerGrid.tsx
Original file line number Diff line number Diff line change
@@ -10,6 +10,8 @@ import TwoVolunteersIcon from "@src/app/icons/TwoVolunteersIcon";
import styles from "./VolunteerGrid.module.css";
import Popup from "./Popup/Popup";
import { Row } from "./Row/Row";
import Modal from "../Modal/Modal";
import OperationSuccessModal from "../OperationSuccessModal/OperationSuccessModal";

interface VolunteerGridProps {
data: IUser[];
@@ -64,6 +66,7 @@ export default function VolunteerGrid(params: VolunteerGridProps) {
const [deleteVolunteerEmail, setDeleteVolunteerEmail] = useState<
string | null
>(null);
const [showSuccessModal, setShowSuccessModal] = useState(false);

const handleConfirmDelete = async () => {
if (deleteVolunteerEmail !== null) {
@@ -79,6 +82,7 @@ export default function VolunteerGrid(params: VolunteerGridProps) {
params.refreshUsers();
}
setPopupOpen(false);
setShowSuccessModal(true);
};

const handleClosePopup = useCallback(() => {
@@ -122,6 +126,12 @@ export default function VolunteerGrid(params: VolunteerGridProps) {
pageCount={params.pageCount}
currentPage={params.currentPage}
/>
<Modal showModal={showSuccessModal} setShowModal={setShowSuccessModal}>
<OperationSuccessModal
className={styles.operationSuccessModal}
subtitle="Account Successfully Deleted"
/>
</Modal>
</div>
);
}