Skip to content

Commit

Permalink
belinda-nextjs-03-220-reset-password-page (#223)
Browse files Browse the repository at this point in the history
* reset password page

* add image file declaration
  • Loading branch information
tinpham5614 authored Feb 23, 2024
1 parent 4ce799e commit 15bb788
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 0 deletions.
187 changes: 187 additions & 0 deletions app/auth/reset-password-page/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
"use client";
import Image from "next/image";
import logo from "@/app/logo.png";
import { ChangeEventHandler, FormEventHandler, useState } from "react";
import Visibility from "@mui/icons-material/Visibility";
import VisibilityOff from "@mui/icons-material/VisibilityOff";
import {
Box,
Button,
Container,
IconButton,
InputAdornment,
Paper,
TextField,
Typography,
} from "@mui/material";

const ResetPasswordPage = () => {
const [password, setPassword] = useState({
newPassword: "",
confirmPassword: "",
});
// destructure password from password state
const { newPassword, confirmPassword } = password;
const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);

// handle toggle password visibility
const togglePasswordVisibility = () => {
setShowPassword(!showPassword);
};

// handle toggle confirm password visibility
const toggleConfirmPasswordVisibility = () => {
setShowConfirmPassword(!showConfirmPassword);
};

// handle change event
const handleChange: ChangeEventHandler<HTMLInputElement> = ({ target }) => {
const { name, value } = target;
setPassword({ ...password, [name]: value });
};

// handle submit event
const handleSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
// prevent the default behavior
e.preventDefault();

// Check if password and confirmPassword match
if (newPassword !== confirmPassword) {
console.error("Passwords do not match");
return;
}

// send request to backend api then log the response
// TODO: send request to backend api then log the response
const res = await fetch("localhost:3000/api/auth/reset-password", {
method: "POST",
body: JSON.stringify(password),
headers: {
"Content-type": "application/json",
},
});
try {
const data = await res.json();
console.log(data);
alert("Password reset successful");
} catch (error) {
console.error("Error parson JSON response:", error);
}
};

return (
<Container
maxWidth="lg"
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
bgcolor: "#12202d",
}}
>
<Box
width={800}
display="flex"
alignItems="center"
flexDirection="column"
bgcolor="#293745"
gap={2}
p={3}
>
<Paper elevation={6} sx={{ width: "100%", maxWidth: 400, padding: 3 }}>
<Container
disableGutters
fixed
maxWidth="xs"
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<Image
src={logo}
alt="logo"
style={{ width: 50, height: 50, marginBottom: 10 }}
/>
</Container>
<Typography
component="h1"
variant="h5"
textAlign="center"
sx={{ mb: 2 }}
>
Reset Password
</Typography>
<Box
component="form"
onSubmit={handleSubmit}
noValidate
sx={{ mt: 1 }}
>
<TextField
sx={{ mb: 2 }}
variant="outlined"
margin="normal"
required
fullWidth
id="newPassword"
label="New Password"
name="newPassword"
type={showPassword ? "text" : "password"}
value={newPassword}
onChange={handleChange}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={togglePasswordVisibility}
>
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
),
}}
/>
<TextField
sx={{ mb: 2 }}
variant="outlined"
margin="normal"
required
fullWidth
id="confirmPassword"
label="Confirm Password"
name="confirmPassword"
type={showConfirmPassword ? "text" : "password"}
value={confirmPassword}
onChange={handleChange}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
aria-label="toggle confirm password visibility"
onClick={toggleConfirmPasswordVisibility}
>
{showConfirmPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
),
}}
/>
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
>
Reset Password
</Button>
</Box>
</Paper>
</Box>
</Container>
);
};
export default ResetPasswordPage;
4 changes: 4 additions & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import './globals.css';
import { Inter } from 'next/font/google';
import Navbar from '@/components/Navbar';
import SessionProvider from '@/components/SessionProvider';
import { ThemeProvider } from '@mui/material/styles';
import theme from './theme/theme';

const inter = Inter({ subsets: ['latin'] })

Expand All @@ -18,12 +20,14 @@ export default function RootLayout({
children: React.ReactNode
}) {
return (
<ThemeProvider theme={theme}>
<html lang="en">
<body className={inter.className}>
<SessionProvider>
<Navbar/>{children}
</SessionProvider>
</body>
</html>
</ThemeProvider>
)
};
22 changes: 22 additions & 0 deletions app/theme/theme.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use client';
import { createTheme } from '@mui/material/styles';

const theme = createTheme({
palette: {
mode: 'light',
primary: {
light: '#3f50b5',
main: '#1565c0',
dark: '#002884',
contrastText: '#fff',
},
secondary: {
light: '#6fbf73',
main: '#4caf50',
dark: '#357a38',
contrastText: '#fff',
},
},
});

export default theme;
4 changes: 4 additions & 0 deletions src/react-app-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare module "*.png";
declare module "*.svg";
declare module "*.jpeg";
declare module "*.jpg";

0 comments on commit 15bb788

Please sign in to comment.