diff --git a/client/assets/SigninScreenBG.png b/client/assets/SigninScreenBG.png new file mode 100644 index 0000000..3f57a22 Binary files /dev/null and b/client/assets/SigninScreenBG.png differ diff --git a/client/src/App.tsx b/client/src/App.tsx index 38e735e..34a4aaa 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,12 +1,14 @@ import { Route, Routes } from "react-router-dom"; import HomePage from "./pages/HomePage"; import SignUpPage from "./pages/SignUpPage"; +import SignInPage from "./pages/SignInPage"; function App() { return ( } path="/" /> } path="/signup" /> + } path="/signin" /> ); } diff --git a/client/src/components/SignInModule.tsx b/client/src/components/SignInModule.tsx new file mode 100644 index 0000000..0068dd8 --- /dev/null +++ b/client/src/components/SignInModule.tsx @@ -0,0 +1,100 @@ +import { Button, Link } from "@nextui-org/react"; +import { Formik, Form } from "formik"; +import * as Yup from "yup"; +import axios from "axios"; +import config from "../config"; +import NextUIFormikInput from "./NextUIFormikInput"; +import { useNavigate } from "react-router-dom"; +import { ChevronLeftIcon } from "../icons"; + +const validationSchema = Yup.object({ + email: Yup.string() + .trim() + .lowercase() + .min(5) + .max(69) + .email("Invalid email format") + .required("Email is required"), + password: Yup.string() + .trim() + .max(69, "Password must be at most 69 characters") + .matches( + /^(?=.*[a-zA-Z])(?=.*[0-9]).{1,}$/, + "Password contains only letters and numbers" + ) + .required("Password is required"), +}); + +export default function SignInModule() { + const navigate = useNavigate(); + + const initialValues = { + email: "", + password: "", + }; + + const handleSubmit = async (values: any) => { + try { + const response = await axios.post( + config.serverAddress + "/users/login", + values + ); + console.log(response.data.accessToken); + } catch (error) { + console.error("Error logging in:", error); + } + }; + + return ( +
+
+

Sign In

+

to ecoconnect

+
+ + {({ isValid, dirty }) => ( +
+ + + + + )} +
+
+

New here?

+ { + navigate("/signup"); + }} + > + Sign up + +
+
+ ); +} diff --git a/client/src/components/SignUpModule.tsx b/client/src/components/SignUpModule.tsx index 8159ed6..2f7b283 100644 --- a/client/src/components/SignUpModule.tsx +++ b/client/src/components/SignUpModule.tsx @@ -4,6 +4,7 @@ import * as Yup from "yup"; import axios from "axios"; import config from "../config"; import NextUIFormikInput from "./NextUIFormikInput"; +import { useNavigate } from "react-router-dom"; const validationSchema = Yup.object({ firstName: Yup.string() @@ -44,6 +45,8 @@ const validationSchema = Yup.object({ }); export default function SignUpModule() { + const navigate = useNavigate(); + const initialValues = { firstName: "", lastName: "", @@ -66,7 +69,7 @@ export default function SignUpModule() { }; return ( -
+
)} +
+

Already here before?

+ { + navigate("/signin"); + }} + > + Sign in + +
); } diff --git a/client/src/components/SingaporeAgencyStrip.tsx b/client/src/components/SingaporeAgencyStrip.tsx index 431e095..378c0fa 100644 --- a/client/src/components/SingaporeAgencyStrip.tsx +++ b/client/src/components/SingaporeAgencyStrip.tsx @@ -3,7 +3,7 @@ import { Link } from "@nextui-org/react"; export default function SingaporeAgencyStrip() { return (
-
+
Merlion Icon

A Singapore Government Agency Website

How to identify diff --git a/client/src/icons.tsx b/client/src/icons.tsx new file mode 100644 index 0000000..94b8540 --- /dev/null +++ b/client/src/icons.tsx @@ -0,0 +1,18 @@ +export const ChevronLeftIcon = () => { + return ( + + + + ); +}; diff --git a/client/src/layouts/default.tsx b/client/src/layouts/default.tsx new file mode 100644 index 0000000..67292bf --- /dev/null +++ b/client/src/layouts/default.tsx @@ -0,0 +1,14 @@ +import SingaporeAgencyStrip from "../components/SingaporeAgencyStrip"; + +export default function DefaultLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( +
+ +
{children}
+
+ ); +} diff --git a/client/src/pages/HomePage.tsx b/client/src/pages/HomePage.tsx index 4be06d6..e1a926d 100644 --- a/client/src/pages/HomePage.tsx +++ b/client/src/pages/HomePage.tsx @@ -1,10 +1,11 @@ import { Button } from "@nextui-org/react"; import { useNavigate } from "react-router-dom"; +import DefaultLayout from "../layouts/default"; export default function HomePage() { const navigate = useNavigate(); return ( -
+

Home

-
+ ); } diff --git a/client/src/pages/SignInPage.tsx b/client/src/pages/SignInPage.tsx new file mode 100644 index 0000000..c2e9f39 --- /dev/null +++ b/client/src/pages/SignInPage.tsx @@ -0,0 +1,36 @@ +import SignInModule from "../components/SignInModule"; +import DefaultLayout from "../layouts/default"; + +export default function SignInPage() { + return ( + +
+
+
+
+
+ HDB flat +
+
+

Welcome back!

+

+ Good to have you here again. Tell us who you are, and wel + will let you in. +

+
+
+
+
+
+
+ +
+
+
+
+ ); +} diff --git a/client/src/pages/SignUpPage.tsx b/client/src/pages/SignUpPage.tsx index dc8ece4..de06468 100644 --- a/client/src/pages/SignUpPage.tsx +++ b/client/src/pages/SignUpPage.tsx @@ -1,11 +1,10 @@ import SignUpModule from "../components/SignUpModule"; -import SingaporeAgencyStrip from "../components/SingaporeAgencyStrip"; +import DefaultLayout from "../layouts/default"; export default function SignUpPage() { return ( -
+
-
@@ -32,6 +31,6 @@ export default function SignUpPage() {
-
+
); }