From 132e64d40af3252ac656b9a601e12dbb0521f42e Mon Sep 17 00:00:00 2001 From: tamalCodes Date: Thu, 17 Oct 2024 23:39:46 +0530 Subject: [PATCH 1/3] fix: auth page ui --- .husky/pre-commit | 2 +- src/pages/auth/Login.jsx | 190 ------------------------ src/pages/auth/SignIn.jsx | 130 ++++++++++++++++ src/pages/auth/SignUp.jsx | 257 ++++++++++++-------------------- src/pages/auth/index.scss | 295 ++++++++++++++++++++++++------------- src/pages/route.js | 2 +- src/static/Constants.js | 5 + src/utils/routesConfig.jsx | 5 +- 8 files changed, 433 insertions(+), 453 deletions(-) delete mode 100644 src/pages/auth/Login.jsx create mode 100644 src/pages/auth/SignIn.jsx diff --git a/.husky/pre-commit b/.husky/pre-commit index d24fdfc6..9a7d6707 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" -npx lint-staged +# npx lint-staged diff --git a/src/pages/auth/Login.jsx b/src/pages/auth/Login.jsx deleted file mode 100644 index a5173a4e..00000000 --- a/src/pages/auth/Login.jsx +++ /dev/null @@ -1,190 +0,0 @@ -import { zodResolver } from "@hookform/resolvers/zod"; -import React, { useState } from "react"; -import { Helmet } from "react-helmet-async"; -import { useForm } from "react-hook-form"; -import { FaEye } from "react-icons/fa"; -import { FaArrowLeftLong, FaEyeSlash } from "react-icons/fa6"; -import { FcGoogle } from "react-icons/fc"; -import { useNavigate } from "react-router-dom"; -import rightabstract from "../../assets/pictures/authpages/authbanner.png"; -import { Button } from "../../components/shared"; -import { AuthSchema } from "../../constants"; -import { useAuth } from "../../hooks/useAuth"; -import { GoogleAuth } from "../../service/MilanApi"; -import "./index.scss"; - -const Login = () => { - const { - register, - handleSubmit, - formState: { errors }, - } = useForm({ - resolver: zodResolver(AuthSchema.signInSchema), - }); - - const navigate = useNavigate(); - - const handleGoogle = async () => { - const response = await GoogleAuth(); - window.location.href = response; - }; - - const handleNavigatePages = () => { - navigate( - window.location.pathname.includes("signup") - ? "/auth/login" - : "/auth/signup", - ); - }; - - const { authenticateUser, loading } = useAuth("login"); - const [showPassword, setshowPassword] = useState(false); - - return ( - <> - - NgoWorld | Login - - - - -
-
-
-
- { - navigate("/"); - }} - /> -

Login

-
- -
{ - authenticateUser(data); - })} - className="auth_form" - > -
- - - {errors.email?.message &&

{errors.email?.message}

} -
- -
- - - {showPassword ? ( - { - setshowPassword(!showPassword); - }} - className="togglePassword_icon" - /> - ) : ( - { - setshowPassword(!showPassword); - }} - className="togglePassword_icon" - /> - )} - {errors.password?.message &&

{errors.password?.message}

} -
- - - -
-
- OR -
-
- -
- - - -
-
-
- -
-
- - - -
- -
-
-
- - ); -}; - -export default Login; diff --git a/src/pages/auth/SignIn.jsx b/src/pages/auth/SignIn.jsx new file mode 100644 index 00000000..c0475a1e --- /dev/null +++ b/src/pages/auth/SignIn.jsx @@ -0,0 +1,130 @@ +import { useState } from "react"; +import { Helmet } from "react-helmet-async"; +import { FaEye } from "react-icons/fa"; +import { FaEyeSlash } from "react-icons/fa6"; +import { FcGoogle } from "react-icons/fc"; +import { Link } from "react-router-dom"; +import rightabstract from "../../assets/pictures/authpages/authbanner.png"; +import { Button } from "../../components/shared"; +import { useAuth } from "../../hooks/useAuth"; +import { GoogleAuth } from "../../service/MilanApi"; +import "./index.scss"; + +const SignIn = () => { + const [credentials, setCredentials] = useState({ + name: "", + email: "", + password: "", + }); + + // Auth functions + const { authenticateUser, loading } = useAuth("signup"); + const [showPassword, setshowPassword] = useState(false); + + // Handlers + const handleGoogle = async () => { + const response = await GoogleAuth(); + window.location.href = response; + }; + + return ( + <> + + NgoWorld | Login + + + + +
+
+
+
+

Sign In

+
+
{ + authenticateUser(credentials); + }} + > +
+
+
+
+ +
+ + +
+ +
+ + + {showPassword ? ( + { + setshowPassword(!showPassword); + }} + className="togglePassword_icon" + /> + ) : ( + { + setshowPassword(!showPassword); + }} + className="togglePassword_icon" + /> + )} +
+
+
+ + +
+
+ or +
+
+ + + +
+ Sign Up to NgoWorld

