Skip to content

Commit

Permalink
feat: update webpage based on get request (#11)
Browse files Browse the repository at this point in the history
* feat: update webpage based on get request

* fix: fix regex

* build: use yarn only for packaging

* docs: update README

Using npm and yarn as a package manager at the same time is not recommended due to potential versioning conflicts. We will only support yarn officially.

* build: delete package-lock.json

* chore: update .gitignore

* docs: fix typo

* style: more specific names

---------

Co-authored-by: Cedric Sirianni <[email protected]>
  • Loading branch information
ni-jessica and csirianni authored Oct 9, 2023
1 parent 57480da commit bdc33d3
Show file tree
Hide file tree
Showing 7 changed files with 3,082 additions and 7,337 deletions.
4 changes: 4 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# npm
# ignore package lock because only supporting yarn
package-lock.json
19 changes: 14 additions & 5 deletions frontend/README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
made with next.js
# Frontend

## Install packages:
yarn add next@latest
yarn add @mui/material @emotion/react @emotion/styled @mui/icons-material
Made with [Next.js](https://nextjs.org/).

## Configuration

To run the frontend server, use your preferred terminal to `cd` into `/frontend` and then install the required packages by running

```bash
yarn install
```

Then, you should be able to start the server with the command

## Run frontend
```bash
yarn dev
```

Open [http://localhost:3000](http://localhost:3000) to view it in the browser. The page will reload if you make edits.

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Expand Down
106 changes: 99 additions & 7 deletions frontend/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
"use client";
import { useState, useEffect, FormEvent, MouseEvent } from "react";
import {
useState,
useEffect,
forwardRef,
FormEvent,
MouseEvent,
} from "react";
import Avatar from "@mui/material/Avatar";
import Button from "@mui/material/Button";
import CssBaseline from "@mui/material/CssBaseline";
Expand All @@ -14,6 +20,10 @@ import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
import Visibility from "@mui/icons-material/Visibility";
import VisibilityOff from "@mui/icons-material/VisibilityOff";
import { createTheme, ThemeProvider } from "@mui/material/styles";
import Snackbar, { SnackbarOrigin } from "@mui/material/Snackbar";
import MuiAlert, { AlertProps } from "@mui/material/Alert";
import CircularProgress from "@mui/material/CircularProgress";
import { useRouter } from "next/navigation";

// can change colors if we want
const theme = createTheme({
Expand All @@ -26,10 +36,15 @@ const theme = createTheme({
/* check that string contains number, upper case, lower case, special character,
and at least 10 characters */
const strongPasswordPattern = new RegExp(
"^(?=.*[a-z])(?=.*[A-Z])(?=.*d)(?=.*[^da-zA-Z]).{10,}$"
"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^da-zA-Z]).{10,}$"
);

interface SnackbarState extends SnackbarOrigin {
open: boolean;
}

export default function SignUp() {
const router = useRouter();
const [showPassword, setShowPassword] = useState(false);
const [isStrongPassword, setIsStrongPassword] = useState(false);
const [isValidForm, setIsValidForm] = useState(false);
Expand All @@ -38,10 +53,42 @@ export default function SignUp() {
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
const [confirmPassword, setConfirmPassword] = useState<string>("");
const [isLoading, setIsLoading] = useState(false);
const [showSnackbar, setShowSnackbar] = useState<SnackbarState>({
vertical: "top",
horizontal: "center",
open: false,
});
const { vertical, horizontal, open } = showSnackbar;

const handleClose = () => {
setShowSnackbar({ ...showSnackbar, open: false });
};

const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
const checkSecurity = async () => {
return {
status: "success", //"fail"
data: {
post: {
id: 1,
title: "mock data",
body: "nini is cool",
},
},
};
};

const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const data = new FormData(event.currentTarget);
setIsLoading(true);
const response = await checkSecurity();
setIsLoading(false);

if (response.status == "success") {
router.push(`/success`);
} else {
setShowSnackbar({ ...showSnackbar, open: true });
}
};

const handleClickShowPassword = () =>
Expand All @@ -63,6 +110,15 @@ export default function SignUp() {
);
}, [password, confirmPassword, isValidForm, isStrongPassword]);

const Alert = forwardRef<HTMLDivElement, AlertProps>(function Alert(
props,
ref
) {
return (
<MuiAlert elevation={6} ref={ref} variant="filled" {...props} />
);
});

return (
<ThemeProvider theme={theme}>
<Container component="main" maxWidth="xs">
Expand Down Expand Up @@ -109,6 +165,7 @@ export default function SignUp() {
fullWidth
id="firstName"
label="First Name"
aria-label="first name"
onChange={(event) => setFirst(event.target.value)}
autoFocus
/>
Expand All @@ -120,6 +177,7 @@ export default function SignUp() {
id="lastName"
label="Last Name"
name="lastName"
aria-label="last name"
autoComplete="family-name"
onChange={(event) => setLast(event.target.value)}
/>
Expand All @@ -131,6 +189,7 @@ export default function SignUp() {
id="email"
label="Email Address"
name="email"
aria-label="email address"
autoComplete="email"
onChange={(event) => setEmail(event.target.value)}
/>
Expand All @@ -143,6 +202,7 @@ export default function SignUp() {
label="Password"
id="password"
autoComplete="new-password"
aria-label="password"
type={showPassword ? "text" : "password"}
onChange={(event) =>
setPassword(event.target.value)
Expand Down Expand Up @@ -173,8 +233,11 @@ export default function SignUp() {
name="password"
label="Confirm your password"
id="confirm-password"
aria-label="confirm password"
type={showPassword ? "text" : "password"}
onChange={(event) => setConfirmPassword(event.target.value)}
onChange={(event) =>
setConfirmPassword(event.target.value)
}
InputProps={{
endAdornment: (
<InputAdornment position="end">
Expand Down Expand Up @@ -216,12 +279,41 @@ export default function SignUp() {
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
disabled={!isStrongPassword || !isValidForm}
disabled={
!isStrongPassword || !isValidForm || isLoading
}
>
Sign Up
{isLoading ? (
<span className="inline-flex">
<CircularProgress
size="24px"
color="inherit"
sx={{ marginRight: "12px" }}
/>
Loading...
</span>
) : (
"Sign Up"
)}
</Button>
</Box>
</Box>
<Snackbar
anchorOrigin={{ vertical, horizontal }}
open={open}
key={vertical + horizontal}
autoHideDuration={8000}
onClose={handleClose}
>
<Alert
severity="error"
onClose={handleClose}
sx={{ width: "100%" }}
>
Password was found in a previously breached dataset!
Please try a different password.
</Alert>
</Snackbar>
</Container>
</ThemeProvider>
);
Expand Down
47 changes: 47 additions & 0 deletions frontend/app/success/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"use client";
import Container from "@mui/material/Container";
import { createTheme, ThemeProvider } from "@mui/material/styles";
import Link from "next/link";

// can change colors if we want
const theme = createTheme({
palette: {
primary: { main: "#2196f3" },
secondary: { main: "#651fff" },
},
});

export default function Success() {
return (
<ThemeProvider theme={theme}>
<Container component="main" maxWidth="xs">
<div className="bg-white p-6 md:mx-auto absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
<div className="text-center">

<svg
viewBox="0 0 24 24"
className="text-green-600 w-16 h-16 mx-auto my-6"
>
<path
fill="currentColor"
d="M12,0A12,12,0,1,0,24,12,12.014,12.014,0,0,0,12,0Zm6.927,8.2-6.845,9.289a1.011,1.011,0,0,1-1.43.188L5.764,13.769a1,1,0,1,1,1.25-1.562l4.076,3.261,6.227-8.451A1,1,0,1,1,18.927,8.2Z"
></path>
</svg>

<h3 className="md:text-6xl text-base font-semibold text-center">
Account Created!
</h3>
<div className="py-10 text-center">
<Link
href="/"
className="px-12 bg-indigo-600 hover:bg-indigo-500 text-white font-semibold py-3"
>
GO BACK
</Link>
</div>
</div>
</div>
</Container>
</ThemeProvider>
);
}
Loading

0 comments on commit bdc33d3

Please sign in to comment.