Skip to content

Commit

Permalink
Merge branch 'main' into add-navbar
Browse files Browse the repository at this point in the history
  • Loading branch information
aliicezhao committed Nov 13, 2024
2 parents 20a00a1 + dc09e33 commit 696a5bb
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 0 deletions.
6 changes: 6 additions & 0 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Default from "./components/pages/Default";
import Login from "./components/auth/Login";
import Signup from "./components/auth/Signup";
import ForgotPasswordPage from "./components/pages/ForgotPassword";
import PrivateRoute from "./components/auth/PrivateRoute";
import CreatePage from "./components/pages/CreatePage";
import PetListPage from "./components/pages/PetListPage";
Expand Down Expand Up @@ -63,6 +64,11 @@ const App = (): React.ReactElement => {
{/* Public Routes */}
<Route exact path={AppRoutes.LOGIN_PAGE} component={Login} />
<Route exact path={AppRoutes.SIGNUP_PAGE} component={Signup} />
<Route
exact
path={AppRoutes.FORGOT_PASSWORD_PAGE}
component={ForgotPasswordPage}
/>

{/* Protected Routes Wrapped in Layout */}
<Layout>
Expand Down
20 changes: 20 additions & 0 deletions frontend/src/components/common/StatusMessage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";
import { Text } from "@chakra-ui/react";

interface StatusMessageProps {
message: string;
color?: string;
}

const StatusMessage = ({
message,
color = "blue.700",
}: StatusMessageProps): React.ReactElement => {
return (
<Text color={color} textAlign="center" lineHeight="120%" marginTop="16px">
{message}
</Text>
);
};

export default StatusMessage;
156 changes: 156 additions & 0 deletions frontend/src/components/pages/ForgotPassword.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import React, { useState } from "react";
import {
Box,
Input,
Text,
Button,
FormControl,
FormErrorMessage,
Flex,
} from "@chakra-ui/react";
import StatusMessage from "../common/StatusMessage";
import background from "./login_background.png";
import backgroundMobile from "./login_background_phone.png";

type SentEmail = {
email: string;
timestamp: number;
};

const ForgotPassword = (): React.ReactElement => {
const [validUser, setValidUser] = useState(true);
const [sentEmail, setSentEmail] = useState(false);
const [sentEmailToUser, setSentEmailToUser] = useState(false);
const [userEmailId, setUserEmaild] = useState("");

const handleUserAuth = (userEmail: string) => {
const emailPattern = /^[^\s@]+@(humanesociety\.org|uwblueprint\.org)$/;
// added uwblueprint for test
const sentEmails: SentEmail[] = JSON.parse(
localStorage.getItem("sentEmails") || "[]",
);
if (!emailPattern.test(userEmail)) {
setValidUser(false);
} else if (sentEmails.some((item) => item.email === userEmail)) {
setValidUser(true);
setSentEmail(false);
setSentEmailToUser(true);
} else {
// make API call to check if user exists
setValidUser(true);
setSentEmail(true);
// send email logic
const newEmail: SentEmail = {
email: userEmail,
timestamp: new Date().getTime(),
};
sentEmails.push(newEmail);
localStorage.setItem("sentEmails", JSON.stringify(sentEmails));
setTimeout(() => {
const updatedSentEmails: SentEmail[] = JSON.parse(
localStorage.getItem("sentEmails") || "[]",
);
const filteredEmails = updatedSentEmails.filter(
(item: SentEmail) => item.email !== userEmail,
);
localStorage.setItem("sentEmails", JSON.stringify(filteredEmails));
setSentEmailToUser(false);
}, 60000);
}
};

const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValidUser(true);
setSentEmail(false);
setSentEmailToUser(false);
setUserEmaild(e.target.value);
};

return (
<Flex
height="100vh"
width="100vw"
backgroundImage={`url(${backgroundMobile})`}
sx={{
"@media (orientation: landscape)": {
height: "auto",
minHeight: "100vh",
overflowY: "auto",
backgroundImage: `url(${background})`,
},
}}
backgroundPosition="center"
backgroundRepeat="no-repeat"
backgroundSize="cover"
backgroundColor="blue.700"
justify="center"
align="center"
overflow="auto"
>
<Box
maxWidth="100vw"
width={["90vw", "50vw", "50vw", "40vw", "30vw"]}
padding={["36px", "36px", "36px", "60px 64px"]}
borderRadius="6px"
backgroundColor="var(--gray-50, #F7FAFC)"
boxShadow="lg"
display="flex"
flexDirection="column"
marginTop="20px"
marginBottom="20px"
>
<Text
color="#4A5568"
textStyle="h2"
textAlign="center"
lineHeight="120%"
>
Forgot Password?
</Text>
<Text py="36px" color="#4A5568" textStyle="body" textAlign="center">
Please enter the email address associated with your account to reset
your password.
</Text>
<Box>
<Text color="#4A5568" textStyle="body">
Email:
</Text>
<FormControl isInvalid={!validUser}>
<Input
placeholder="[email protected]"
size="lg"
borderRadius="md"
borderColor="gray.400"
onChange={handleInputChange}
/>
{!validUser && (
<FormErrorMessage fontSize="16px">
Must be a valid humanesociety.org email
</FormErrorMessage>
)}
</FormControl>
<Button
textStyle="button"
size="lg"
width="100%"
variant="solid"
color="white"
bg="blue.700"
marginTop="30px"
onClick={() => handleUserAuth(userEmailId)}
>
Send
</Button>
</Box>
{sentEmail && (
<StatusMessage message="A password reset link has been sent to your email!" />
)}
{sentEmailToUser && (
<StatusMessage message="You have already sent an email to this user." />
)}
</Box>
</Flex>
);
};

export default ForgotPassword;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions frontend/src/constants/Routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export const LOGIN_PAGE = "/login";

export const SIGNUP_PAGE = "/signup";

export const FORGOT_PASSWORD_PAGE = "/forgotPassword";

export const EDIT_TEAM_PAGE = "/edit-team";

export const DISPLAY_ENTITY_PAGE = "/entity";
Expand Down

0 comments on commit 696a5bb

Please sign in to comment.