Skip to content

Commit 3708374

Browse files
committed
merged with main
2 parents 20ec5a1 + 5232065 commit 3708374

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+971
-515
lines changed

.vscode/settings.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

README.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
# Boilerplate
22

3-
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.
3+
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.
44

55
## Features
66

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

1614
## Required tools
1715

client/src/AdminDashboard/AdminDashboardPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { Typography, Grid } from '@mui/material';
2+
import { Typography, Grid, AppBar } from '@mui/material';
33
import ScreenGrid from '../components/ScreenGrid';
44
// import UserTable from './QuestionTable';
55
import QuestionTable from './QuestionTable';

client/src/App.tsx

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { BrowserRouter, Routes, Route } from 'react-router-dom';
55
import { Provider } from 'react-redux';
66
import { PersistGate } from 'redux-persist/integration/react';
77
import theme from './assets/theme';
8-
import { store, persistor } from './util/redux/store';
8+
import { persistor, store } from './util/redux/store';
99
import NotFoundPage from './NotFound/NotFoundPage';
1010
import HomePage from './Home/HomePage';
1111
import AboutThisProjectPage from './Home/AboutThisProjectPage';
@@ -23,6 +23,7 @@ import RegisterPage from './Authentication/RegisterPage';
2323
import LoginPage from './Authentication/LoginPage';
2424
import EmailResetPasswordPage from './Authentication/EmailResetPasswordPage';
2525
import ResetPasswordPage from './Authentication/ResetPasswordPage';
26+
import QuestionPage from './Question/QuestionPage';
2627

2728
function App() {
2829
/* const testa = {
@@ -61,45 +62,34 @@ function App() {
6162
path="/reset-password/:token"
6263
element={<ResetPasswordPage />}
6364
/>
64-
{/* <Route element={<AdminRoutesWrapper />}> */}
65-
<Route path="/users" element={<AdminDashboardPage />} />
66-
{/* </Route> */}
67-
<Route path="/editResource" element={<EditResource />} />
68-
<Route path="/editQuestion" element={<EditQuestion />} />
65+
<Route path="/home" element={<HomePage />} />
66+
<Route path="/question" element={<QuestionPage />} />
6967
</Route>
7068
{/* Routes accessed only if user is authenticated */}
71-
{/* <Route element={<AdminRoutesWrapper />}> */}
7269
<Route element={<ProtectedRoutesWrapper />}>
73-
{/* <Route path="/users" element={<AdminDashboardPage />} /> */}
70+
<Route
71+
path="/admin-dashboard"
72+
element={<AdminDashboardPage />}
73+
/>
74+
<Route path="/users" element={<AdminDashboardPage />} />
75+
<Route path="/editResource" element={<EditResource />} />
76+
<Route path="/editQuestion" element={<EditQuestion />} />
7477
</Route>
7578

7679
{/* Route which redirects to a different page depending on if the user is an authenticated or not by utilizing the DynamicRedirect component */}
7780
<Route
7881
path="/"
7982
element={
80-
<DynamicRedirect unAuthPath="/login" authPath="/home" />
83+
<DynamicRedirect
84+
unAuthPath="/home"
85+
authPath="/admin-dashboard"
86+
/>
8187
}
8288
/>
89+
<Route path="/about" element={<AboutThisProjectPage />} />
8390

8491
{/* Route which is accessed if no other route is matched */}
8592
<Route path="*" element={<NotFoundPage />} />
86-
87-
<Route path="/home" element={<HomePage />} />
88-
<Route path="/about-us" element={<AboutThisProjectPage />} />
89-
90-
{/* <Route
91-
path="/dropdown"
92-
element={
93-
<Box padding={2}>
94-
<ResourceDropdown
95-
title="Example Resource"
96-
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."
97-
/>
98-
</Box>
99-
}
100-
/> */}
101-
{/* <Route path="popupwarning" element={<PopupWarning />} /> */}
102-
{/* <Route path="/sidebar" element={<SidebarComponent />} /> */}
10393
</Routes>
10494
</CssBaseline>
10595
</ThemeProvider>

