Skip to content

Commit

Permalink
Update: Added nodemon and SwaggerJS
Browse files Browse the repository at this point in the history
  • Loading branch information
hoangsonww committed Nov 1, 2024
1 parent 4071468 commit 1d438b2
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 13 deletions.
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<link rel="apple-touch-icon" href="%PUBLIC_URL%/android-chrome-192x192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap" rel="stylesheet">
<title>Fusion Electronics</title>
<title>Fusion Electronics - MERN E-commerce Website</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
3 changes: 2 additions & 1 deletion src/pages/ForgotPassword.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function ForgotPassword() {
</Typography>

{error && (
<Typography variant="body2" color="error" sx={{ mb: 2 }}>
<Typography variant="body2" color="error" sx={{ mb: 2, textAlign: "center" }}>
{error}
</Typography>
)}
Expand All @@ -46,6 +46,7 @@ function ForgotPassword() {
fullWidth
margin="normal"
value={email}
type={'email'}
onChange={(e) => setEmail(e.target.value)}
required
/>
Expand Down
41 changes: 37 additions & 4 deletions src/pages/Login.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import React, { useState } from 'react';
import { Box, Container, TextField, Typography, Button, CircularProgress, Paper } from '@mui/material';
import {
Box,
Container,
TextField,
Typography,
Button,
CircularProgress,
Paper,
IconButton,
InputAdornment,
} from '@mui/material';
import { Visibility, VisibilityOff } from '@mui/icons-material';
import axios from 'axios';

function Login() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [showPassword, setShowPassword] = useState(false); // State to toggle password visibility
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);

Expand All @@ -14,7 +26,10 @@ function Login() {
setError(null);

try {
const response = await axios.post('https://mern-stack-ecommerce-app-h5wb.onrender.com/api/auth/login', { email, password });
const response = await axios.post(
'https://mern-stack-ecommerce-app-h5wb.onrender.com/api/auth/login',
{ email, password }
);
const token = response.data.token;
// Store token in localStorage or sessionStorage
localStorage.setItem('MERNEcommerceToken', token);
Expand All @@ -27,6 +42,11 @@ function Login() {
}
};

// Toggle password visibility
const handleTogglePasswordVisibility = () => {
setShowPassword((prev) => !prev);
};

return (
<Container maxWidth="sm" sx={{ mt: 4 }}>
<Paper elevation={3} sx={{ p: 4, borderRadius: 2 }}>
Expand All @@ -35,7 +55,7 @@ function Login() {
</Typography>

{error && (
<Typography variant="body2" color="error" sx={{ mb: 2 }}>
<Typography variant="body2" color="error" sx={{ mb: 2, textAlign: "center" }}>
{error}
</Typography>
)}
Expand All @@ -52,13 +72,26 @@ function Login() {
/>
<TextField
label="Password"
type="password"
type={showPassword ? 'text' : 'password'}
variant="outlined"
fullWidth
margin="normal"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleTogglePasswordVisibility}
edge="end"
>
{showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
}}
/>

<Box sx={{ display: 'flex', justifyContent: 'center', mt: 3 }}>
Expand Down
77 changes: 73 additions & 4 deletions src/pages/Register.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
import React, { useState } from 'react';
import { Box, Container, TextField, Typography, Button, CircularProgress, Paper } from '@mui/material';
import {
Box,
Container,
TextField,
Typography,
Button,
CircularProgress,
Paper,
IconButton,
InputAdornment,
} from '@mui/material';
import { Visibility, VisibilityOff } from '@mui/icons-material';
import axios from 'axios'; // For making API calls

function Register() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState(''); // New state for confirming password
const [showPassword, setShowPassword] = useState(false); // State for password visibility toggle
const [showConfirmPassword, setShowConfirmPassword] = useState(false); // State for confirm password visibility toggle
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);

Expand All @@ -14,8 +28,17 @@ function Register() {
setLoading(true);
setError(null);

if (password !== confirmPassword) {
setError("Passwords do not match");
setLoading(false);
return;
}

try {
const response = await axios.post('https://mern-stack-ecommerce-app-h5wb.onrender.com/api/auth/register', { name, email, password });
const response = await axios.post(
'https://mern-stack-ecommerce-app-h5wb.onrender.com/api/auth/register',
{ name, email, password }
);
const token = response.data.token;
// Store token in localStorage or sessionStorage
localStorage.setItem('token', token);
Expand All @@ -28,6 +51,16 @@ function Register() {
}
};

// Toggle password visibility
const handleTogglePasswordVisibility = () => {
setShowPassword((prev) => !prev);
};

// Toggle confirm password visibility
const handleToggleConfirmPasswordVisibility = () => {
setShowConfirmPassword((prev) => !prev);
};

return (
<Container maxWidth="sm" sx={{ mt: 4 }}>
<Paper elevation={3} sx={{ p: 4, borderRadius: 2 }}>
Expand All @@ -36,7 +69,7 @@ function Register() {
</Typography>

{error && (
<Typography variant="body2" color="error" sx={{ mb: 2 }}>
<Typography variant="body2" color="error" sx={{ mb: 2, textAlign: "center" }}>
{error}
</Typography>
)}
Expand All @@ -62,13 +95,49 @@ function Register() {
/>
<TextField
label="Password"
type="password"
type={showPassword ? 'text' : 'password'}
variant="outlined"
fullWidth
margin="normal"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleTogglePasswordVisibility}
edge="end"
>
{showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
}}
/>
<TextField
label="Confirm Password"
type={showConfirmPassword ? 'text' : 'password'}
variant="outlined"
fullWidth
margin="normal"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
required
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
aria-label="toggle confirm password visibility"
onClick={handleToggleConfirmPasswordVisibility}
edge="end"
>
{showConfirmPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
}}
/>

<Box sx={{ display: 'flex', justifyContent: 'center', mt: 3 }}>
Expand Down
53 changes: 50 additions & 3 deletions src/pages/ResetPassword.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import React, { useState } from 'react';
import { Box, Container, TextField, Typography, Button, CircularProgress, Paper } from '@mui/material';
import {
Box,
Container,
TextField,
Typography,
Button,
CircularProgress,
Paper,
IconButton,
InputAdornment,
} from '@mui/material';
import { Visibility, VisibilityOff } from '@mui/icons-material';
import axios from 'axios';

function ResetPassword() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(null);
const [error, setError] = useState(null);
Expand Down Expand Up @@ -33,6 +46,14 @@ function ResetPassword() {
}
};

const handleTogglePasswordVisibility = () => {
setShowPassword((prev) => !prev);
};

const handleToggleConfirmPasswordVisibility = () => {
setShowConfirmPassword((prev) => !prev);
};

return (
<Container maxWidth="sm" sx={{ mt: 4 }}>
<Paper elevation={3} sx={{ p: 4, borderRadius: 2 }}>
Expand Down Expand Up @@ -64,23 +85,49 @@ function ResetPassword() {
/>
<TextField
label="New Password"
type="password"
type={showPassword ? 'text' : 'password'}
variant="outlined"
fullWidth
margin="normal"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleTogglePasswordVisibility}
edge="end"
>
{showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
}}
/>
<TextField
label="Confirm New Password"
type="password"
type={showConfirmPassword ? 'text' : 'password'}
variant="outlined"
fullWidth
margin="normal"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
required
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
aria-label="toggle confirm password visibility"
onClick={handleToggleConfirmPasswordVisibility}
edge="end"
>
{showConfirmPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
}}
/>

<Box sx={{ display: 'flex', justifyContent: 'center', mt: 3 }}>
Expand Down

0 comments on commit 1d438b2

Please sign in to comment.