Skip to content

Commit

Permalink
merged with main
Browse files Browse the repository at this point in the history
  • Loading branch information
rosewang01 committed May 22, 2024
2 parents 20ec5a1 + 5232065 commit 3708374
Show file tree
Hide file tree
Showing 44 changed files with 971 additions and 515 deletions.
1 change: 0 additions & 1 deletion .vscode/settings.json

This file was deleted.

16 changes: 7 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
# Boilerplate

This is a simple boilerplate designed to serve as robust template for quickly starting development on a [Typescript](https://www.typescriptlang.org) based [MERN](https://www.mongodb.com/mern-stack) web application.
This is a web app built for Abuse and Sexual Assault Prevention, a student organization at Penn, as a resource tree for all sexual violence resources at Penn. This is a [Typescript](https://www.typescriptlang.org) based [MERN](https://www.mongodb.com/mern-stack) web application.

## Features

- Session based authentication with [Passport](https://www.passportjs.org)
- Emailing for account verification and resetting password with [SendGrid](https://sendgrid.com)
- Admin functionality for viewing/deleting/promoting other users
- Clean authentication pages built with [Material UI](https://mui.com)
- In memory database testing with [Jest](https://jestjs.io) and [Supertest](https://www.npmjs.com/package/supertest)
- [AirBnb Typescript styling](https://github.com/airbnb/javascript) with [Prettier](https://prettier.io) and [ESLint](https://eslint.org)
- [Husky](https://typicode.github.io/husky/#/) and [lint-staged](https://github.com/okonet/lint-staged) for checking linting on commits
- [GitHub Actions](https://docs.github.com/en/actions) for ensuring linting + tests pass on pushes
- Admin portal with ability to change resources, questions, and answers
- Rich text editor for answer and question changes
- Tree-based data structure in backend
- Private and secure user experience that does not track user data
- Back and Next buttons, as well as ability to see other resources if different answers were selected
- Dictionary and side help bar for unkown terms, filtered based on the words in the question/answer/resource

## Required tools

Expand Down
2 changes: 1 addition & 1 deletion client/src/AdminDashboard/AdminDashboardPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Typography, Grid } from '@mui/material';
import { Typography, Grid, AppBar } from '@mui/material';
import ScreenGrid from '../components/ScreenGrid';
// import UserTable from './QuestionTable';
import QuestionTable from './QuestionTable';
Expand Down
42 changes: 16 additions & 26 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import theme from './assets/theme';
import { store, persistor } from './util/redux/store';
import { persistor, store } from './util/redux/store';
import NotFoundPage from './NotFound/NotFoundPage';
import HomePage from './Home/HomePage';
import AboutThisProjectPage from './Home/AboutThisProjectPage';
Expand All @@ -23,6 +23,7 @@ import RegisterPage from './Authentication/RegisterPage';
import LoginPage from './Authentication/LoginPage';
import EmailResetPasswordPage from './Authentication/EmailResetPasswordPage';
import ResetPasswordPage from './Authentication/ResetPasswordPage';
import QuestionPage from './Question/QuestionPage';

function App() {
/* const testa = {
Expand Down Expand Up @@ -61,45 +62,34 @@ function App() {
path="/reset-password/:token"
element={<ResetPasswordPage />}
/>
{/* <Route element={<AdminRoutesWrapper />}> */}
<Route path="/users" element={<AdminDashboardPage />} />
{/* </Route> */}
<Route path="/editResource" element={<EditResource />} />
<Route path="/editQuestion" element={<EditQuestion />} />
<Route path="/home" element={<HomePage />} />
<Route path="/question" element={<QuestionPage />} />
</Route>
{/* Routes accessed only if user is authenticated */}
{/* <Route element={<AdminRoutesWrapper />}> */}
<Route element={<ProtectedRoutesWrapper />}>
{/* <Route path="/users" element={<AdminDashboardPage />} /> */}
<Route
path="/admin-dashboard"
element={<AdminDashboardPage />}
/>
<Route path="/users" element={<AdminDashboardPage />} />
<Route path="/editResource" element={<EditResource />} />
<Route path="/editQuestion" element={<EditQuestion />} />
</Route>

{/* Route which redirects to a different page depending on if the user is an authenticated or not by utilizing the DynamicRedirect component */}
<Route
path="/"
element={
<DynamicRedirect unAuthPath="/login" authPath="/home" />
<DynamicRedirect
unAuthPath="/home"
authPath="/admin-dashboard"
/>
}
/>
<Route path="/about" element={<AboutThisProjectPage />} />

{/* Route which is accessed if no other route is matched */}
<Route path="*" element={<NotFoundPage />} />

<Route path="/home" element={<HomePage />} />
<Route path="/about-us" element={<AboutThisProjectPage />} />

{/* <Route
path="/dropdown"
element={
<Box padding={2}>
<ResourceDropdown
title="Example Resource"
content="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sed gravida ex. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Mauris ut erat pulvinar, dignissim est et, eleifend quam. Aenean euismod ultricies accumsan. Sed vel nulla posuere, vestibulum sem eget, porttitor dolor. Integer et erat in mi tincidunt sollicitudin."
/>
</Box>
}
/> */}
{/* <Route path="popupwarning" element={<PopupWarning />} /> */}
{/* <Route path="/sidebar" element={<SidebarComponent />} /> */}
</Routes>
</CssBaseline>
</ThemeProvider>
Expand Down
6 changes: 3 additions & 3 deletions client/src/Authentication/LoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ function LoginPage() {
<FormCol>
<Grid item container justifyContent="center">
<Typography variant="h2" textAlign="center">
Log In
Administrator Log In
</Typography>
</Grid>
<Grid item width="1">
Expand Down Expand Up @@ -177,11 +177,11 @@ function LoginPage() {
Forgot password?
</Link>
</Grid>
<Grid item>
{/* <Grid item>
<Link component={RouterLink} to="/register">
Sign up
</Link>
</Grid>
</Grid> */}
</FormRow>
</FormCol>
</FormGrid>
Expand Down
14 changes: 11 additions & 3 deletions client/src/Home/AboutThisProjectPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ function AboutThisProjectPage() {
direction="row"
justifyContent="space-between"
alignItems="flex-start"
height="100%"
height="100vh"
fit-content="100%"
>
<Grid item width="100%">
<NavBar />
</Grid>

<Grid item width="100%" padding={2} justifyContent="flex-start">
<Grid item width="100%" justifyContent="flex-start">
<Typography variant="h3" fontWeight="bold" textAlign="center">
Guide to Interpersonal Resources at Penn
</Typography>
Expand Down Expand Up @@ -130,7 +130,15 @@ function AboutThisProjectPage() {
</Box>
</Grid>
</Grid>
<Grid item width="100%" alignItems="flex-end" padding={0} spacing={0}>
<Grid
item
width="100%"
alignItems="flex-end"
padding={0}
spacing={0}
position="fixed"
bottom={0}
>
<Footer />
</Grid>
</Grid>
Expand Down
3 changes: 2 additions & 1 deletion client/src/Home/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState } from 'react';
import Button from '@mui/material/Button';
import { Typography, Grid } from '@mui/material';
import Box from '@mui/system/Box';
import { useNavigate } from 'react-router-dom';
import ScreenGrid from '../components/ScreenGrid';
import Footer from '../components/Footer';
import NavBar from '../components/NavBar';
Expand Down Expand Up @@ -42,7 +43,7 @@ function HomePage() {
</Grid>

<Grid container direction="column" alignItems="center" padding={8}>
<Button variant="contained" size="large">
<Button variant="contained" size="large" href="/question">
Begin
</Button>
<Box padding={2}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* eslint-disable no-underscore-dangle */
import * as React from 'react';
import { Button } from '@mui/material';
import { IAnswer } from '../util/types/answer';
import HTMLMapper from '../../components/HTMLMapper';
import { IAnswer } from '../../util/types/answer';

interface AnswerButtonProps {
answer: IAnswer;
Expand Down Expand Up @@ -66,7 +67,7 @@ function AnswerButton(props: AnswerButtonProps) {
padding: '6px 22px',
}}
>
{answer.text}
<HTMLMapper text={answer.text} />
</Button>
);
}
Expand Down
52 changes: 52 additions & 0 deletions client/src/Question/Components/BackButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as React from 'react';
import { Button } from '@mui/material';

interface BackButtonProps {
onClick: any;
}

function BackButton(props: BackButtonProps) {
const { onClick } = props;

const [isHover, setIsHover] = React.useState(false);

const handleMouseEnter = () => {
setIsHover(true);
};

const handleMouseLeave = () => {
setIsHover(false);
};

return (
<Button
id="qback"
onClick={onClick}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
sx={{
width: '96px',
height: '39px',
textTransform: 'none',
backgroundColor: '#EEEEEE',
color: 'rgba(0, 0, 0, 0.87)',
padding: '6px 16px 6px 12px',
gap: '8px',
position: 'fixed',
left: '4.72%',
right: '88.61%',
top: '75.45%',
bottom: '10.74%',
fontFamily: 'Roboto',
fontStyle: 'normal',
fontWeight: '500',
fontSize: '14px',
lineHeight: '14px',
}}
>
BACK
</Button>
);
}

export default BackButton;
91 changes: 91 additions & 0 deletions client/src/Question/Components/ConfirmationModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React from 'react';
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';

interface IConfirmModal {
buttonText: string;
title: string;
body: string;
// eslint-disable-next-line @typescript-eslint/ban-types
onConfirm: Function;
}
/**
* A modal component that displays a confirmation message and a button to confirm the action or cancel the action.
* @param buttonText - the text to display on the confirmation button
* @param title - the title of the modal
* @param body - the body of the modal
* @param onConfirm - the function to call when the confirmation button is clicked
*/
export default function ConfirmModal({
buttonText,
title,
body,
onConfirm,
}: IConfirmModal) {
const [open, setOpen] = React.useState(false);

const handleClickOpen = () => {
setOpen(true);
};

const handleClose = () => {
setOpen(false);
};

const handleConfirm = () => {
onConfirm();
handleClose();
};

return (
<div>
<Button
onClick={handleClickOpen}
sx={{
width: '96px',
height: '39px',
textTransform: 'none',
backgroundColor: '#EEEEEE',
color: 'rgba(0, 0, 0, 0.87)',
padding: '6px 16px 6px 12px',
gap: '8px',
position: 'absolute',
left: '88.61%',
right: '4.72%',
top: '80.45%',
bottom: '15.74%',
fontFamily: 'Roboto',
fontStyle: 'normal',
fontWeight: '500',
fontSize: '14px',
lineHeight: '14px',
}}
>
{buttonText}
</Button>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{title}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
{body}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={handleConfirm} autoFocus>
Confirm
</Button>
</DialogActions>
</Dialog>
</div>
);
}
Loading

0 comments on commit 3708374

Please sign in to comment.