Skip to content

Commit 7ece235

Browse files
committed
merge main into branch
2 parents 70e404c + 7e78426 commit 7ece235

File tree

2 files changed

+187
-111
lines changed

2 files changed

+187
-111
lines changed

frontend/src/components/auth/Login.tsx

Lines changed: 182 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useContext, useState } from "react";
1+
import React, { useContext, useState, useEffect } from "react";
22
import { Redirect } from "react-router-dom";
33
import {
44
Button,
@@ -19,10 +19,10 @@ import background from "../assets/background.png";
1919
import backgroundMobile from "../assets/background_mobile.png";
2020
import auth from "../../firebase/firebase";
2121
import authAPIClient from "../../APIClients/AuthAPIClient";
22+
import { CREATE_PASSWORD_PAGE, HOME_PAGE } from "../../constants/Routes";
2223
import AuthContext from "../../contexts/AuthContext";
2324
import { AuthenticatedUser } from "../../types/AuthTypes";
24-
25-
let didInit = false;
25+
import ResponsiveModalWindow from "../common/responsive/ResponsiveModalWindow";
2626

2727
const Login = (): React.ReactElement => {
2828
const { authenticatedUser, setAuthenticatedUser } = useContext(AuthContext);
@@ -56,143 +56,215 @@ const Login = (): React.ReactElement => {
5656
setErrorMessage("Invalid login credentials.");
5757
}
5858
};
59-
const checkIfSignInLink = async () => {
60-
if (!authenticatedUser) {
59+
60+
const [redirectTo, setRedirectTo] = useState<string | null>(null);
61+
const [status, setStatus] = useState<"loading" | "error" | "default">(
62+
"default",
63+
);
64+
65+
useEffect(() => {
66+
setStatus("loading");
67+
const checkIfSignInLink = async () => {
6168
const url = window.location.href;
6269
const urlSearchParams = new URLSearchParams(window.location.search);
6370
const signInEmail = urlSearchParams.get("email"); // passed in from actionCode
6471
const isSignInLink = isSignInWithEmailLink(auth, url);
72+
6573
if (signInEmail && isSignInLink) {
6674
const user: AuthenticatedUser = await authAPIClient.loginWithSignInLink(
6775
url,
6876
signInEmail,
6977
);
70-
setAuthenticatedUser(user);
78+
if (user) {
79+
setAuthenticatedUser(user);
80+
setRedirectTo(CREATE_PASSWORD_PAGE);
81+
} else {
82+
setStatus("error");
83+
}
84+
} else {
85+
setStatus("default");
7186
}
87+
};
88+
89+
if (authenticatedUser) {
90+
setRedirectTo(HOME_PAGE);
91+
} else {
92+
checkIfSignInLink();
7293
}
73-
// alert: user is already logged in, please log out before trying again
74-
};
94+
}, [authenticatedUser, setAuthenticatedUser]);
7595

76-
if (authenticatedUser) {
77-
return <Redirect to="/" />;
96+
if (redirectTo) {
97+
return <Redirect to={redirectTo} />;
7898
}
7999

80-
if (!didInit) {
81-
didInit = true;
82-
checkIfSignInLink();
100+
if (authenticatedUser) {
101+
return <Redirect to="/" />;
83102
}
84103

85104
return (
86-
<Flex
87-
maxWidth="100vw"
88-
height="100vh"
89-
position="relative"
90-
backgroundRepeat="no-repeat"
91-
backgroundPosition="center"
92-
backgroundSize="cover"
93-
backgroundImage={`url(${backgroundMobile})`}
94-
sx={{
95-
"@media (orientation: landscape)": {
96-
height: "auto",
97-
minHeight: "100vh",
98-
overflowY: "auto",
99-
backgroundImage: `url(${background})`,
100-
},
101-
}}
102-
>
103-
<Center flex="1">
105+
<>
106+
{status === "loading" && (
104107
<Flex
105-
gap="2.2rem"
106-
direction="column"
107-
justify="center"
108-
alignItems="center"
109-
padding="1rem"
108+
maxWidth="100vw"
109+
height="100vh"
110+
position="relative"
111+
backgroundRepeat="no-repeat"
112+
backgroundPosition="center"
113+
backgroundSize="cover"
114+
sx={{
115+
"@media (orientation: landscape)": {
116+
height: "auto",
117+
minHeight: "100vh",
118+
overflowY: "auto",
119+
},
120+
}}
110121
>
111-
<ResponsiveLogo />
112-
<ResponsiveAuthContainer>
113-
<Text
114-
color="#4A5568"
115-
textStyle={{ base: "h2Mobile", md: "h2" }}
116-
mb="0"
117-
textAlign="center"
118-
>
119-
Welcome Back!
122+
<ResponsiveModalWindow>
123+
<Text color="#2C5282" textAlign="center">
124+
Loading, please wait...
125+
</Text>
126+
</ResponsiveModalWindow>
127+
</Flex>
128+
)}
129+
130+
{status === "error" && (
131+
<Flex
132+
maxWidth="100vw"
133+
height="100vh"
134+
position="relative"
135+
backgroundRepeat="no-repeat"
136+
backgroundPosition="center"
137+
backgroundSize="cover"
138+
sx={{
139+
"@media (orientation: landscape)": {
140+
height: "auto",
141+
minHeight: "100vh",
142+
overflowY: "auto",
143+
},
144+
}}
145+
>
146+
<ResponsiveModalWindow>
147+
<Text color="red.500" textAlign="center">
148+
An error occurred. If your link is expired, ask an adminstrator
149+
for assistance.
120150
</Text>
121-
<Stack>
122-
<Stack spacing={{ base: "1rem", md: "1.5rem" }} width="100%">
123-
<Box>
124-
<FormLabel
125-
fontSize="14px"
126-
textColor="var(--gray-600, #4A5568)"
127-
lineHeight="8px"
128-
>
129-
Email:
130-
</FormLabel>
131-
<FormControl isInvalid={!!errorMessage}>
132-
<ResponsiveEmailInput
133-
value={email}
134-
onChange={handleEmailChange}
135-
/>
136-
</FormControl>
137-
</Box>
138-
<Box>
139-
<FormLabel
140-
textColor="var(--gray-600, #4A5568)"
141-
fontSize="14px"
142-
lineHeight="8px"
143-
>
144-
Password:
145-
</FormLabel>
146-
<FormControl isInvalid={!!errorMessage}>
147-
<ResponsivePasswordInput
148-
value={password}
149-
onChange={handlePasswordChange}
150-
/>
151-
</FormControl>
152-
</Box>
151+
</ResponsiveModalWindow>
152+
</Flex>
153+
)}
154+
155+
{status === "default" && !redirectTo && (
156+
<Flex
157+
maxWidth="100vw"
158+
height="100vh"
159+
position="relative"
160+
backgroundRepeat="no-repeat"
161+
backgroundPosition="center"
162+
backgroundSize="cover"
163+
backgroundImage={`url(${backgroundMobile})`}
164+
sx={{
165+
"@media (orientation: landscape)": {
166+
height: "auto",
167+
minHeight: "100vh",
168+
overflowY: "auto",
169+
backgroundImage: `url(${background})`,
170+
},
171+
}}
172+
>
173+
<Center flex="1">
174+
<Flex
175+
gap="2.2rem"
176+
direction="column"
177+
justify="center"
178+
alignItems="center"
179+
padding="1rem"
180+
>
181+
<ResponsiveLogo />
182+
<ResponsiveAuthContainer>
153183
<Text
154-
cursor="pointer"
155-
fontSize="14px"
156-
onClick={handleForgotPassword}
157-
color="#494B42"
184+
color="#4A5568"
185+
textStyle={{ base: "h2Mobile", md: "h2" }}
186+
mb="0"
158187
textAlign="center"
159-
_hover={{ textDecoration: "underline" }}
160188
>
161-
Forgot Password?
189+
Welcome Back!
162190
</Text>
163-
</Stack>
164-
165-
<Box>
166-
<Button
167-
type="submit"
168-
fontSize="14px"
169-
onClick={handleLogin}
170-
color="white"
171-
h="2.4rem"
172-
width="100%"
173-
bg="var(--blue-700, #2C5282)"
174-
>
175-
Login
176-
</Button>
177-
{errorMessage && (
178-
<Box textAlign="center">
191+
<Stack>
192+
<Stack spacing={{ base: "1rem", md: "1.5rem" }} width="100%">
193+
<Box>
194+
<FormLabel
195+
fontSize="14px"
196+
textColor="var(--gray-600, #4A5568)"
197+
lineHeight="8px"
198+
>
199+
Email:
200+
</FormLabel>
201+
<FormControl isInvalid={!!errorMessage}>
202+
<ResponsiveEmailInput
203+
value={email}
204+
onChange={handleEmailChange}
205+
/>
206+
</FormControl>
207+
</Box>
208+
<Box>
209+
<FormLabel
210+
textColor="var(--gray-600, #4A5568)"
211+
fontSize="14px"
212+
lineHeight="8px"
213+
>
214+
Password:
215+
</FormLabel>
216+
<FormControl isInvalid={!!errorMessage}>
217+
<ResponsivePasswordInput
218+
value={password}
219+
onChange={handlePasswordChange}
220+
/>
221+
</FormControl>
222+
</Box>
179223
<Text
180-
color="red.500"
224+
cursor="pointer"
181225
fontSize="14px"
182-
lineHeight="1"
183-
mb="0"
184-
mt="1rem"
226+
onClick={handleForgotPassword}
227+
color="#494B42"
228+
textAlign="center"
229+
_hover={{ textDecoration: "underline" }}
185230
>
186-
{errorMessage}
231+
Forgot Password?
187232
</Text>
233+
</Stack>
234+
235+
<Box>
236+
<Button
237+
type="submit"
238+
fontSize="14px"
239+
onClick={handleLogin}
240+
color="white"
241+
h="2.4rem"
242+
width="100%"
243+
bg="var(--blue-700, #2C5282)"
244+
>
245+
Login
246+
</Button>
247+
{errorMessage && (
248+
<Box textAlign="center">
249+
<Text
250+
color="red.500"
251+
fontSize="14px"
252+
lineHeight="1"
253+
mb="0"
254+
mt="1rem"
255+
>
256+
{errorMessage}
257+
</Text>
258+
</Box>
259+
)}
188260
</Box>
189-
)}
190-
</Box>
191-
</Stack>
192-
</ResponsiveAuthContainer>
261+
</Stack>
262+
</ResponsiveAuthContainer>
263+
</Flex>
264+
</Center>
193265
</Flex>
194-
</Center>
195-
</Flex>
266+
)}
267+
</>
196268
);
197269
};
198270

frontend/src/components/pages/CreatePasswordPage.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ import {
1010
FormLabel,
1111
FormControl,
1212
} from "@chakra-ui/react";
13+
import { useHistory } from "react-router-dom";
1314
import ResponsiveLogo from "../common/responsive/ResponsiveAuthPageLogo";
1415
import ResponsivePasswordInput from "../common/responsive/ResponsivePasswordInput";
1516
import ResponsiveAuthContainer from "../common/responsive/ResponsiveAuthContainer";
1617
import ResponsiveModalWindow from "../common/responsive/ResponsiveModalWindow";
1718
import background from "../assets/background.png";
1819
import backgroundMobile from "../assets/background_mobile.png";
1920
import AuthAPIClient from "../../APIClients/AuthAPIClient";
21+
import { HOME_PAGE } from "../../constants/Routes";
2022

2123
const CreatePasswordPage = (): React.ReactElement => {
2224
const [showModal, setShowModal] = React.useState(false);
@@ -25,6 +27,8 @@ const CreatePasswordPage = (): React.ReactElement => {
2527
const [errorMessage, setErrorMessage] = React.useState("");
2628
const [email, setEmail] = React.useState("Email not found.");
2729

30+
const history = useHistory();
31+
2832
React.useEffect(() => {
2933
const getEmail = async () => {
3034
const userEmail = await AuthAPIClient.getEmailOfCurrentUser();
@@ -73,7 +77,7 @@ const CreatePasswordPage = (): React.ReactElement => {
7377
};
7478

7579
const handleGetStarted = () => {
76-
// TODO: Navigate to main page
80+
history.push(HOME_PAGE);
7781
};
7882

7983
return (

0 commit comments

Comments
 (0)