From a71f5ebf9d93925bd4f6376e16b5934e43ef48f2 Mon Sep 17 00:00:00 2001 From: Hy Nguyen Date: Mon, 15 Jan 2024 01:29:56 -0600 Subject: [PATCH] validate registration --- app/routes/{_auth.login.tsx => login.tsx} | 121 ++++++++++++++++++---- app/routes/test2.tsx | 21 ---- app/tailwind.css | 4 +- 3 files changed, 101 insertions(+), 45 deletions(-) rename app/routes/{_auth.login.tsx => login.tsx} (57%) delete mode 100644 app/routes/test2.tsx diff --git a/app/routes/_auth.login.tsx b/app/routes/login.tsx similarity index 57% rename from app/routes/_auth.login.tsx rename to app/routes/login.tsx index fe4bf64..6e89f6a 100644 --- a/app/routes/_auth.login.tsx +++ b/app/routes/login.tsx @@ -1,6 +1,6 @@ import { Link, Form, useOutletContext, useActionData, redirect } from "@remix-run/react"; import { json } from "@remix-run/node"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { createServerClient, parse, serialize } from '@supabase/ssr'; @@ -16,7 +16,6 @@ import type { ActionFunctionArgs } from "@remix-run/node" export async function action({request}: ActionFunctionArgs) { const formData = await request.formData(); - ////return json({ xxx: formData.get("form_type") }); const cookies = parse(request.headers.get('Cookie') ?? '') const headers = new Headers() @@ -46,20 +45,38 @@ export async function action({request}: ActionFunctionArgs) { // REGISTER else if (formData.get("form_type") === "REGISTER") { + const displayName = String(formData.get("reg_display_name_input")); const email = String(formData.get("reg_email_input")); const password = String(formData.get("reg_password_input")); + const passwordConfirm = String(formData.get("reg_confirm_password_input")); + let errorMessage: string | null = null; - // validate info again on server side - if (!email.includes("@") || !email.includes(".")) { - errorMessage = "Invalid email address."; - } - else if (password.length < 6) { - errorMessage = "Password should be at least 6 characters."; - } - ////// more checks + const validations : [boolean, string][] = [ + [!email.includes("@") || !email.includes("."), "Invalid email address."], + [password.length < 6, "Password should be at least 6 characters."], + [!(/[A-Z]/.test(password)), "Password should contain at least 1 uppercase."], + [!(/[a-z]/.test(password)), "Password should contain at least 1 lowercase."], + [!(/\d/.test(password)), "Password should contain at least 1 number."], + [!(/[!@#$%^&*()_+={}\[\]:;<>,.?~\\|\-]/.test(password)), "Password should contain at least 1 symbol."], + [password !== passwordConfirm, "Confirm password doesn't match."] + ]; + validations.some(vali => { + if (vali[0]){ + errorMessage = vali[1]; + return true; + } else return false; + }); + + // const d = await supabase.auth.getUser() + // console.log(d) + // const s = await supabase.auth.getSession() + // console.log(s) if (errorMessage) return json({ errorMessage }); + const {error} = await supabase.auth.signUp({email, password}); + if (error) json({ errorMessage: "Error: Failed to register." }); + return redirect("/"); } @@ -68,10 +85,20 @@ export async function action({request}: ActionFunctionArgs) { export default function Login(){ + const actionData = useActionData(); - console.log(actionData?.errorMessage); ///////// keeps coming back to undefined + const [errorMessage, setErrorMessage] = useState(null); + + const resetErrorMessage = () => setErrorMessage(null); + // update errorMessage on form submission + useEffect(()=>{ + if (actionData?.errorMessage){ + setErrorMessage(actionData.errorMessage); + } + }, [actionData]); + // switch between login & signup const [isAtLogin, setIsAtLogin] = useState(true); const { supabase } = useOutletContext<{ supabase: SupabaseClient }>() @@ -79,13 +106,33 @@ export default function Login(){ const { data, error } = await supabase.auth.signInWithOAuth({ provider: providerName }); + if (error) alert("Error while logging in.") }; const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [regPassword, setRegPassword] = useState(""); - const [regConfirmPassword, setRegConfirmPassword] = useState(""); + + const [showPassReqs, setShowPassReqs] = useState(false); + const [passReqs, setPassReqs] = useState({ + hasSixChar: false, + hasUppercase: false, + hasLowercase: false, + hasNumber: false, + hasSymbol: false + }); + + useEffect(()=>{ + setPassReqs({ + hasSixChar: regPassword.length >= 6, + hasUppercase: /[A-Z]/.test(regPassword), + hasLowercase: /[a-z]/.test(regPassword), + hasNumber: /\d/.test(regPassword), + hasSymbol: /[!@#$%^&*()_+={}\[\]:;<>,.?~\\|\-]/.test(regPassword) + }); + }, [regPassword]); + const fillDemoAcc = ()=>{ setEmail("hynguyendev@gmail.com"); @@ -113,12 +160,16 @@ export default function Login(){
OR
-
-
-
+

Login

@@ -133,9 +184,7 @@ export default function Login(){ className="text-input" value={password} onChange={(e) => setPassword(e.target.value)}/> - {actionData?.errorMessage ? ( - {actionData?.errorMessage} - ) : null/* ///////// */} + {errorMessage}
@@ -143,23 +192,51 @@ export default function Login(){
-
+

Register

+ + + + {/* Password requirements popup div */} +
+ +
+ + className="text-input" required + onFocus={()=>setShowPassReqs(true)} + onBlur={()=>setShowPassReqs(false)} + onChange={e=>setRegPassword(e.target.value)} + value={regPassword}/> + className="text-input" required /> + {errorMessage}
diff --git a/app/routes/test2.tsx b/app/routes/test2.tsx deleted file mode 100644 index 719d34f..0000000 --- a/app/routes/test2.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import type { ActionFunctionArgs } from "@remix-run/node"; // or cloudflare/deno -import { json } from "@remix-run/node"; // or cloudflare/deno -import { Form, useActionData } from "@remix-run/react"; - -export async function action({ - request, -}: ActionFunctionArgs) { - const body = await request.formData(); - const name = body.get("visitorsName"); - return json({ message: `Hello, ${name}` }); -} - -export default function Invoices() { - const data = useActionData(); - return ( - - - {data ? data.message : "Waiting..."} - - ); -} diff --git a/app/tailwind.css b/app/tailwind.css index a74891e..ee50f53 100644 --- a/app/tailwind.css +++ b/app/tailwind.css @@ -6,7 +6,7 @@ html { --color-1: #fff; /*background*/ --color-2: #000; /*text*/ --color-3: #562a2a; /*button*/ - --color-4: #170d53; /* */ + --color-4: #170d53; /* red error */ --color-5: #0d5641; /**/ } @@ -14,7 +14,7 @@ html.dark { --color-1: #1d1d1d; --color-2: #7fffe1; --color-3: #353535; - --color-4: #147b2d; + --color-4: #d75252; --color-5: #9f9d12; }