client/src/Authentication/LoginPage.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ function LoginPage() {
134134
<FormCol>
135135
<Grid item container justifyContent="center">
136136
<Typography variant="h2" textAlign="center">
137-
Log In
137+
Administrator Log In
138138
</Typography>
139139
</Grid>
140140
<Grid item width="1">
@@ -177,11 +177,11 @@ function LoginPage() {
177177
Forgot password?
178178
</Link>
179179
</Grid>
180-
<Grid item>
180+
{/* <Grid item>
181181
<Link component={RouterLink} to="/register">
182182
Sign up
183183
</Link>
184-
</Grid>
184+
</Grid> */}
185185
</FormRow>
186186
</FormCol>
187187
</FormGrid>

client/src/Home/AboutThisProjectPage.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ function AboutThisProjectPage() {
2121
direction="row"
2222
justifyContent="space-between"
2323
alignItems="flex-start"
24-
height="100%"
24+
height="100vh"
2525
fit-content="100%"
2626
>
2727
<Grid item width="100%">
2828
<NavBar />
2929
</Grid>
3030

31-
<Grid item width="100%" padding={2} justifyContent="flex-start">
31+
<Grid item width="100%" justifyContent="flex-start">
3232
<Typography variant="h3" fontWeight="bold" textAlign="center">
3333
Guide to Interpersonal Resources at Penn
3434
</Typography>
@@ -130,7 +130,15 @@ function AboutThisProjectPage() {
130130
</Box>
131131
</Grid>
132132
</Grid>
133-
<Grid item width="100%" alignItems="flex-end" padding={0} spacing={0}>
133+
<Grid
134+
item
135+
width="100%"
136+
alignItems="flex-end"
137+
padding={0}
138+
spacing={0}
139+
position="fixed"
140+
bottom={0}
141+
>
134142
<Footer />
135143
</Grid>
136144
</Grid>

client/src/Home/HomePage.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { useState } from 'react';
22
import Button from '@mui/material/Button';
33
import { Typography, Grid } from '@mui/material';
44
import Box from '@mui/system/Box';
5+
import { useNavigate } from 'react-router-dom';
56
import ScreenGrid from '../components/ScreenGrid';
67
import Footer from '../components/Footer';
78
import NavBar from '../components/NavBar';
@@ -42,7 +43,7 @@ function HomePage() {
4243
</Grid>
4344

4445
<Grid container direction="column" alignItems="center" padding={8}>
45-
<Button variant="contained" size="large">
46+
<Button variant="contained" size="large" href="/question">
4647
Begin
4748
</Button>
4849
<Box padding={2}>

client/src/Question/AnswerButton.tsx renamed to client/src/Question/Components/AnswerButton.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/* eslint-disable no-underscore-dangle */
22
import * as React from 'react';
33
import { Button } from '@mui/material';
4-
import { IAnswer } from '../util/types/answer';
4+
import HTMLMapper from '../../components/HTMLMapper';
5+
import { IAnswer } from '../../util/types/answer';
56

67
interface AnswerButtonProps {
78
answer: IAnswer;
@@ -66,7 +67,7 @@ function AnswerButton(props: AnswerButtonProps) {
6667
padding: '6px 22px',
6768
}}
6869
>
69-
{answer.text}
70+
<HTMLMapper text={answer.text} />
7071
</Button>
7172
);
7273
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import * as React from 'react';
2+
import { Button } from '@mui/material';
3+
4+
interface BackButtonProps {
5+
onClick: any;
6+
}
7+
8+
function BackButton(props: BackButtonProps) {
9+
const { onClick } = props;
10+
11+
const [isHover, setIsHover] = React.useState(false);
12+
13+
const handleMouseEnter = () => {
14+
setIsHover(true);
15+
};
16+
17+
const handleMouseLeave = () => {
18+
setIsHover(false);
19+
};
20+
21+
return (
22+
<Button
23+
id="qback"
24+
onClick={onClick}
25+
onMouseEnter={handleMouseEnter}
26+
onMouseLeave={handleMouseLeave}
27+
sx={{
28+
width: '96px',
29+
height: '39px',
30+
textTransform: 'none',
31+
backgroundColor: '#EEEEEE',
32+
color: 'rgba(0, 0, 0, 0.87)',
33+
padding: '6px 16px 6px 12px',
34+
gap: '8px',
35+
position: 'fixed',
36+
left: '4.72%',
37+
right: '88.61%',
38+
top: '75.45%',
39+
bottom: '10.74%',
40+
fontFamily: 'Roboto',
41+
fontStyle: 'normal',
42+
fontWeight: '500',
43+
fontSize: '14px',
44+
lineHeight: '14px',
45+
}}
46+
>
47+
BACK
48+
</Button>
49+
);
50+
}
51+
52+
export default BackButton;
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import React from 'react';
2+
import Button from '@mui/material/Button';
3+
import Dialog from '@mui/material/Dialog';
4+
import DialogActions from '@mui/material/DialogActions';
5+
import DialogContent from '@mui/material/DialogContent';
6+
import DialogContentText from '@mui/material/DialogContentText';
7+
import DialogTitle from '@mui/material/DialogTitle';
8+
9+
interface IConfirmModal {
10+
buttonText: string;
11+
title: string;
12+
body: string;
13+
// eslint-disable-next-line @typescript-eslint/ban-types
14+
onConfirm: Function;
15+
}
16+
/**
17+
* A modal component that displays a confirmation message and a button to confirm the action or cancel the action.
18+
* @param buttonText - the text to display on the confirmation button
19+
* @param title - the title of the modal
20+
* @param body - the body of the modal
21+
* @param onConfirm - the function to call when the confirmation button is clicked
22+
*/
23+
export default function ConfirmModal({
24+
buttonText,
25+
title,
26+
body,
27+
onConfirm,
28+
}: IConfirmModal) {
29+
const [open, setOpen] = React.useState(false);
30+
31+
const handleClickOpen = () => {
32+
setOpen(true);
33+
};
34+
35+
const handleClose = () => {
36+
setOpen(false);
37+
};
38+
39+
const handleConfirm = () => {
40+
onConfirm();
41+
handleClose();
42+
};
43+
44+
return (
45+
<div>
46+
<Button
47+
onClick={handleClickOpen}
48+
sx={{
49+
width: '96px',
50+
height: '39px',
51+
textTransform: 'none',
52+
backgroundColor: '#EEEEEE',
53+
color: 'rgba(0, 0, 0, 0.87)',
54+
padding: '6px 16px 6px 12px',
55+
gap: '8px',
56+
position: 'absolute',
57+
left: '88.61%',
58+
right: '4.72%',
59+
top: '80.45%',
60+
bottom: '15.74%',
61+
fontFamily: 'Roboto',
62+
fontStyle: 'normal',
63+
fontWeight: '500',
64+
fontSize: '14px',
65+
lineHeight: '14px',
66+
}}
67+
>
68+
{buttonText}
69+
</Button>
70+
<Dialog
71+
open={open}
72+
onClose={handleClose}
73+
aria-labelledby="alert-dialog-title"
74+
aria-describedby="alert-dialog-description"
75+
>
76+
<DialogTitle id="alert-dialog-title">{title}</DialogTitle>
77+
<DialogContent>
78+
<DialogContentText id="alert-dialog-description">
79+
{body}
80+
</DialogContentText>
81+
</DialogContent>
82+
<DialogActions>
83+
<Button onClick={handleClose}>Cancel</Button>
84+
<Button onClick={handleConfirm} autoFocus>
85+
Confirm
86+
</Button>
87+
</DialogActions>
88+
</Dialog>
89+
</div>
90+
);
91+
}

0 commit comments

Comments
 (0)