Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

- Remove the login landing page #1345

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions Client/src/Pages/Auth/Login/Components/EmailStep.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { useRef, useEffect } from "react";
import { Box, Button, Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import TextInput from "../../../../Components/Inputs/TextInput";
import PropTypes from "prop-types";

/**
* Renders the email step of the login process which includes an email field.
*
* @param {Object} props
* @param {Object} props.form - Form state object.
* @param {Object} props.errors - Object containing form validation errors.
* @param {Function} props.onSubmit - Callback function to handle form submission.
* @param {Function} props.onChange - Callback function to handle form input changes.
* @param {Function} props.onBack - Callback function to handle "Back" button click.
* @returns {JSX.Element}
*/
const EmailStep = ({ form, errors, onSubmit, onChange }) => {
const theme = useTheme();
const inputRef = useRef(null);

useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);

return (
<>
<Stack
gap={{ xs: theme.spacing(12), sm: theme.spacing(16) }}
textAlign="center"
>
<Box>
<Typography component="h1">Log In</Typography>
<Typography>Enter your email address</Typography>
</Box>
<Box
textAlign="left"
component="form"
noValidate
spellCheck={false}
onSubmit={onSubmit}
display="grid"
gap={{ xs: theme.spacing(12), sm: theme.spacing(16) }}
>
<TextInput
type="email"
id="login-email-input"
label="Email"
isRequired={true}
placeholder="[email protected]"
autoComplete="email"
value={form.email}
onInput={(e) => (e.target.value = e.target.value.toLowerCase())}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid assigning directly within expressions

Assigning a value inside an expression can lead to unexpected behaviour. Instead of modifying e.target.value within the onInput, consider handling the lowercase transformation differently.

Apply this diff to fix the issue:

-onInput={(e) => (e.target.value = e.target.value.toLowerCase())}
+onChange={(e) => {
+  e.target.value = e.target.value.toLowerCase();
+  onChange(e);
+}}

This ensures the value is transformed and the change is properly propagated.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (1.9.4)

[error] 55-55: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)

onChange={onChange}
error={errors.email ? true : false}
helperText={errors.email}
ref={inputRef}
/>
<Stack
direction="row"
justifyContent="flex-end"
>
<Button
variant="contained"
color="primary"
type="submit"
disabled={errors.email && true}
sx={{
width: "30%",
"&.Mui-focusVisible": {
outline: `2px solid ${theme.palette.primary.main}`,
outlineOffset: `2px`,
boxShadow: `none`,
},
}}
>
Continue
</Button>
</Stack>
</Box>
</Stack>
</>
);
};

EmailStep.propTypes = {
form: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired,
onSubmit: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
};

export default EmailStep;
159 changes: 159 additions & 0 deletions Client/src/Pages/Auth/Login/Components/PasswordStep.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import { useRef, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { Box, Button, Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import LoadingButton from "@mui/lab/LoadingButton";
import { useSelector } from "react-redux";
import TextInput from "../../../../Components/Inputs/TextInput";
import { PasswordEndAdornment } from "../../../../Components/Inputs/TextInput/Adornments";
import ArrowBackRoundedIcon from "@mui/icons-material/ArrowBackRounded";
import PropTypes from "prop-types";

/**
* Renders the password step of the login process, including a password input field.
*
* @param {Object} props
* @param {Object} props.form - Form state object.
* @param {Object} props.errors - Object containing form validation errors.
* @param {Function} props.onSubmit - Callback function to handle form submission.
* @param {Function} props.onChange - Callback function to handle form input changes.
* @param {Function} props.onBack - Callback function to handle "Back" button click.
* @returns {JSX.Element}
*/
const PasswordStep = ({ form, errors, onSubmit, onChange, onBack }) => {
const theme = useTheme();
const navigate = useNavigate();
const inputRef = useRef(null);
const authState = useSelector((state) => state.auth);

useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);

const handleNavigate = () => {
if (form.email !== "" && !errors.email) {
sessionStorage.setItem("email", form.email);
}
navigate("/forgot-password");
};

return (
<>
<Stack
gap={{ xs: theme.spacing(12), sm: theme.spacing(16) }}
position="relative"
textAlign="center"
>
<Box>
<Typography component="h1">Log In</Typography>
<Typography>Enter your password</Typography>
</Box>
<Box
component="form"
noValidate
spellCheck={false}
onSubmit={onSubmit}
textAlign="left"
mb={theme.spacing(5)}
sx={{
display: "grid",
gap: { xs: theme.spacing(12), sm: theme.spacing(16) },
}}
>
<TextInput
type="password"
id="login-password-input"
label="Password"
isRequired={true}
placeholder="••••••••••"
autoComplete="current-password"
value={form.password}
onChange={onChange}
error={errors.password ? true : false}
helperText={errors.password}
ref={inputRef}
endAdornment={<PasswordEndAdornment />}
/>
<Stack
direction="row"
justifyContent="space-between"
>
<Button
variant="outlined"
color="info"
onClick={onBack}
sx={{
px: theme.spacing(5),
"& svg.MuiSvgIcon-root": {
mr: theme.spacing(3),
},
"&:focus-visible": {
outline: `2px solid ${theme.palette.primary.main}`,
outlineOffset: `2px`,
},
}}
>
<ArrowBackRoundedIcon />
Back
</Button>
<LoadingButton
variant="contained"
color="primary"
type="submit"
loading={authState.isLoading}
disabled={errors.password && true}
sx={{
width: "30%",
"&.Mui-focusVisible": {
outline: `2px solid ${theme.palette.primary.main}`,
outlineOffset: `2px`,
boxShadow: `none`,
},
}}
>
Continue
</LoadingButton>
</Stack>
</Box>
<Box
textAlign="center"
sx={{
position: "absolute",
bottom: 0,
left: "50%",
transform: `translate(-50%, 150%)`,
}}
>
<Typography
className="forgot-p"
display="inline-block"
color={theme.palette.primary.main}
>
Forgot password?
</Typography>
<Typography
component="span"
color={theme.palette.primary.main}
ml={theme.spacing(2)}
sx={{ userSelect: "none" }}
onClick={handleNavigate}
>
Reset password
</Typography>
</Box>
</Stack>
</>
);
};

PasswordStep.propTypes = {
form: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired,
onSubmit: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
onBack: PropTypes.func.isRequired,
};

export default PasswordStep
Loading
Loading