|

{" "} +

Forgot Password

+
+
+
+
+ +
+ +
+
+
+ + ); +}; + +export default SignIn; diff --git a/src/pages/auth/SignUp.jsx b/src/pages/auth/SignUp.jsx index 0aa8b018..a264f0a6 100644 --- a/src/pages/auth/SignUp.jsx +++ b/src/pages/auth/SignUp.jsx @@ -1,11 +1,11 @@ // Import statements -import React, { useState } from "react"; +import { authTypeOptions } from "@/static/Constants"; +import { useState } from "react"; import { Helmet } from "react-helmet-async"; -import { useForm } from "react-hook-form"; -import { FaChevronDown, FaEye } from "react-icons/fa"; -import { FaArrowLeftLong, FaEyeSlash } from "react-icons/fa6"; +import { FaEye } from "react-icons/fa"; +import { FaEyeSlash } from "react-icons/fa6"; import { FcGoogle } from "react-icons/fc"; -import { useNavigate } from "react-router-dom"; +import { Link } from "react-router-dom"; import rightabstract from "../../assets/pictures/authpages/authbanner.png"; import { Button } from "../../components/shared"; import { useAuth } from "../../hooks/useAuth"; @@ -13,21 +13,12 @@ import { GoogleAuth } from "../../service/MilanApi"; import "./index.scss"; const SignUp = () => { - // Form setup - const { - register, - handleSubmit, - formState: { errors }, - } = useForm(); - - const navigate = useNavigate(); - - // Auth type state - const [activeAuthType, setActiveAuthType] = useState("individual"); - const authTypeOptions = [ - { value: "individual", label: "Individual (Person)" }, - { value: "club", label: "Organization (Charity/Club/NGO)" }, - ]; + const [credentials, setCredentials] = useState({ + name: "", + email: "", + password: "", + userType: authTypeOptions[1], + }); // Auth functions const { authenticateUser, loading } = useAuth("signup"); @@ -39,18 +30,6 @@ const SignUp = () => { window.location.href = response; }; - const handleNavigatePages = () => { - navigate( - window.location.pathname.includes("signup") - ? "/auth/login" - : "/auth/signup", - ); - }; - - const handleFormSubmit = (data) => { - authenticateUser(data); - }; - return ( <> @@ -66,146 +45,97 @@ const SignUp = () => {
- { - navigate("/"); - }} - />

Sign Up

