Skip to content

Commit

Permalink
Task11/user boilerplate (#12)
Browse files Browse the repository at this point in the history
* update user schema to contain city, state, and isAcceptingRequests

* update chapter and user routes

* update user schema with isActive field

* fix register function for admin to add new chapter

* fixing register function
  • Loading branch information
kygchng authored Dec 1, 2024
1 parent 91ef52e commit a1d9ed1
Show file tree
Hide file tree
Showing 23 changed files with 255 additions and 652 deletions.
2 changes: 1 addition & 1 deletion client/src/AdminDashboard/TempAdminDashboardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,4 +243,4 @@ function TempAdminDashboardPage() {
);
}

export default TempAdminDashboardPage;
export default TempAdminDashboardPage;
15 changes: 8 additions & 7 deletions client/src/AdminDashboard/UserTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
import React, { useEffect, useState } from 'react';
import CircularProgress from '@mui/material/CircularProgress';
import { LocationCity } from '@material-ui/icons';
import { PaginationTable, TColumn } from '../components/PaginationTable.tsx';
import DeleteUserButton from './DeleteUserButton.tsx';
import PromoteUserButton from './PromoteUserButton.tsx';
Expand All @@ -14,8 +15,8 @@ import IUser from '../util/types/user.ts';

interface AdminDashboardRow {
key: string;
first: string;
last: string;
city: string;
state: string;
email: string;
promote: React.ReactElement;
remove: React.ReactElement;
Expand All @@ -28,8 +29,8 @@ interface AdminDashboardRow {
function UserTable() {
// define columns for the table
const columns: TColumn[] = [
{ id: 'first', label: 'First Name' },
{ id: 'last', label: 'Last Name' },
{ id: 'city', label: 'City' },
{ id: 'state', label: 'State' },
{ id: 'email', label: 'Email' },
{ id: 'promote', label: 'Promote to Admin' },
{ id: 'remove', label: 'Remove User' },
Expand All @@ -41,11 +42,11 @@ function UserTable() {
promote: React.ReactElement,
remove: React.ReactElement,
): AdminDashboardRow {
const { _id, firstName, lastName, email } = user;
const { _id, city, state, email } = user;
return {
key: _id,
first: firstName,
last: lastName,
city,
state,
email,
promote,
remove,
Expand Down
2 changes: 1 addition & 1 deletion client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ function App() {
<Route element={<UnauthenticatedRoutesWrapper />}>
<Route path="/login" element={<LoginPage />} />
<Route path="/admin" element={<TempAdminDashboardPage />} />
<Route path="/register" element={<RegisterPage />} />
<Route
path="/verify-account/:token"
element={<VerifyAccountPage />}
Expand All @@ -58,6 +57,7 @@ function App() {
/>
{/* Routes accessed only if user is authenticated */}
<Route element={<ProtectedRoutesWrapper />}>
<Route path="/register" element={<RegisterPage />} />
<Route path="/home" element={<HomePage />} />
</Route>
<Route element={<AdminRoutesWrapper />}>
Expand Down
18 changes: 4 additions & 14 deletions client/src/Authentication/LoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,11 @@ function LoginPage() {
const dispatch = useAppDispatch();
function dispatchUser(
userEmail: string,
firstName: string,
lastName: string,
city: string,
state: string,
admin: boolean,
) {
dispatch(loginRedux({ email: userEmail, firstName, lastName, admin }));
dispatch(loginRedux({ email: userEmail, city, state, admin }));
}

const clearErrorMessages = () => {
Expand Down Expand Up @@ -197,12 +197,7 @@ function LoginPage() {
loginUser(values.email, values.password)
.then((user) => {
console.log('navigating to home!');
dispatchUser(
user.email!,
user.firstName!,
user.lastName!,
user.admin!,
);
dispatchUser(user.email!, user.city!, user.state!, user.admin!);
navigate('/home');
})
.catch((e) => {
Expand Down Expand Up @@ -270,11 +265,6 @@ function LoginPage() {
Forgot password?
</Link>
</Grid>
<Grid item>
<Link component={RouterLink} to="/register" color="secondary">
Sign up
</Link>
</Grid>
</FormRow>
<SupportingElements>
<SupportingIcon
Expand Down
46 changes: 23 additions & 23 deletions client/src/Authentication/RegisterPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,23 @@ function RegisterPage() {

// Default values for state
const defaultValues = {
firstName: '',
lastName: '',
city: '',
state: '',
email: '',
password: '',
confirmPassword: '',
};
const defaultShowErrors = {
firstName: false,
lastName: false,
city: false,
state: false,
email: false,
password: false,
confirmPassword: false,
alert: false,
};
const defaultErrorMessages = {
firstName: '',
lastName: '',
city: '',
state: '',
email: '',
password: '',
confirmPassword: '',
Expand Down Expand Up @@ -101,14 +101,14 @@ function RegisterPage() {
}
}

if (!values.firstName.match(nameRegex)) {
setErrorMessage('firstName', InputErrorMessage.INVALID_NAME);
setShowError('firstName', true);
if (!values.city.match(nameRegex)) {
setErrorMessage('city', InputErrorMessage.INVALID_NAME);
setShowError('city', true);
isValid = false;
}
if (!values.lastName.match(nameRegex)) {
setErrorMessage('lastName', InputErrorMessage.INVALID_NAME);
setShowError('lastName', true);
if (!values.state.match(nameRegex)) {
setErrorMessage('state', InputErrorMessage.INVALID_NAME);
setShowError('state', true);
isValid = false;
}
if (!values.email.match(emailRegex)) {
Expand All @@ -132,7 +132,7 @@ function RegisterPage() {

async function handleSubmit() {
if (validateInputs()) {
register(values.firstName, values.lastName, values.email, values.password)
register(values.city, values.state, values.email, values.password)
.then(() => {
setShowError('alert', true);
setAlertTitle('');
Expand All @@ -158,27 +158,27 @@ function RegisterPage() {
<Grid item width=".5">
<TextField
fullWidth
error={showError.firstName}
helperText={errorMessage.firstName}
error={showError.city}
helperText={errorMessage.city}
size="small"
type="text"
required
label="First Name"
value={values.firstName}
onChange={(e) => setValue('firstName', e.target.value)}
label="City"
value={values.city}
onChange={(e) => setValue('city', e.target.value)}
/>
</Grid>
<Grid item width=".5">
<TextField
fullWidth
error={showError.lastName}
helperText={errorMessage.lastName}
error={showError.state}
helperText={errorMessage.state}
size="small"
type="text"
required
label="Last Name"
value={values.lastName}
onChange={(e) => setValue('lastName', e.target.value)}
label="State"
value={values.state}
onChange={(e) => setValue('state', e.target.value)}
/>
</Grid>
</FormRow>
Expand Down
26 changes: 13 additions & 13 deletions client/src/Authentication/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,22 @@ async function verifyAccount(verificationToken: string) {

/**
* Sends a request to the server to register a user for an account
* @param firstName
* @param lastName
* @param city
* @param state
* @param email
* @param password
* @throws An {@link Error} with a `messsage` field describing the issue in verifying
*/
async function register(
firstName: string,
lastName: string,
city: string,
state: string,
email: string,
password: string,
) {
const lowercaseEmail = email.toLowerCase();
const res = await postData('auth/register', {
firstName,
lastName,
const res = await postData('admin/register', {
city,
state,
email: lowercaseEmail,
password,
});
Expand Down Expand Up @@ -94,25 +94,25 @@ async function resetPassword(password: string, token: string) {

/**
* Sends a request to the server to register a new user via an invite
* @param firstName
* @param lastName
* @param city
* @param state
* @param email
* @param password
* @param inviteToken
* @throws An {@link Error} with a `messsage` field describing the issue in
* resetting the password
*/
async function registerInvite(
firstName: string,
lastName: string,
city: string,
state: string,
email: string,
password: string,
inviteToken: string,
) {
const lowercaseEmail = email.toLowerCase();
const res = await postData('auth/register-invite', {
firstName,
lastName,
city,
state,
email: lowercaseEmail,
password,
inviteToken,
Expand Down
28 changes: 19 additions & 9 deletions client/src/Home/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React, { useState } from 'react';
import Button from '@mui/material/Button';
import { NavigateFunction, useNavigate } from 'react-router-dom';
import { Typography, Grid } from '@mui/material';
import {
NavigateFunction,
useNavigate,
Link as RouterLink,
} from 'react-router-dom';
import { Link, Typography, Grid } from '@mui/material';
import { useAppDispatch, useAppSelector } from '../util/redux/hooks.ts';
import {
logout as logoutAction,
Expand Down Expand Up @@ -37,12 +41,17 @@ function PromoteButton({
Promote self to admin
</PrimaryButton>
) : (
<PrimaryButton
variant="contained"
onClick={() => navigator('/users', { replace: true })}
>
View all users
</PrimaryButton>
<div>
<PrimaryButton
variant="contained"
onClick={() => navigator('/users', { replace: true })}
>
View all users
</PrimaryButton>
<Link component={RouterLink} to="/register" color="secondary">
Register a New Chapter
</Link>
</div>
);
}
/**
Expand All @@ -69,7 +78,8 @@ function HomePage() {
}
};

const message = `Welcome to the Boilerplate, ${user.firstName} ${user.lastName}!`;
const message = `Welcome to the Boilerplate, ${user.city}, ${user.state}!`;
console.log(user);
return (
<ScreenGrid>
<Typography variant="h2">{message}</Typography>
Expand Down
20 changes: 10 additions & 10 deletions client/src/util/redux/userSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ import type { RootState } from './store.ts';

export interface UserState {
email: string | null;
firstName: string | null;
lastName: string | null;
city: string | null;
state: string | null;
admin: boolean | null;
}

interface Payload {
email: string;
firstName: string;
lastName: string;
city: string;
state: string;
admin: boolean;
}

const initialState = {
email: null,
firstName: null,
lastName: null,
city: null,
state: null,
} as UserState;

/**
Expand All @@ -31,17 +31,17 @@ const userSlice = createSlice({
reducers: {
login: (state, action: PayloadAction<Payload>) => {
state.email = action.payload.email;
state.firstName = action.payload.firstName;
state.lastName = action.payload.lastName;
state.city = action.payload.city;
state.state = action.payload.state;
state.admin = action.payload.admin;
},
toggleAdmin: (state) => {
state.admin = !state.admin;
},
logout: (state) => {
state.email = null;
state.firstName = null;
state.lastName = null;
state.city = null;
state.state = null;
state.admin = null;
},
},
Expand Down
6 changes: 4 additions & 2 deletions server/src/config/configPassport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import {

interface IUserWithPassword {
_id: string;
firstName: string;
lastName: string;
city: string;
state: string;
isAcceptingRequests: boolean;
isActive: boolean;
email: string;
password?: string;
verified: boolean;
Expand Down
Loading

0 comments on commit a1d9ed1

Please sign in to comment.