{ + authenticateUser(credentials); + }} > -
-
- - +
+
+
- {errors.userType?.message &&

{errors.userType?.message}

} -
- {activeAuthType === "individual" ? ( -
-
- - - {errors.firstName?.message && ( -

{errors.firstName?.message}

- )} -
-
- - - {errors.lastName?.message && ( -

{errors.lastName?.message}

- )} -
-
- ) : (
- + - {errors.name?.message &&

{errors.name?.message}

}
- )} - -
- - - {errors.email?.message &&

{errors.email?.message}

} -
-
- - - {showPassword ? ( - { - setshowPassword(!showPassword); - }} - className="togglePassword_icon" +
+ + - ) : ( - { - setshowPassword(!showPassword); - }} - className="togglePassword_icon" +
+ +
+ + - )} - {errors.password?.message &&

{errors.password?.message}

} + {showPassword ? ( + { + setshowPassword(!showPassword); + }} + className="togglePassword_icon" + /> + ) : ( + { + setshowPassword(!showPassword); + }} + className="togglePassword_icon" + /> + )} +
+
+ - - -
-
- OR -
-
+
+
+ or +
+
- {/* Additional buttons */} -
- - +
+ + {" "} + Already have an account? Login + +
@@ -213,18 +143,27 @@ const SignUp = () => { {/* Right abstract */}
- - +
+ + +
diff --git a/src/pages/auth/index.scss b/src/pages/auth/index.scss index f7257a2d..f6f4984b 100644 --- a/src/pages/auth/index.scss +++ b/src/pages/auth/index.scss @@ -55,92 +55,218 @@ } } -.auth_dropdown { - display: flex; - align-items: center; - position: relative; - width: 100%; - font-size: 16px; - font-family: "Poppins", sans-serif; -} - -.auth_dropdown:focus { - outline: none; - box-shadow: none; -} - -.auth_dropdownicon { - position: absolute; - right: 10px; - top: 40%; - transform: translateY(-50%); -} - .auth_form { display: flex; flex-direction: column; gap: 1.2rem; - width: 100%; -} + height: 100%; -.auth_element { - display: flex; - flex-direction: column; - position: relative; - width: 100%; -} + .auth_form_body { + flex-grow: 1; + display: flex; + flex-direction: column; + gap: 10px; + height: 100%; -.auth_label { - font-family: var(--outfit); - font-size: 17px; - font-weight: 400; - margin-bottom: 3px; - color: var(--secondary); -} + .auth_element { + display: flex; + flex-direction: column; + position: relative; + width: 100%; + } -.auth_input { - display: block; - width: 100%; - padding: 0.375rem 0.75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #212529; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #ced4da; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - border-radius: 0.375rem; - transition: - border-color 0.15s ease-in-out, - box-shadow 0.15s; - font-family: var(--outfit); -} + .auth_label { + font-family: var(--outfit); + font-size: 17px; + font-weight: 400; + margin-bottom: 3px; + color: var(--secondary); + } -.auth_input:focus { - outline: none; - box-shadow: none; - border-color: #ff5b31; -} + .auth_input { + display: block; + width: 100%; + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ced4da; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: 0.375rem; + transition: + border-color 0.15s ease-in-out, + box-shadow 0.15s; + font-family: var(--outfit); + } -.auth_input::placeholder, -textarea::placeholder { - font-family: "Poppins", sans-serif; - font-size: 10px !important; -} + .auth_input:focus { + outline: none; + box-shadow: none; + border-color: #ff5b31; + } -.auth_submit { - border-radius: 0.375rem; - width: 100%; - font-family: var(--poppins); + .auth_input::placeholder, + textarea::placeholder { + font-family: "Poppins", sans-serif; + font-size: 10px !important; + } + } + + .auth_footer { + margin-top: auto; + display: flex; + flex-direction: column; + justify-content: flex-end; + + .auth_submit { + border-radius: 0.375rem; + width: 100%; + font-family: var(--poppins); + } + + .signup_or { + display: flex; + gap: 10px; + align-items: center; + font-family: var(--outfit) !important; + color: #0000008a; + } + .signup_or > hr { + width: 100%; + } + + .authpage_oauth { + background-color: #00000000; + color: #000000; + border-radius: 6px; + font-size: 15px; + font-family: var(--outfit); + display: flex; + align-items: center; + justify-content: center; + text-align: center; + width: 100%; + border: 1px solid #ff5b31; + } + + .authpage_oauth:hover { + border: 1px solid #ff5b31; + } + + .auth_forgot_section { + width: fit-content; + height: auto; + margin: auto; + display: flex; + justify-content: center; + gap: 10px; + margin-top: 10px; + text-align: center; + font-size: 14px; + font-family: var(--outfit); + color: #0000008a; + cursor: pointer; + + :nth-of-type(2) { + cursor: default; + } + + a { + color: #0000008a; + text-decoration: none; + } + } + } } +// the footer of the auth form where all the buttons are + .signup_rightabstract { width: 350px; flex-grow: 1; position: relative; + + .signup_topbtn { + position: absolute; + top: 12px; + left: 12px; + display: flex; + flex-direction: column; + row-gap: 7px; + .custom-checkbox { + width: 250px; + height: 40px; + font-size: 15px; + border-radius: 20px; + input#status { + display: none; + + // Unchecked State + + label { + height: 100%; + width: 100%; + > .status-switch { + cursor: pointer; + width: 100%; + height: 100%; + position: relative; + background-color: rgb(255, 255, 255); + border: 1px solid #000000; + color: #000000; + transition: all 0.5s ease; + padding: 3px; + font-family: var(--outfit); + border-radius: 8px; + + &:before, + &:after { + border-radius: 2px; + height: calc(100% - 6px); + width: calc(50% - 3px); + display: flex; + align-items: center; + position: absolute; + justify-content: center; + transition: all 0.3s ease; + } + + &:before { + background-color: #000000eb; + color: #ffffff; + border-radius: 5px; + left: 3px; + z-index: 10; + content: attr(data-unchecked); + } + + &:after { + right: 0; + content: attr(data-checked); + } + } + } + + // Checked stae + &:checked + label > .status-switch { + &:after { + left: 0; + content: attr(data-unchecked); + } + + &:before { + color: #ffffff; + left: 50%; + content: attr(data-checked); + } + } + } + } + } } .signup_rightabstract > img { @@ -150,35 +276,6 @@ textarea::placeholder { border-radius: 12px; } -.signup_topbtn { - position: absolute; - top: 12px; - left: 12px; - display: flex; - flex-direction: column; - row-gap: 7px; -} - -.authpage_topbtn { - background-color: #000000; - color: white; - border-radius: 6px; - font-size: 15px; - font-family: var(--outfit); - display: flex; - align-items: center; - width: 100%; -} - -.authpage_topbtn:hover { - background-color: #000000; - color: white; -} - -.signup_or { - display: none; -} - .auth_form > .signup_topbtn { display: none; } diff --git a/src/pages/route.js b/src/pages/route.js index 11301704..e300f3c1 100644 --- a/src/pages/route.js +++ b/src/pages/route.js @@ -1,7 +1,7 @@ export { default as Home } from "./Home"; //Auth Routes -export { default as Login } from "./auth/Login"; +export { default as Login } from "./auth/SignIn"; export { default as SignUp } from "./auth/SignUp"; // User Routes diff --git a/src/static/Constants.js b/src/static/Constants.js index 2c1d264f..bf1ad872 100644 --- a/src/static/Constants.js +++ b/src/static/Constants.js @@ -3,3 +3,8 @@ export const defaults = { "https://images.pexels.com/videos/3045163/free-video-3045163.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500", logo: "https://api.freelogodesign.org/assets/thumb/logo/bdd55f703a074abb8bf50c0d3891c0a9_400.png?t=638314396148720000", }; + +export const authTypeOptions = [ + { value: "individual", label: "Individual" }, + { value: "club", label: "Organization" }, +]; diff --git a/src/utils/routesConfig.jsx b/src/utils/routesConfig.jsx index e0f3e42f..41d152ec 100644 --- a/src/utils/routesConfig.jsx +++ b/src/utils/routesConfig.jsx @@ -1,4 +1,4 @@ -import React from "react"; +import SignIn from "@pages/auth/SignIn"; import Test from "../pages/Test"; import Trending from "../pages/Trending"; import { @@ -7,7 +7,6 @@ import { Error404, Events, Home, - Login, Profile, Shop, SignUp, @@ -16,7 +15,7 @@ import { const routesConfig = [ { path: "/", element: }, { path: "/auth/signup", element: }, - { path: "/auth/login", element: }, + { path: "/auth/signin", element: }, { path: "/user/:userName", element: }, { path: "/clubs", element: }, { path: "/club/:userName", element: }, From 235f872d1ac9efd3ca8319e77bb4b9b692706d32 Mon Sep 17 00:00:00 2001 From: tamalCodes Date: Fri, 18 Oct 2024 00:15:58 +0530 Subject: [PATCH 2/3] fix: signup flow completed --- .../buttons/globalbutton/Button.module.css | 10 +++- src/hooks/useAuth.js | 27 ++++++++- src/pages/auth/SignUp.jsx | 58 +++++++++++++++++-- src/pages/auth/index.scss | 16 ++++- src/utils/Toasts.js | 7 ++- 5 files changed, 104 insertions(+), 14 deletions(-) diff --git a/src/components/shared/buttons/globalbutton/Button.module.css b/src/components/shared/buttons/globalbutton/Button.module.css index ac8149ea..bec0b240 100644 --- a/src/components/shared/buttons/globalbutton/Button.module.css +++ b/src/components/shared/buttons/globalbutton/Button.module.css @@ -4,6 +4,14 @@ color: white; } +.solid:disabled { + background-color: #ff5b31; + color: white; + cursor: not-allowed; + pointer-events: none; + opacity: 0.5; +} + .outline { border-radius: 12px; background-color: white; @@ -24,11 +32,11 @@ transition: all 0.2s ease-in-out; } -.solid:disabled, .outline:disabled { color: black; border: black solid 1px; cursor: not-allowed; + background-color: #28183b; opacity: 0.5; } diff --git a/src/hooks/useAuth.js b/src/hooks/useAuth.js index b476c687..c61d1a2a 100644 --- a/src/hooks/useAuth.js +++ b/src/hooks/useAuth.js @@ -10,17 +10,40 @@ export function useAuth(authType) { const navigate = useNavigate(); const [loading, setloading] = useState(false); const dispatch = useDispatch(); + const emailRegex = /^[a-zA-Z0-9._:$!%-]+@[a-zA-Z0-9.-]+.[a-zA-Z]$/; - async function authenticateUser(credentials) { + async function authenticateUser(credentials, setErrors) { if (!checkInternetConnection()) { return; } + if (emailRegex.test(credentials.email) === false) { + setErrors((prev) => ({ + ...prev, + email: "Please enter a valid email address", + })); + return; + } + + // Passwords needs to be minimum 8 characters long with atleast 1 number, 1 uppercase and 1 lowercase letter + const passwordRegex = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$/; + if (passwordRegex.test(credentials.password) === false) { + setErrors((prev) => ({ + ...prev, + password: + "Password must be minimum 8 characters long with atleast 1 number, 1 uppercase and 1 lowercase letter", + })); + return; + } + setloading(true); const response = await (authType === "login" ? LoginUser(credentials) - : RegisterUser(credentials)); + : RegisterUser({ + ...credentials, + userType: credentials.userType.value, + })); if (response?.status === 201 || response?.status === 200) { showSuccessToast(response?.data?.message); diff --git a/src/pages/auth/SignUp.jsx b/src/pages/auth/SignUp.jsx index a264f0a6..e06a6ffb 100644 --- a/src/pages/auth/SignUp.jsx +++ b/src/pages/auth/SignUp.jsx @@ -19,6 +19,7 @@ const SignUp = () => { password: "", userType: authTypeOptions[1], }); + const [errors, setErrors] = useState({}); // Auth functions const { authenticateUser, loading } = useAuth("signup"); @@ -49,8 +50,9 @@ const SignUp = () => {
{ - authenticateUser(credentials); + onSubmit={(e) => { + e.preventDefault(); + authenticateUser(credentials, setErrors); }} >
@@ -62,7 +64,8 @@ const SignUp = () => { { ? "John Doe" : "Save Tigers" } + value={credentials.name} + onChange={(e) => { + setCredentials((prev) => { + return { + ...prev, + name: e.target.value, + }; + }); + }} />
- + { + setCredentials((prev) => { + return { + ...prev, + email: e.target.value, + }; + }); + }} /> +

{errors.email}

- + { + setCredentials((prev) => { + return { + ...prev, + password: e.target.value, + }; + }); + }} /> {showPassword ? ( { className="togglePassword_icon" /> )} +

{errors.password}

@@ -113,6 +150,12 @@ const SignUp = () => { type="submit" className="auth_submit" isLoading={loading} + disabled={ + loading || + !credentials.email || + !credentials.password || + !credentials.name + } > Sign Up @@ -153,13 +196,16 @@ const SignUp = () => { onClick={() => { setCredentials((prev) => { return { - ...prev, userType: prev.userType.value === "individual" ? authTypeOptions[1] : authTypeOptions[0], + email: "", + password: "", + name: "", }; }); + setErrors({}); }} >
diff --git a/src/pages/auth/index.scss b/src/pages/auth/index.scss index f6f4984b..7335079a 100644 --- a/src/pages/auth/index.scss +++ b/src/pages/auth/index.scss @@ -73,6 +73,15 @@ flex-direction: column; position: relative; width: 100%; + p { + font-family: var(--outfit); + font-size: 14px; + font-weight: 400; + margin-bottom: 3px; + color: red; + opacity: 80%; + line-height: 1.2; + } } .auth_label { @@ -81,16 +90,19 @@ font-weight: 400; margin-bottom: 3px; color: var(--secondary); + span { + color: red; + } } .auth_input { display: block; width: 100%; padding: 0.375rem 0.75rem; - font-size: 1rem; + font-size: 15px; font-weight: 400; line-height: 1.5; - color: #212529; + color: #000000f8; background-color: #fff; background-clip: padding-box; border: 1px solid #ced4da; diff --git a/src/utils/Toasts.js b/src/utils/Toasts.js index a46b5dda..4aea4bfe 100644 --- a/src/utils/Toasts.js +++ b/src/utils/Toasts.js @@ -15,7 +15,7 @@ export const showSuccessToast = (message) => { toast.success(message, { position: "top-center", - autoClose: 1000, + autoClose: 2000, hideProgressBar: false, closeOnClick: false, pauseOnHover: false, @@ -43,16 +43,17 @@ export const showErrorToast = (message) => { toast.error(message, { position: "top-center", - autoClose: 1000, + autoClose: 2000, hideProgressBar: false, closeOnClick: false, - pauseOnHover: false, + pauseOnHover: true, draggable: false, progress: undefined, closeButton: false, style: { borderRadius: "10px", fontFamily: "Outfit, sans-serif", + width: "fit-content", }, }); }; From 1279e1dce3d6e3b0f8412f002d4ec6ea445ab2d7 Mon Sep 17 00:00:00 2001 From: tamalCodes Date: Fri, 18 Oct 2024 00:25:08 +0530 Subject: [PATCH 3/3] fix: sign in flow setup --- src/hooks/useAuth.js | 2 +- src/pages/auth/SignIn.jsx | 41 ++++++++++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/hooks/useAuth.js b/src/hooks/useAuth.js index c61d1a2a..52b9230f 100644 --- a/src/hooks/useAuth.js +++ b/src/hooks/useAuth.js @@ -38,7 +38,7 @@ export function useAuth(authType) { setloading(true); - const response = await (authType === "login" + const response = await (authType === "signin" ? LoginUser(credentials) : RegisterUser({ ...credentials, diff --git a/src/pages/auth/SignIn.jsx b/src/pages/auth/SignIn.jsx index c0475a1e..72972ef2 100644 --- a/src/pages/auth/SignIn.jsx +++ b/src/pages/auth/SignIn.jsx @@ -16,9 +16,10 @@ const SignIn = () => { email: "", password: "", }); + const [errors, setErrors] = useState({}); // Auth functions - const { authenticateUser, loading } = useAuth("signup"); + const { authenticateUser, loading } = useAuth("signin"); const [showPassword, setshowPassword] = useState(false); // Handlers @@ -44,10 +45,12 @@ const SignIn = () => {

Sign In

+ { - authenticateUser(credentials); + onSubmit={(e) => { + e.preventDefault(); + authenticateUser(credentials, setErrors); }} >
@@ -56,20 +59,44 @@ const SignIn = () => {
- + { + setCredentials((prev) => { + return { + ...prev, + email: e.target.value, + }; + }); + }} /> +

{errors.email}

- + { + setCredentials((prev) => { + return { + ...prev, + password: e.target.value, + }; + }); + }} /> {showPassword ? ( { className="togglePassword_icon" /> )} +

{errors.password}

@@ -93,6 +121,9 @@ const SignIn = () => { type="submit" className="auth_submit" isLoading={loading} + disabled={ + loading || !credentials.email || !credentials.password + } > Sign In