From e1cae1d63bea06575267956191e68523d673e762 Mon Sep 17 00:00:00 2001 From: Stanley Tsonev Date: Fri, 20 Jan 2023 09:26:50 -0500 Subject: [PATCH 01/29] auth ui --- components/Auth.tsx | 45 +++++++++++++++++++++++++++++++++++ components/deletemewhen.txt | 1 - components/forms/Login.tsx | 9 +++++++ components/forms/Register.tsx | 9 +++++++ pages/login.tsx | 17 +++++++++++-- styles/Login.module.css | 10 ++++++++ 6 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 components/Auth.tsx delete mode 100644 components/deletemewhen.txt create mode 100644 components/forms/Login.tsx create mode 100644 components/forms/Register.tsx create mode 100644 styles/Login.module.css diff --git a/components/Auth.tsx b/components/Auth.tsx new file mode 100644 index 0000000..a36ac34 --- /dev/null +++ b/components/Auth.tsx @@ -0,0 +1,45 @@ +import { Dispatch, SetStateAction } from 'react'; +import Login from './forms/Login'; +import Register from './forms/Register'; +import { useState } from 'react'; + +export default function Auth({ + type, + setAuthType, +}: { + type: 'login' | 'register'; + setAuthType: Dispatch>; +}) { + const [serverError, setServerError] = useState(null); + return ( +
+
{serverError ?? serverError}
+ {type == 'login' ? ( + + ) : ( + + )} + {type == 'login' ? ( +
+ Not registed?{' '} + setAuthType('register')} + > + Sign up now + +
+ ) : ( +
+ Have an account?{' '} + setAuthType('login')} + > + Login here + +
+ )} +
+ ); +} diff --git a/components/deletemewhen.txt b/components/deletemewhen.txt deleted file mode 100644 index d8f0cc0..0000000 --- a/components/deletemewhen.txt +++ /dev/null @@ -1 +0,0 @@ -delete me when you add and commit another file to this directory. This file should only exist if the directory is empty in order to maintain directory/project structure \ No newline at end of file diff --git a/components/forms/Login.tsx b/components/forms/Login.tsx new file mode 100644 index 0000000..63eb0b7 --- /dev/null +++ b/components/forms/Login.tsx @@ -0,0 +1,9 @@ +import { Dispatch, SetStateAction } from 'react'; + +export default function Login({ + setServerError, +}: { + setServerError: Dispatch>; +}) { + return
Login
; +} diff --git a/components/forms/Register.tsx b/components/forms/Register.tsx new file mode 100644 index 0000000..742f6d8 --- /dev/null +++ b/components/forms/Register.tsx @@ -0,0 +1,9 @@ +import { Dispatch, SetStateAction } from 'react'; + +export default function Register({ + setServerError, +}: { + setServerError: Dispatch>; +}) { + return
Register
; +} diff --git a/pages/login.tsx b/pages/login.tsx index 4d8814d..0ee6cdf 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -1,10 +1,14 @@ import { useUser, useSupabaseClient } from '@supabase/auth-helpers-react'; import Head from 'next/head'; +import styles from '@/styles/Login.module.css'; +import Auth from '@/components/Auth'; +import { useState } from 'react'; export default function Login() { const user = useUser(); const supabase = useSupabaseClient(); - // + const [authType, setAuthType] = useState<'login' | 'register'>('login'); + return ( <> @@ -13,7 +17,16 @@ export default function Login() { - login page + +
+
+
+ +
+
+
); } diff --git a/styles/Login.module.css b/styles/Login.module.css new file mode 100644 index 0000000..e967964 --- /dev/null +++ b/styles/Login.module.css @@ -0,0 +1,10 @@ +@media only screen and (min-width: 640px) { + .loginMD { + display: grid; + grid-template-columns: + repeat(3, minmax(16px, 1fr)) repeat(6, minmax(0, 192px)) + repeat(3, minmax(16px, 1fr)); + + grid-template-rows: minmax(48px, 1fr) minmax(768px, 1fr) minmax(48px, 1fr); + } +} From 5f5340ae72796662bd3296fcd5711d4b9f5ff889 Mon Sep 17 00:00:00 2001 From: Stanley Tsonev Date: Fri, 20 Jan 2023 18:53:23 -0500 Subject: [PATCH 02/29] layout spacing, registeration --- components/Auth.tsx | 50 ++++++++++--------- components/forms/Login.tsx | 6 ++- components/forms/Register.tsx | 92 ++++++++++++++++++++++++++++++++++- pages/login.tsx | 15 +++++- 4 files changed, 137 insertions(+), 26 deletions(-) diff --git a/components/Auth.tsx b/components/Auth.tsx index a36ac34..be5504d 100644 --- a/components/Auth.tsx +++ b/components/Auth.tsx @@ -12,32 +12,38 @@ export default function Auth({ }) { const [serverError, setServerError] = useState(null); return ( -
+
{serverError ?? serverError}
+
+ {type == 'login' ? ( + + ) : ( + + )} +
{type == 'login' ? ( - - ) : ( - - )} - {type == 'login' ? ( -
- Not registed?{' '} - setAuthType('register')} - > - Sign up now - +
+
+ Not registed?{' '} + setAuthType('register')} + > + Sign up now + +
) : ( -
- Have an account?{' '} - setAuthType('login')} - > - Login here - +
+
+ Have an account?{' '} + setAuthType('login')} + > + Login here + +
)}
diff --git a/components/forms/Login.tsx b/components/forms/Login.tsx index 63eb0b7..4bf8cbe 100644 --- a/components/forms/Login.tsx +++ b/components/forms/Login.tsx @@ -5,5 +5,9 @@ export default function Login({ }: { setServerError: Dispatch>; }) { - return
Login
; + return ( +
+
Login
+
+ ); } diff --git a/components/forms/Register.tsx b/components/forms/Register.tsx index 742f6d8..6aa4403 100644 --- a/components/forms/Register.tsx +++ b/components/forms/Register.tsx @@ -5,5 +5,95 @@ export default function Register({ }: { setServerError: Dispatch>; }) { - return
Register
; + return ( +
+
+ +
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+ ); } diff --git a/pages/login.tsx b/pages/login.tsx index 0ee6cdf..a29fe2b 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -3,6 +3,7 @@ import Head from 'next/head'; import styles from '@/styles/Login.module.css'; import Auth from '@/components/Auth'; import { useState } from 'react'; +import Image from 'next/image'; export default function Login() { const user = useUser(); @@ -20,9 +21,19 @@ export default function Login() {
-
+
+
+ Next.js Logo +
From d81b6884157eaba0b06a2f71b8a97b1f1be98ec5 Mon Sep 17 00:00:00 2001 From: Stanley Tsonev Date: Fri, 20 Jan 2023 21:01:47 -0500 Subject: [PATCH 03/29] mobile auth css --- components/Auth.tsx | 10 +++---- components/forms/Login.tsx | 53 +++++++++++++++++++++++++++++++++-- components/forms/Register.tsx | 38 ++++++++++++++----------- 3 files changed, 77 insertions(+), 24 deletions(-) diff --git a/components/Auth.tsx b/components/Auth.tsx index be5504d..e02dc9a 100644 --- a/components/Auth.tsx +++ b/components/Auth.tsx @@ -23,10 +23,10 @@ export default function Auth({
{type == 'login' ? (
-
- Not registed?{' '} +
+ Not registered?{' '} setAuthType('register')} > Sign up now @@ -35,10 +35,10 @@ export default function Auth({
) : (
-
+
Have an account?{' '} setAuthType('login')} > Login here diff --git a/components/forms/Login.tsx b/components/forms/Login.tsx index 4bf8cbe..08ce9e9 100644 --- a/components/forms/Login.tsx +++ b/components/forms/Login.tsx @@ -6,8 +6,57 @@ export default function Login({ setServerError: Dispatch>; }) { return ( -
-
Login
+ +
+ +
+ +
+ +
+ +
+ +
); } diff --git a/components/forms/Register.tsx b/components/forms/Register.tsx index 6aa4403..c8c0121 100644 --- a/components/forms/Register.tsx +++ b/components/forms/Register.tsx @@ -16,14 +16,15 @@ export default function Register({ self-start text-base font-normal - text-white - border border-solid border-blueGrey-600 + placeholder:text-white + placeholder:opacity-60 + border-2 border-solid border-blueGrey-600 rounded-2xl transition ease-in-out - focus:outline-blueGrey-50 + focus:outline-frost-50 m-0 focus:outline-none bg-inherit flex-1" - placeholder="Enter Username*" + placeholder="Enter Username" >
@@ -35,14 +36,15 @@ export default function Register({ self-start text-base font-normal - text-white - border border-solid border-blueGrey-600 + placeholder:text-white + placeholder:opacity-60 + border-2 border-solid border-blueGrey-600 rounded-2xl transition ease-in-out - focus:outline-blueGrey-50 + focus:outline-frost-50 m-0 focus:outline-none bg-inherit flex-1" - placeholder="Enter Email*" + placeholder="Enter Email" >
@@ -55,14 +57,15 @@ export default function Register({ self-start text-base font-normal - text-white - border border-solid border-blueGrey-600 + placeholder:text-white + placeholder:opacity-60 + border-2 border-solid border-white rounded-2xl transition ease-in-out - focus:outline-blueGrey-50 + focus:outline-frost-50 m-0 focus:outline-none bg-inherit flex-1" - placeholder="Enter password*" + placeholder="Enter password" >
@@ -75,20 +78,21 @@ export default function Register({ self-start text-base font-normal - text-white - border border-solid border-blueGrey-600 + placeholder:text-white + placeholder:opacity-60 + border-2 border-white rounded-2xl transition ease-in-out - focus:outline-blueGrey-50 + focus:outline-frost-50 m-0 focus:outline-none bg-inherit flex-1" - placeholder="Confirm password*" + placeholder="Confirm password" >
)}
diff --git a/pages/login.tsx b/pages/login.tsx index e818a1a..1c6502b 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -1,4 +1,3 @@ -import { useUser, useSupabaseClient } from '@supabase/auth-helpers-react'; import Head from 'next/head'; import styles from '@/styles/Login.module.css'; import Auth from '@/components/Auth'; @@ -7,8 +6,6 @@ import Image from 'next/image'; import Yeti from '../public/Yeti.png'; export default function Login() { - const user = useUser(); - const supabase = useSupabaseClient(); const [authType, setAuthType] = useState<'login' | 'register'>('login'); return ( From b05e56e3ffd453e9c58bde228d25e580499d4393 Mon Sep 17 00:00:00 2001 From: Stanley Tsonev Date: Sat, 21 Jan 2023 16:16:39 -0500 Subject: [PATCH 09/29] eslint --- components/forms/Login.tsx | 1 - components/forms/Register.tsx | 2 +- pages/login.tsx | 11 ++--------- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/components/forms/Login.tsx b/components/forms/Login.tsx index 49de0a5..ed18525 100644 --- a/components/forms/Login.tsx +++ b/components/forms/Login.tsx @@ -138,4 +138,3 @@ export default function Login({ ); } -// bg-gradient-to-r from-frost-300 to-frost-500 diff --git a/components/forms/Register.tsx b/components/forms/Register.tsx index 6c831a2..5a34788 100644 --- a/components/forms/Register.tsx +++ b/components/forms/Register.tsx @@ -3,7 +3,7 @@ import styles from '@/styles/Login.module.css'; import { createUserSchema, CreateUserInput } from '@/types/client/user'; import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; -import { useUser, useSupabaseClient } from '@supabase/auth-helpers-react'; +import { useSupabaseClient } from '@supabase/auth-helpers-react'; import { Database } from '@/types/database.supabase'; export default function Register({ diff --git a/pages/login.tsx b/pages/login.tsx index 1c6502b..67b0ffb 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -27,13 +27,7 @@ export default function Login() {
FrostCord
- Yeti + Yeti
FrostCord Logo Date: Sat, 21 Jan 2023 17:03:09 -0500 Subject: [PATCH 10/29] validation text --- types/client/user.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/client/user.ts b/types/client/user.ts index 1b4299c..6f6db67 100644 --- a/types/client/user.ts +++ b/types/client/user.ts @@ -7,7 +7,7 @@ export const createUserSchema = object({ email: z.string().min(1, { message: 'Email is required' }), password: string({ required_error: 'Password is required', - }).min(6, 'Password must be at least 3 characters'), + }).min(6, 'Password must be at least 6 characters'), passwordConfirmation: z .string() .min(1, { message: 'Password confirmation is required' }), From bbfde7adbd1b15e9510afe29b461656464f142be Mon Sep 17 00:00:00 2001 From: Stan-l-e-y <85900924+Stan-l-e-y@users.noreply.github.com> Date: Sat, 21 Jan 2023 17:04:59 -0500 Subject: [PATCH 11/29] Update components/forms/Login.tsx Co-authored-by: multimokia --- components/forms/Login.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/forms/Login.tsx b/components/forms/Login.tsx index ed18525..a834a25 100644 --- a/components/forms/Login.tsx +++ b/components/forms/Login.tsx @@ -122,7 +122,7 @@ export default function Login({ > {errors.password && (

- {errors.password?.message} + {errors.password.message}

)}
From aba7d41ef454c91b774dbdc3f868ca1aa31c11ae Mon Sep 17 00:00:00 2001 From: Stan-l-e-y <85900924+Stan-l-e-y@users.noreply.github.com> Date: Sat, 21 Jan 2023 17:06:00 -0500 Subject: [PATCH 12/29] Apply suggestions from code review Co-authored-by: multimokia --- components/forms/Login.tsx | 2 +- components/forms/Register.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/forms/Login.tsx b/components/forms/Login.tsx index a834a25..7011b15 100644 --- a/components/forms/Login.tsx +++ b/components/forms/Login.tsx @@ -80,7 +80,7 @@ export default function Login({ > {errors.email && (

- {errors.email?.message} + {errors.email.message}

)}
diff --git a/components/forms/Register.tsx b/components/forms/Register.tsx index 5a34788..b86997f 100644 --- a/components/forms/Register.tsx +++ b/components/forms/Register.tsx @@ -84,7 +84,7 @@ export default function Register({ > {errors.username && ( - {errors.username?.message} + {errors.username.message} )}
@@ -125,7 +125,7 @@ export default function Register({ > {errors.email && (

- {errors.email?.message} + {errors.email.message}

)}
@@ -166,7 +166,7 @@ export default function Register({ > {errors.password && (

- {errors.password?.message} + {errors.password.message}

)} From ea8fd0cc347a55e470e4de086d1c285ac0642db3 Mon Sep 17 00:00:00 2001 From: Stanley Tsonev Date: Sun, 22 Jan 2023 08:09:12 -0500 Subject: [PATCH 13/29] refactor styles --- components/forms/Login.tsx | 45 +++++++-------------- components/forms/Register.tsx | 75 +++++++++-------------------------- components/forms/Styles.ts | 18 +++++++++ 3 files changed, 51 insertions(+), 87 deletions(-) create mode 100644 components/forms/Styles.ts diff --git a/components/forms/Login.tsx b/components/forms/Login.tsx index ed18525..f24668f 100644 --- a/components/forms/Login.tsx +++ b/components/forms/Login.tsx @@ -9,6 +9,7 @@ import { zodResolver } from '@hookform/resolvers/zod'; import { useRouter } from 'next/router'; import { useSupabaseClient } from '@supabase/auth-helpers-react'; import { Database } from '@/types/database.supabase'; +import { Input } from './Styles'; export default function Login({ setServerError, @@ -60,21 +61,7 @@ export default function Login({ @@ -103,20 +90,7 @@ export default function Login({ @@ -129,7 +103,18 @@ export default function Login({
@@ -106,20 +94,7 @@ export default function Register({ @@ -147,20 +122,7 @@ export default function Register({ @@ -192,20 +154,7 @@ export default function Register({ @@ -218,7 +167,19 @@ export default function Register({
From d03992bce84ed7aaf5667e49ea8adff195f7668c Mon Sep 17 00:00:00 2001 From: Stan-l-e-y Date: Tue, 24 Jan 2023 00:14:38 +0200 Subject: [PATCH 18/29] reset password part 1 (frontend) --- components/Auth.tsx | 36 +++++++++++++++++++++++++----- components/forms/Login.tsx | 7 ++++-- components/forms/PasswordReset.tsx | 4 ++++ components/forms/Register.tsx | 4 ++-- pages/login.tsx | 2 +- pages/passwordreset.tsx | 18 +++++++++++++++ styles/Login.module.css | 2 +- 7 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 components/forms/PasswordReset.tsx create mode 100644 pages/passwordreset.tsx diff --git a/components/Auth.tsx b/components/Auth.tsx index e3920ed..0aed548 100644 --- a/components/Auth.tsx +++ b/components/Auth.tsx @@ -1,30 +1,54 @@ import { Dispatch, SetStateAction } from 'react'; import Login from './forms/Login'; import Register from './forms/Register'; +import PasswordReset from './forms/PasswordReset'; import { useState } from 'react'; +import { useSupabaseClient } from '@supabase/auth-helpers-react'; +import { Database } from '@/types/database.supabase'; export default function Auth({ type, setAuthType, }: { - type: 'login' | 'register'; - setAuthType: Dispatch>; + type: 'login' | 'register' | 'resetPassword'; + setAuthType: Dispatch>; }) { const [serverError, setServerError] = useState(null); + const [resetPassword, setResetPassword] = useState(false); + + const supabase = useSupabaseClient(); + + async function handleReset() { + //TODO: get email from field + const { data, error } = await supabase.auth.resetPasswordForEmail('', { + redirectTo: 'http://localhost:3000/passwordreset', + }) + + } + + return (

{serverError ?? serverError}

-
+
+ {/* TODO: make this render either 1 of 3 states */} + {/* {type == 'resetPassword' ? : type == 'login' ? ( + + ) : ( + + )} */} + + {type == 'login' ? ( - + ) : ( )}
{type == 'login' ? ( -
+
Not registered?{' '}
) : ( -
+
Have an account?{' '} >; + setServerError: Dispatch>, + setAuthType: Dispatch>; }) { const router = useRouter(); const supabase = useSupabaseClient(); @@ -100,6 +102,7 @@ export default function Login({

)}
+ setAuthType('resetPassword')} className='text-sm mt-3 text-frost-800 font-bold hover:text-frost-600 hover:cursor-pointer'>Forgot password?
+} \ No newline at end of file diff --git a/components/forms/Register.tsx b/components/forms/Register.tsx index 7135fd1..141b9b3 100644 --- a/components/forms/Register.tsx +++ b/components/forms/Register.tsx @@ -12,7 +12,7 @@ export default function Register({ setAuthType, }: { setServerError: Dispatch>; - setAuthType: Dispatch>; + setAuthType: Dispatch>; }) { const supabase = useSupabaseClient(); const { @@ -46,7 +46,7 @@ export default function Register({ return (
diff --git a/pages/login.tsx b/pages/login.tsx index 67b0ffb..2a7e81d 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -6,7 +6,7 @@ import Image from 'next/image'; import Yeti from '../public/Yeti.png'; export default function Login() { - const [authType, setAuthType] = useState<'login' | 'register'>('login'); + const [authType, setAuthType] = useState<'login' | 'register' | 'resetPassword'>('login'); return ( <> diff --git a/pages/passwordreset.tsx b/pages/passwordreset.tsx new file mode 100644 index 0000000..6d3a4c2 --- /dev/null +++ b/pages/passwordreset.tsx @@ -0,0 +1,18 @@ +import { useEffect } from "react" +import { useSupabaseClient, useUser } from '@supabase/auth-helpers-react'; + +export default function Passwordreset() { + + const user = useUser() + + useEffect(() => { + console.log(user) + },[]) + + return ( +
+
password reset
+ +
+ ) +} \ No newline at end of file diff --git a/styles/Login.module.css b/styles/Login.module.css index 31a37f1..c59635e 100644 --- a/styles/Login.module.css +++ b/styles/Login.module.css @@ -5,7 +5,7 @@ repeat(3, minmax(16px, 1fr)) repeat(6, minmax(0, 192px)) repeat(3, minmax(16px, 1fr)); - grid-template-rows: minmax(48px, 1fr) minmax(768px, 1fr) minmax(48px, 1fr); + grid-template-rows: minmax(48px, 1fr) minmax(640px, 1fr) minmax(48px, 1fr); } .rightSide { box-shadow: inset 0 5px 0 hsl(194, 81%, 70%); From d8cc2d358c4da4f8884115786fb143130b7e5a25 Mon Sep 17 00:00:00 2001 From: Stan-l-e-y Date: Tue, 24 Jan 2023 00:17:37 +0200 Subject: [PATCH 19/29] eslint --- components/Auth.tsx | 4 ++-- components/forms/PasswordReset.tsx | 2 +- pages/passwordreset.tsx | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/components/Auth.tsx b/components/Auth.tsx index 0aed548..a0e6579 100644 --- a/components/Auth.tsx +++ b/components/Auth.tsx @@ -22,7 +22,7 @@ export default function Auth({ //TODO: get email from field const { data, error } = await supabase.auth.resetPasswordForEmail('', { redirectTo: 'http://localhost:3000/passwordreset', - }) + }); } @@ -34,7 +34,7 @@ export default function Auth({

{/* TODO: make this render either 1 of 3 states */} - {/* {type == 'resetPassword' ? : type == 'login' ? ( + {/* {type == 'resetPassword' ? : type == 'login' ? ( ) : ( diff --git a/components/forms/PasswordReset.tsx b/components/forms/PasswordReset.tsx index 76cb473..1930c5a 100644 --- a/components/forms/PasswordReset.tsx +++ b/components/forms/PasswordReset.tsx @@ -1,4 +1,4 @@ export default function PasswordReset() { - return
reset password
+ return
reset password
; } \ No newline at end of file diff --git a/pages/passwordreset.tsx b/pages/passwordreset.tsx index 6d3a4c2..a92c3ea 100644 --- a/pages/passwordreset.tsx +++ b/pages/passwordreset.tsx @@ -1,18 +1,18 @@ -import { useEffect } from "react" +import { useEffect } from 'react'; import { useSupabaseClient, useUser } from '@supabase/auth-helpers-react'; export default function Passwordreset() { - const user = useUser() + const user = useUser(); useEffect(() => { - console.log(user) - },[]) + console.log(user); + },[user]); return (
-
password reset
+
password reset
- ) + ); } \ No newline at end of file From ebb163fbab5ff767cd3540559ccb00a7f175d64a Mon Sep 17 00:00:00 2001 From: Stanley Tsonev Date: Tue, 24 Jan 2023 12:55:26 -0500 Subject: [PATCH 20/29] ui changes --- components/Auth.tsx | 9 +++------ components/forms/Login.tsx | 19 +++++++++++++------ components/forms/Register.tsx | 2 ++ components/forms/Styles.ts | 4 ++-- pages/login.tsx | 13 +++++++++---- styles/Login.module.css | 31 ++++++++++++++++++++++--------- 6 files changed, 51 insertions(+), 27 deletions(-) diff --git a/components/Auth.tsx b/components/Auth.tsx index a0e6579..7a84066 100644 --- a/components/Auth.tsx +++ b/components/Auth.tsx @@ -23,10 +23,8 @@ export default function Auth({ const { data, error } = await supabase.auth.resetPasswordForEmail('', { redirectTo: 'http://localhost:3000/passwordreset', }); - } - return (

@@ -40,15 +38,14 @@ export default function Auth({ )} */} - {type == 'login' ? ( - + ) : ( )}

{type == 'login' ? ( -
+
Not registered?{' '}
) : ( -
+
Have an account?{' '} >, + setServerError: Dispatch>; setAuthType: Dispatch>; }) { const router = useRouter(); @@ -46,7 +46,7 @@ export default function Login({ }; return ( -
+
-
+
)}
- setAuthType('resetPassword')} className='text-sm mt-3 text-frost-800 font-bold hover:text-frost-600 hover:cursor-pointer'>Forgot password? + setAuthType('resetPassword')} + className="text-sm mt-3 text-frost-800 font-bold hover:text-frost-600 hover:cursor-pointer" + > + Forgot password? +
+
+ + );; +} diff --git a/components/forms/Register.tsx b/components/forms/Register.tsx index c455c1f..236bbe7 100644 --- a/components/forms/Register.tsx +++ b/components/forms/Register.tsx @@ -1,5 +1,5 @@ import { Dispatch, SetStateAction } from 'react'; -import styles from '@/styles/Login.module.css'; +import styles from '@/styles/Auth.module.css'; import { createUserSchema, CreateUserInput } from '@/types/client/user'; import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; diff --git a/pages/login.tsx b/pages/login.tsx index 535c2db..a847d33 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -1,5 +1,5 @@ import Head from 'next/head'; -import styles from '@/styles/Login.module.css'; +import styles from '@/styles/Auth.module.css'; import Auth from '@/components/Auth'; import { useState } from 'react'; import Image from 'next/image'; diff --git a/pages/passwordreset.tsx b/pages/passwordreset.tsx index a92c3ea..e301849 100644 --- a/pages/passwordreset.tsx +++ b/pages/passwordreset.tsx @@ -4,10 +4,7 @@ import { useSupabaseClient, useUser } from '@supabase/auth-helpers-react'; export default function Passwordreset() { const user = useUser(); - - useEffect(() => { - console.log(user); - },[user]); + //TODO: redirect user to this page after clicking link in email return (
@@ -15,4 +12,4 @@ export default function Passwordreset() {
); -} \ No newline at end of file +} diff --git a/styles/Login.module.css b/styles/Auth.module.css similarity index 87% rename from styles/Login.module.css rename to styles/Auth.module.css index bb9c932..ecca554 100644 --- a/styles/Login.module.css +++ b/styles/Auth.module.css @@ -45,8 +45,8 @@ } .input { - box-shadow: inset 0 5px 4px hsla(0, 0%, 0%, 0.1), - 0 4px 1px hsla(0, 0%, 90%, 0.15); + box-shadow: inset 0 5px 2px hsla(0, 0%, 0%, 0.1), + 0 3px 2px hsla(0, 0%, 90%, 0.15); } .frostCord { @@ -56,5 +56,5 @@ .logo { box-shadow: inset 0 2px 1px hsl(194, 71%, 50%), - 0 20px 25px hsla(0, 0%, 100%, 0.649); + 0 20px 25px hsla(0, 0%, 100%, 0.649), 0 15px 25px hsla(0, 3%, 46%, 0.649); } diff --git a/types/client/passwordRecovery.ts b/types/client/passwordRecovery.ts new file mode 100644 index 0000000..b639014 --- /dev/null +++ b/types/client/passwordRecovery.ts @@ -0,0 +1,7 @@ +import { object, TypeOf, z } from 'zod'; + +export const createPasswordRecoverySchema = object({ + email: z.string().min(1, { message: 'Email is required' }), +}); + +export type CreatePasswordInputRecovery = TypeOf; From eb8074475183a335ac1206c603c8c3c791b52d04 Mon Sep 17 00:00:00 2001 From: Stanley Tsonev Date: Wed, 25 Jan 2023 20:44:21 -0500 Subject: [PATCH 23/29] toast msgs, reset password api --- components/Auth.tsx | 10 ---------- components/forms/Login.tsx | 2 +- components/forms/PasswordReset.tsx | 24 +++++++++++++++++++++--- components/forms/Register.tsx | 2 +- middleware.ts | 10 ++++++++++ package.json | 1 + pages/_app.tsx | 3 +++ pages/index.tsx | 16 ++++++++++++++++ pages/passwordreset.tsx | 1 + styles/Auth.module.css | 9 +++++---- 10 files changed, 59 insertions(+), 19 deletions(-) diff --git a/components/Auth.tsx b/components/Auth.tsx index 716c096..fc5afda 100644 --- a/components/Auth.tsx +++ b/components/Auth.tsx @@ -14,16 +14,6 @@ export default function Auth({ setAuthType: Dispatch>; }) { const [serverError, setServerError] = useState(null); - const [resetPassword, setResetPassword] = useState(false); - - const supabase = useSupabaseClient(); - - async function handleReset() { - //TODO: get email from field - const { data, error } = await supabase.auth.resetPasswordForEmail('', { - redirectTo: 'http://localhost:3000/passwordreset', - }); - } function renderAuth(type: 'login' | 'register' | 'resetPassword') { switch (type) { diff --git a/components/forms/Login.tsx b/components/forms/Login.tsx index 9345c41..a141065 100644 --- a/components/forms/Login.tsx +++ b/components/forms/Login.tsx @@ -115,7 +115,7 @@ export default function Login({ ${styles.button} bg-frost-600 hover:bg-frost-700 - active:shadow-lg + active:shadow-sm active:bg-frost-800 font-bold py-2 px-4 diff --git a/components/forms/PasswordReset.tsx b/components/forms/PasswordReset.tsx index d17200c..15b7c24 100644 --- a/components/forms/PasswordReset.tsx +++ b/components/forms/PasswordReset.tsx @@ -6,6 +6,7 @@ import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { useSupabaseClient } from '@supabase/auth-helpers-react'; import { Database } from '@/types/database.supabase'; +import { toast } from 'react-toastify'; export default function PasswordReset({ setServerError, @@ -25,9 +26,26 @@ export default function PasswordReset({ resolver: zodResolver(createPasswordRecoverySchema), }); + const onSubmit = async (formData: CreatePasswordInputRecovery) => { - //TODO: send password recovery email, set auth type to login and - //display toast message with "A password recovery email has been set" + + const { data, error } = await supabase.auth.resetPasswordForEmail(formData.email, { + redirectTo: 'http://localhost:3000/passwordreset', + }); + + if (error) { + setServerError(error.message); + setTimeout(() => { + setServerError(null); + }, 7000); + } + if (data && !error) { + toast.success(`An email has been sent to ${formData.email}`, { + position: 'top-center', + autoClose: 3000 + }); + setAuthType('login'); + } }; return ( @@ -71,7 +89,7 @@ export default function PasswordReset({ ${styles.button} bg-frost-600 hover:bg-frost-700 - active:shadow-lg + active:shadow-sm active:bg-frost-800 font-bold py-2 px-4 diff --git a/components/forms/Register.tsx b/components/forms/Register.tsx index 236bbe7..c4239e8 100644 --- a/components/forms/Register.tsx +++ b/components/forms/Register.tsx @@ -170,7 +170,7 @@ export default function Register({ className={` bg-frost-600 hover:bg-frost-700 - active:shadow-lg + active:shadow-sm active:bg-frost-800 font-bold py-2 diff --git a/middleware.ts b/middleware.ts index 6409118..02d86a0 100644 --- a/middleware.ts +++ b/middleware.ts @@ -8,11 +8,21 @@ export async function middleware(req: NextRequest) { // Create authenticated Supabase Client. const supabase = createMiddlewareSupabaseClient({ req, res }); // Check if we have a session + + supabase.auth.onAuthStateChange(async (event, session) => { + console.log(event); + // console.log(session); + if (event == 'PASSWORD_RECOVERY') { + console.log('passreco'); + return res; + } + }); const { data: { session }, } = await supabase.auth.getSession(); const redirectUrl = req.nextUrl.clone(); + console.log(redirectUrl); // Check auth condition if (session?.user) { // Authentication successful, forward request to protected route. diff --git a/package.json b/package.json index bd7697a..2ca86f4 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "react": "18.2.0", "react-dom": "18.2.0", "react-hook-form": "^7.42.1", + "react-toastify": "^9.1.1", "swr": "^2.0.1", "typescript": "4.9.4", "zod": "^3.20.2" diff --git a/pages/_app.tsx b/pages/_app.tsx index a660947..cc10c26 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -5,6 +5,8 @@ import { AppProps } from 'next/app'; import { useState } from 'react'; import { Source_Sans_3 } from '@next/font/google'; import { Database } from '@/types/database.supabase'; +import { ToastContainer } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; const sourceSans3 = Source_Sans_3({ subsets: ['latin'] }); @@ -23,6 +25,7 @@ function App({ supabaseClient={supabaseClient} initialSession={pageProps.initialSession} > +
diff --git a/pages/index.tsx b/pages/index.tsx index 4f8c5c7..6ed3e69 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -5,6 +5,8 @@ import styles from '@/styles/Home.module.css'; import { Auth, ThemeSupa } from '@supabase/auth-ui-react'; import { useUser, useSupabaseClient } from '@supabase/auth-helpers-react'; import { useRouter } from 'next/router'; +import { useEffect } from 'react'; +import { toast } from 'react-toastify'; const inter = Inter({ subsets: ['latin'] }); @@ -18,6 +20,20 @@ export default function Home() { if (error) console.log(error); router.push('/login'); }; + + useEffect(() => { + supabase.auth.onAuthStateChange(async (event, session) => { + console.log(event); + console.log(session); + if (event == 'PASSWORD_RECOVERY') { + console.log('passreco'); + toast.success('passwordrec', { + position: 'top-center', + autoClose: 3000 + }); + } + }); + }); return ( <> diff --git a/pages/passwordreset.tsx b/pages/passwordreset.tsx index e301849..f3206e2 100644 --- a/pages/passwordreset.tsx +++ b/pages/passwordreset.tsx @@ -4,6 +4,7 @@ import { useSupabaseClient, useUser } from '@supabase/auth-helpers-react'; export default function Passwordreset() { const user = useUser(); + const supabase = useSupabaseClient(); //TODO: redirect user to this page after clicking link in email return ( diff --git a/styles/Auth.module.css b/styles/Auth.module.css index ecca554..279fece 100644 --- a/styles/Auth.module.css +++ b/styles/Auth.module.css @@ -12,10 +12,11 @@ grid-template-rows: minmax(8px, 1fr) minmax(768px, 1fr) minmax(32px, 1fr); } .rightSide { - box-shadow: inset 0 2px 1px hsl(194, 61%, 47%), - 0 4px 8px hsla(0, 0%, 99%, 0.549); + box-shadow: inset 0 5px 3px hsl(194, 61%, 47%), + 0 4px 5px hsla(0, 0%, 99%, 0.549); } } +/* inset 0 2px 1px hsl(194, 61%, 47%) */ .mainContainer { filter: drop-shadow(0 2px 10px rgba(51, 50, 50, 0.904)) @@ -41,12 +42,12 @@ } .button { - box-shadow: inset 0 2px 1px hsl(194, 71%, 50%), 0 2px 3px hsla(0, 0%, 0%, 0.2); + box-shadow: inset 0 2px 1px hsl(194, 71%, 50%), 0 3px 2px hsla(0, 0%, 0%, 0.2), 3px 10px 7px hsla(0, 2%, 50%, 0.2); } .input { box-shadow: inset 0 5px 2px hsla(0, 0%, 0%, 0.1), - 0 3px 2px hsla(0, 0%, 90%, 0.15); + 1px 5px 4px hsla(0, 1%, 90%, 0.15),inset 0 4px 1px hsla(0, 0%, 0%, 0.1),inset -4px 0 4px hsla(0, 0%, 0%, 0.1); } .frostCord { From bbfa92d7dd23cf59bb7dce9c6e4184c40a642a4e Mon Sep 17 00:00:00 2001 From: Stanley Tsonev Date: Fri, 27 Jan 2023 08:37:57 -0500 Subject: [PATCH 24/29] password reset part pain --- components/forms/Login.tsx | 1 + components/forms/PasswordReset.tsx | 4 +- components/forms/Register.tsx | 1 + components/forms/Styles.ts | 6 +- components/forms/UpdatePassword.tsx | 135 ++++++++++++++++++++++++++++ context/EventContext.tsx | 39 ++++++++ lib/supabase-browser.ts | 6 ++ middleware.ts | 11 +-- pages/_app.tsx | 39 +++++--- pages/index.tsx | 15 ---- pages/login.tsx | 2 +- pages/passwordreset.tsx | 87 ++++++++++++++++-- styles/Auth.module.css | 20 ++++- types/client/updatePassword.ts | 15 ++++ 14 files changed, 332 insertions(+), 49 deletions(-) create mode 100644 components/forms/UpdatePassword.tsx create mode 100644 context/EventContext.tsx create mode 100644 lib/supabase-browser.ts create mode 100644 types/client/updatePassword.ts diff --git a/components/forms/Login.tsx b/components/forms/Login.tsx index a141065..d2152a3 100644 --- a/components/forms/Login.tsx +++ b/components/forms/Login.tsx @@ -29,6 +29,7 @@ export default function Login({ }); const onSubmit = async (formData: CreateSessionInput) => { + //TODO: disable login button const { data, error } = await supabase.auth.signInWithPassword({ email: formData.email, password: formData.password, diff --git a/components/forms/PasswordReset.tsx b/components/forms/PasswordReset.tsx index 15b7c24..4263a3e 100644 --- a/components/forms/PasswordReset.tsx +++ b/components/forms/PasswordReset.tsx @@ -28,7 +28,7 @@ export default function PasswordReset({ const onSubmit = async (formData: CreatePasswordInputRecovery) => { - + //TODO: disable resetpass button, loading spinner? const { data, error } = await supabase.auth.resetPasswordForEmail(formData.email, { redirectTo: 'http://localhost:3000/passwordreset', }); @@ -105,5 +105,5 @@ export default function PasswordReset({
- );; + ); } diff --git a/components/forms/Register.tsx b/components/forms/Register.tsx index c4239e8..90ad0e5 100644 --- a/components/forms/Register.tsx +++ b/components/forms/Register.tsx @@ -24,6 +24,7 @@ export default function Register({ }); const onSubmit = async (formData: CreateUserInput) => { + //TODO: disable register button const { data, error } = await supabase.auth.signUp({ email: formData.email, password: formData.password, diff --git a/components/forms/Styles.ts b/components/forms/Styles.ts index d98491e..b987fa1 100644 --- a/components/forms/Styles.ts +++ b/components/forms/Styles.ts @@ -6,13 +6,11 @@ text-base font-normal placeholder:text-white placeholder:opacity-60 -border -border-solid -border-grey-400 rounded-2xl transition ease-in-out focus:outline-frost-50 -m-0 focus:outline-none +m-0 +focus:outline-none bg-inherit flex-1`; diff --git a/components/forms/UpdatePassword.tsx b/components/forms/UpdatePassword.tsx new file mode 100644 index 0000000..51007fe --- /dev/null +++ b/components/forms/UpdatePassword.tsx @@ -0,0 +1,135 @@ +import { Input } from './Styles'; +import styles from '@/styles/Auth.module.css'; +import { createUpdatePasswordSchema, CreateUpdatePasswordInput } from '@/types/client/updatePassword'; +import { useForm } from 'react-hook-form'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { Database } from '@/types/database.supabase'; +import { useSupabaseClient } from '@supabase/auth-helpers-react'; +import { Dispatch, SetStateAction } from 'react'; +import { toast } from 'react-toastify'; +import { useRouter } from 'next/router'; + +export default function UpdatePassword({setServerError} : {setServerError: Dispatch>;}) { + const router = useRouter(); + const supabase = useSupabaseClient(); + + const { + register, + handleSubmit, + formState: { errors }, + } = useForm({ + resolver: zodResolver(createUpdatePasswordSchema), + }); + + const onSubmit = async (formData: CreateUpdatePasswordInput) => { + //TODO: disable updatePass button, loading spinner? + const { data, error } = await supabase.auth.updateUser({ + password: formData.password + }); + + if (error) { + setServerError(error.message); + setTimeout(() => { + setServerError(null); + }, 7000); + } + if (data && !error) { + toast.success('Password successfully updated', { + position: 'top-center', + autoClose: 3000 + }); + router.push('/'); + } + }; + + + return ( +
+ +
+
+ + + +
+ + {errors.password && ( +

+ {errors.password.message} +

+ )} +
+ +
+
+ + + +
+ + {errors.passwordConfirmation && ( +

+ {errors.passwordConfirmation.message} +

+ )} +
+ +
+ +
+
+ ); +} diff --git a/context/EventContext.tsx b/context/EventContext.tsx new file mode 100644 index 0000000..8d45871 --- /dev/null +++ b/context/EventContext.tsx @@ -0,0 +1,39 @@ +import { + createContext, + SetStateAction, + useContext, + useState, + Dispatch, +} from 'react'; + +type PWRecoveryEventContextValue = { + pwRecoveryEvent: boolean; + setPWRecoveryEvent: Dispatch>; +}; + +export const PWRecoveryEventCtxDefaultVal: PWRecoveryEventContextValue = { + pwRecoveryEvent: false, + setPWRecoveryEvent: (state) => {}, +}; + +export const PWRecoveryEventContext = createContext(PWRecoveryEventCtxDefaultVal); + +export function EventProvider({ children }: { children: React.ReactNode }) { + const [pwRecoveryEvent, setPWRecoveryEvent] = useState(PWRecoveryEventCtxDefaultVal.pwRecoveryEvent); + + return ( + + {children} + + ); +} + +// export function usePWRecoveryEvent() { +// const { pwRecoveryEvent } = useContext(PWRecoveryEventContext); +// return pwRecoveryEvent; +// } + +// export function usePWRecoveryEventSetter() { +// const { setPWRecoveryEvent } = useContext(PWRecoveryEventContext); +// return setPWRecoveryEvent; +// } diff --git a/lib/supabase-browser.ts b/lib/supabase-browser.ts new file mode 100644 index 0000000..b7e3e9e --- /dev/null +++ b/lib/supabase-browser.ts @@ -0,0 +1,6 @@ +import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs'; +import { Database } from '@/types/database.supabase'; + +const supabase = createBrowserSupabaseClient(); + +export default supabase; diff --git a/middleware.ts b/middleware.ts index 02d86a0..0a11553 100644 --- a/middleware.ts +++ b/middleware.ts @@ -5,18 +5,13 @@ import type { NextRequest } from 'next/server'; export async function middleware(req: NextRequest) { // We need to create a response and hand it to the supabase client to be able to modify the response headers. const res = NextResponse.next(); + return res; + // Forward req if User tries to reset password, authorization will happen on the client + if (req.nextUrl.pathname == '/passwordreset') return res; // Create authenticated Supabase Client. const supabase = createMiddlewareSupabaseClient({ req, res }); // Check if we have a session - supabase.auth.onAuthStateChange(async (event, session) => { - console.log(event); - // console.log(session); - if (event == 'PASSWORD_RECOVERY') { - console.log('passreco'); - return res; - } - }); const { data: { session }, } = await supabase.auth.getSession(); diff --git a/pages/_app.tsx b/pages/_app.tsx index cc10c26..b79598e 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -2,11 +2,16 @@ import '@/styles/globals.css'; import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs'; import { SessionContextProvider, Session } from '@supabase/auth-helpers-react'; import { AppProps } from 'next/app'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { Source_Sans_3 } from '@next/font/google'; -import { Database } from '@/types/database.supabase'; import { ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; +import { toast } from 'react-toastify'; +import { EventProvider, PWRecoveryEventContext, PWRecoveryEventCtxDefaultVal } from 'context/EventContext'; +// import supabase from '@/lib/supabase-browser'; + +import { Database } from '@/types/database.supabase'; + const sourceSans3 = Source_Sans_3({ subsets: ['latin'] }); @@ -16,19 +21,31 @@ function App({ }: AppProps<{ initialSession: Session; }>) { - const [supabaseClient] = useState(() => - createBrowserSupabaseClient() - ); - + const [pwRecoveryEvent, setPWRecoveryEvent] = useState(PWRecoveryEventCtxDefaultVal.pwRecoveryEvent); + //tsonevstanley@gmail.com + //prob just gonna have to remove the event check fully + const supabase = createBrowserSupabaseClient(); + useEffect(() => { + supabase.auth.onAuthStateChange(async (event, session) => { + if (event == 'PASSWORD_RECOVERY') { + toast('yerer'); + setPWRecoveryEvent(true); + } + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + },[]); + return ( - -
- -
+ + +
+ +
+
); } diff --git a/pages/index.tsx b/pages/index.tsx index 6ed3e69..58cd82a 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -5,8 +5,6 @@ import styles from '@/styles/Home.module.css'; import { Auth, ThemeSupa } from '@supabase/auth-ui-react'; import { useUser, useSupabaseClient } from '@supabase/auth-helpers-react'; import { useRouter } from 'next/router'; -import { useEffect } from 'react'; -import { toast } from 'react-toastify'; const inter = Inter({ subsets: ['latin'] }); @@ -21,19 +19,6 @@ export default function Home() { router.push('/login'); }; - useEffect(() => { - supabase.auth.onAuthStateChange(async (event, session) => { - console.log(event); - console.log(session); - if (event == 'PASSWORD_RECOVERY') { - console.log('passreco'); - toast.success('passwordrec', { - position: 'top-center', - autoClose: 3000 - }); - } - }); - }); return ( <> diff --git a/pages/login.tsx b/pages/login.tsx index a847d33..db26573 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -21,7 +21,7 @@ export default function Login() {
(null); + + const isAuth = user && pwRecoveryEvent; + + + //conditionally render this form if user exists AND event is password recovery, our middleware ill not catch this route since + //the access token is return in the URL fragment + + + if (!isAuth) { + return ( +
+
+
+
+
Unauthorized
+ + +
return to login
+
+
+
+ ); + } return ( -
-
password reset
- -
+
+
+
+
{user ?
+
Update Password
+

+ {serverError ?? serverError} +

+ +
:

no user

}
+
+
+
); } diff --git a/styles/Auth.module.css b/styles/Auth.module.css index 279fece..1885f04 100644 --- a/styles/Auth.module.css +++ b/styles/Auth.module.css @@ -1,5 +1,5 @@ @media only screen and (min-width: 1280px) { - .loginMD { + .authMD { display: grid; grid-template-columns: repeat(3, minmax(16px, 1fr)) minmax(0, 192px) minmax(0, 192px) minmax( @@ -16,7 +16,22 @@ 0 4px 5px hsla(0, 0%, 99%, 0.549); } } -/* inset 0 2px 1px hsl(194, 61%, 47%) */ + +/* 5-8 */ +@media only screen and (min-width: 1280px) { + .resetPWMD { + display: grid; + grid-template-columns: + repeat(3, minmax(16px, 1fr)) minmax(0, 192px) minmax(0, 192px) minmax( + 0, + 128px + ) + minmax(0, 128px) minmax(0, 192px) minmax(0, 128px) + repeat(3, minmax(16px, 1fr)); + + grid-template-rows: minmax(8px, 1fr) minmax(640px, 1fr) minmax(32px, 1fr); + } +} .mainContainer { filter: drop-shadow(0 2px 10px rgba(51, 50, 50, 0.904)) @@ -25,6 +40,7 @@ .icon { padding: 8px; + margin-left: -1px; position: absolute; box-sizing: border-box; top: 50%; diff --git a/types/client/updatePassword.ts b/types/client/updatePassword.ts new file mode 100644 index 0000000..6985ec7 --- /dev/null +++ b/types/client/updatePassword.ts @@ -0,0 +1,15 @@ +import { object, TypeOf, z, string } from 'zod'; + +export const createUpdatePasswordSchema = object({ + password: string({ + required_error: 'Password is required', + }).min(6, 'Password must be at least 6 characters'), + passwordConfirmation: z + .string() + .min(1, { message: 'Password confirmation is required' }), +}).refine((data) => data.password === data.passwordConfirmation, { + message: 'Passwords do not match', + path: ['passwordConfirmation'], +}); + +export type CreateUpdatePasswordInput = TypeOf; From 2ee094aa28ad9b78473ad6ee24ffbb441de80521 Mon Sep 17 00:00:00 2001 From: Stanley Tsonev Date: Sat, 28 Jan 2023 07:53:01 -0500 Subject: [PATCH 25/29] password reset flow --- components/Auth.tsx | 46 +++++++++++---------- components/forms/Login.tsx | 35 ++++------------ components/forms/PasswordReset.tsx | 20 +++------ components/forms/Register.tsx | 63 +++++------------------------ components/forms/UpdatePassword.tsx | 33 ++++----------- components/icons/EmailIcon.tsx | 14 +++++++ components/icons/PasswordIcon.tsx | 14 +++++++ components/icons/UsernameIcon.tsx | 14 +++++++ context/EventContext.tsx | 39 ------------------ lib/supabase-browser.ts | 6 --- middleware.ts | 4 +- pages/_app.tsx | 31 +++----------- pages/passwordreset.tsx | 51 ++++++++++------------- styles/Auth.module.css | 2 +- 14 files changed, 128 insertions(+), 244 deletions(-) create mode 100644 components/icons/EmailIcon.tsx create mode 100644 components/icons/PasswordIcon.tsx create mode 100644 components/icons/UsernameIcon.tsx delete mode 100644 context/EventContext.tsx delete mode 100644 lib/supabase-browser.ts diff --git a/components/Auth.tsx b/components/Auth.tsx index fc5afda..c4b9f21 100644 --- a/components/Auth.tsx +++ b/components/Auth.tsx @@ -3,8 +3,6 @@ import Login from './forms/Login'; import Register from './forms/Register'; import PasswordReset from './forms/PasswordReset'; import { useState } from 'react'; -import { useSupabaseClient } from '@supabase/auth-helpers-react'; -import { Database } from '@/types/database.supabase'; export default function Auth({ type, @@ -15,32 +13,13 @@ export default function Auth({ }) { const [serverError, setServerError] = useState(null); - function renderAuth(type: 'login' | 'register' | 'resetPassword') { - switch (type) { - case 'login': - return ( - - ); - case 'register': - return ( - - ); - case 'resetPassword': - return ; - default: - return ( - - ); - } - } - return (

{serverError ?? serverError}

- {renderAuth(type)} + {renderAuth(type, setServerError, setAuthType)}
{type == 'login' ? (
@@ -70,3 +49,26 @@ export default function Auth({
); } + +function renderAuth( + type: 'login' | 'register' | 'resetPassword', + setServerError: Dispatch>, + setAuthType: Dispatch> +) { + switch (type) { + case 'login': + return ( + + ); + case 'register': + return ( + + ); + case 'resetPassword': + return ; + default: + return ( + + ); + } +} diff --git a/components/forms/Login.tsx b/components/forms/Login.tsx index d2152a3..c8f6676 100644 --- a/components/forms/Login.tsx +++ b/components/forms/Login.tsx @@ -10,6 +10,8 @@ import { useRouter } from 'next/router'; import { useSupabaseClient } from '@supabase/auth-helpers-react'; import { Database } from '@/types/database.supabase'; import { Input } from './Styles'; +import EmailIcon from '../icons/EmailIcon'; +import PasswordIcon from '../icons/PasswordIcon'; export default function Login({ setServerError, @@ -23,13 +25,13 @@ export default function Login({ const { register, handleSubmit, - formState: { errors }, + formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(createSessionSchema), + mode: 'onChange' }); const onSubmit = async (formData: CreateSessionInput) => { - //TODO: disable login button const { data, error } = await supabase.auth.signInWithPassword({ email: formData.email, password: formData.password, @@ -49,18 +51,7 @@ export default function Login({
- - - +
- - - +
- Login diff --git a/components/forms/PasswordReset.tsx b/components/forms/PasswordReset.tsx index 4263a3e..369523a 100644 --- a/components/forms/PasswordReset.tsx +++ b/components/forms/PasswordReset.tsx @@ -7,6 +7,7 @@ import { zodResolver } from '@hookform/resolvers/zod'; import { useSupabaseClient } from '@supabase/auth-helpers-react'; import { Database } from '@/types/database.supabase'; import { toast } from 'react-toastify'; +import EmailIcon from '../icons/EmailIcon'; export default function PasswordReset({ setServerError, @@ -21,14 +22,14 @@ export default function PasswordReset({ const { register, handleSubmit, - formState: { errors }, + formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(createPasswordRecoverySchema), + mode: 'onChange' }); const onSubmit = async (formData: CreatePasswordInputRecovery) => { - //TODO: disable resetpass button, loading spinner? const { data, error } = await supabase.auth.resetPasswordForEmail(formData.email, { redirectTo: 'http://localhost:3000/passwordreset', }); @@ -57,18 +58,7 @@ export default function PasswordReset({
- - - +
Send Email diff --git a/components/forms/Register.tsx b/components/forms/Register.tsx index 90ad0e5..757968a 100644 --- a/components/forms/Register.tsx +++ b/components/forms/Register.tsx @@ -6,6 +6,9 @@ import { useForm } from 'react-hook-form'; import { useSupabaseClient } from '@supabase/auth-helpers-react'; import { Database } from '@/types/database.supabase'; import { Input } from './Styles'; +import EmailIcon from '../icons/EmailIcon'; +import PasswordIcon from '../icons/PasswordIcon'; +import UsernameIcon from '../icons/UsernameIcon'; export default function Register({ setServerError, @@ -18,13 +21,13 @@ export default function Register({ const { register, handleSubmit, - formState: { errors }, + formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(createUserSchema), + mode: 'onChange' }); const onSubmit = async (formData: CreateUserInput) => { - //TODO: disable register button const { data, error } = await supabase.auth.signUp({ email: formData.email, password: formData.password, @@ -52,18 +55,7 @@ export default function Register({ >
- - - +
)}
-
- - - +
- - - +
- - - +
)}
-
diff --git a/components/forms/UpdatePassword.tsx b/components/forms/UpdatePassword.tsx index 51007fe..666ecfb 100644 --- a/components/forms/UpdatePassword.tsx +++ b/components/forms/UpdatePassword.tsx @@ -8,6 +8,7 @@ import { useSupabaseClient } from '@supabase/auth-helpers-react'; import { Dispatch, SetStateAction } from 'react'; import { toast } from 'react-toastify'; import { useRouter } from 'next/router'; +import PasswordIcon from '../icons/PasswordIcon'; export default function UpdatePassword({setServerError} : {setServerError: Dispatch>;}) { const router = useRouter(); @@ -16,13 +17,13 @@ export default function UpdatePassword({setServerError} : {setServerError: Dispa const { register, handleSubmit, - formState: { errors }, + formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(createUpdatePasswordSchema), + mode: 'onChange' }); const onSubmit = async (formData: CreateUpdatePasswordInput) => { - //TODO: disable updatePass button, loading spinner? const { data, error } = await supabase.auth.updateUser({ password: formData.password }); @@ -50,18 +51,7 @@ export default function UpdatePassword({setServerError} : {setServerError: Dispa
- - - +
- - - +
Submit diff --git a/components/icons/EmailIcon.tsx b/components/icons/EmailIcon.tsx new file mode 100644 index 0000000..ba1f99d --- /dev/null +++ b/components/icons/EmailIcon.tsx @@ -0,0 +1,14 @@ +export default function EmailIcon() { + return ( + + ); +} diff --git a/components/icons/PasswordIcon.tsx b/components/icons/PasswordIcon.tsx new file mode 100644 index 0000000..6d02a6f --- /dev/null +++ b/components/icons/PasswordIcon.tsx @@ -0,0 +1,14 @@ +export default function PasswordIcon() { + return ( + + ); +} diff --git a/components/icons/UsernameIcon.tsx b/components/icons/UsernameIcon.tsx new file mode 100644 index 0000000..7f32a8c --- /dev/null +++ b/components/icons/UsernameIcon.tsx @@ -0,0 +1,14 @@ +export default function UsernameIcon() { + return ( + + ); +} diff --git a/context/EventContext.tsx b/context/EventContext.tsx deleted file mode 100644 index 8d45871..0000000 --- a/context/EventContext.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { - createContext, - SetStateAction, - useContext, - useState, - Dispatch, -} from 'react'; - -type PWRecoveryEventContextValue = { - pwRecoveryEvent: boolean; - setPWRecoveryEvent: Dispatch>; -}; - -export const PWRecoveryEventCtxDefaultVal: PWRecoveryEventContextValue = { - pwRecoveryEvent: false, - setPWRecoveryEvent: (state) => {}, -}; - -export const PWRecoveryEventContext = createContext(PWRecoveryEventCtxDefaultVal); - -export function EventProvider({ children }: { children: React.ReactNode }) { - const [pwRecoveryEvent, setPWRecoveryEvent] = useState(PWRecoveryEventCtxDefaultVal.pwRecoveryEvent); - - return ( - - {children} - - ); -} - -// export function usePWRecoveryEvent() { -// const { pwRecoveryEvent } = useContext(PWRecoveryEventContext); -// return pwRecoveryEvent; -// } - -// export function usePWRecoveryEventSetter() { -// const { setPWRecoveryEvent } = useContext(PWRecoveryEventContext); -// return setPWRecoveryEvent; -// } diff --git a/lib/supabase-browser.ts b/lib/supabase-browser.ts deleted file mode 100644 index b7e3e9e..0000000 --- a/lib/supabase-browser.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs'; -import { Database } from '@/types/database.supabase'; - -const supabase = createBrowserSupabaseClient(); - -export default supabase; diff --git a/middleware.ts b/middleware.ts index 0a11553..075e114 100644 --- a/middleware.ts +++ b/middleware.ts @@ -5,7 +5,6 @@ import type { NextRequest } from 'next/server'; export async function middleware(req: NextRequest) { // We need to create a response and hand it to the supabase client to be able to modify the response headers. const res = NextResponse.next(); - return res; // Forward req if User tries to reset password, authorization will happen on the client if (req.nextUrl.pathname == '/passwordreset') return res; // Create authenticated Supabase Client. @@ -17,7 +16,7 @@ export async function middleware(req: NextRequest) { } = await supabase.auth.getSession(); const redirectUrl = req.nextUrl.clone(); - console.log(redirectUrl); + // Check auth condition if (session?.user) { // Authentication successful, forward request to protected route. @@ -27,7 +26,6 @@ export async function middleware(req: NextRequest) { redirectUrl.pathname = '/'; return NextResponse.redirect(redirectUrl); } - return res; } diff --git a/pages/_app.tsx b/pages/_app.tsx index b79598e..64e095d 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -2,17 +2,11 @@ import '@/styles/globals.css'; import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs'; import { SessionContextProvider, Session } from '@supabase/auth-helpers-react'; import { AppProps } from 'next/app'; -import { useEffect, useState } from 'react'; import { Source_Sans_3 } from '@next/font/google'; import { ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; -import { toast } from 'react-toastify'; -import { EventProvider, PWRecoveryEventContext, PWRecoveryEventCtxDefaultVal } from 'context/EventContext'; -// import supabase from '@/lib/supabase-browser'; - import { Database } from '@/types/database.supabase'; - const sourceSans3 = Source_Sans_3({ subsets: ['latin'] }); function App({ @@ -21,31 +15,18 @@ function App({ }: AppProps<{ initialSession: Session; }>) { - const [pwRecoveryEvent, setPWRecoveryEvent] = useState(PWRecoveryEventCtxDefaultVal.pwRecoveryEvent); - //tsonevstanley@gmail.com - //prob just gonna have to remove the event check fully + const supabase = createBrowserSupabaseClient(); - useEffect(() => { - supabase.auth.onAuthStateChange(async (event, session) => { - if (event == 'PASSWORD_RECOVERY') { - toast('yerer'); - setPWRecoveryEvent(true); - } - }); - // eslint-disable-next-line react-hooks/exhaustive-deps - },[]); - + return ( - - -
- -
-
+ +
+ +
); } diff --git a/pages/passwordreset.tsx b/pages/passwordreset.tsx index 5e29fd2..ff29510 100644 --- a/pages/passwordreset.tsx +++ b/pages/passwordreset.tsx @@ -1,27 +1,16 @@ -import { useContext, useEffect, useState } from 'react'; -import { useSupabaseClient, useUser } from '@supabase/auth-helpers-react'; -import { toast } from 'react-toastify'; +import { useState } from 'react'; +import { useUser } from '@supabase/auth-helpers-react'; import styles from '@/styles/Auth.module.css'; import UpdatePassword from '@/components/forms/UpdatePassword'; -import { PWRecoveryEventContext } from 'context/EventContext'; +import { useRouter } from 'next/router'; -export default function Passwordreset() { +export default function Passwordreset() { const user = useUser(); - const supabase = useSupabaseClient(); - - const {pwRecoveryEvent, setPWRecoveryEvent} = useContext(PWRecoveryEventContext); - + const router = useRouter(); const [serverError, setServerError] = useState(null); - const isAuth = user && pwRecoveryEvent; - - - //conditionally render this form if user exists AND event is password recovery, our middleware ill not catch this route since - //the access token is return in the URL fragment - - - if (!isAuth) { + if (!user) { return (
-
-
Unauthorized
- - -
return to login
+
+
+
Unauthorized
+
return to router.push('/login')}>login
+
+
@@ -77,13 +68,15 @@ export default function Passwordreset() { xl:rounded-3xl `} > -
{user ?
-
Update Password
-

- {serverError ?? serverError} -

- -
:

no user

}
+
+
+
Update Password
+

+ {serverError ?? serverError} +

+ +
+
diff --git a/styles/Auth.module.css b/styles/Auth.module.css index 1885f04..9249554 100644 --- a/styles/Auth.module.css +++ b/styles/Auth.module.css @@ -9,7 +9,7 @@ minmax(0, 128px) minmax(0, 192px) minmax(0, 128px) repeat(3, minmax(16px, 1fr)); - grid-template-rows: minmax(8px, 1fr) minmax(768px, 1fr) minmax(32px, 1fr); + grid-template-rows: minmax(8px, 1fr) minmax(640px, 768px) minmax(32px, 1fr); } .rightSide { box-shadow: inset 0 5px 3px hsl(194, 61%, 47%), From 2043c3a60368dab57177855e7d5dc0fe8a43fbf2 Mon Sep 17 00:00:00 2001 From: Stanley Tsonev Date: Sun, 29 Jan 2023 08:15:39 -0500 Subject: [PATCH 26/29] style changes --- pages/login.tsx | 2 +- public/bubbles.svg | 12 ++++++++++++ styles/Auth.module.css | 33 ++++++++++++++++++++++++++------- 3 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 public/bubbles.svg diff --git a/pages/login.tsx b/pages/login.tsx index db26573..0073779 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -35,7 +35,7 @@ export default function Login() {
+ + + bubbles + Created with Sketch. + + + + + + + diff --git a/styles/Auth.module.css b/styles/Auth.module.css index 9249554..7932bf9 100644 --- a/styles/Auth.module.css +++ b/styles/Auth.module.css @@ -11,13 +11,30 @@ grid-template-rows: minmax(8px, 1fr) minmax(640px, 768px) minmax(32px, 1fr); } + .rightSide { - box-shadow: inset 0 5px 3px hsl(194, 61%, 47%), - 0 4px 5px hsla(0, 0%, 99%, 0.549); + background-image: linear-gradient( + to top left, + hsla(197, 79%, 74%, 10%), + hsla(197, 81%, 39%, 10%) + ), + linear-gradient( + to top, + hsla(197, 79%, 74%, 100%), + hsla(197, 81%, 39%, 70%) + ), + url('../public/bubbles.svg'), + linear-gradient( + to top, + hsla(197, 79%, 74%, 90%), + hsla(197, 81%, 39%, 100%) + ); + box-shadow: inset 0 10px 4px hsla(197, 81%, 44%, 30%), + 17px 17px 4px hsla(0, 0%, 18%, 0.749), + 18px 25px 20px hsla(0, 0%, 21%, 0.749); } } -/* 5-8 */ @media only screen and (min-width: 1280px) { .resetPWMD { display: grid; @@ -58,20 +75,22 @@ } .button { - box-shadow: inset 0 2px 1px hsl(194, 71%, 50%), 0 3px 2px hsla(0, 0%, 0%, 0.2), 3px 10px 7px hsla(0, 2%, 50%, 0.2); + box-shadow: inset 0 4px 3px hsl(194, 71%, 48%), + 2px 4px 2px hsla(0, 0%, 0%, 0.2), 3px 10px 7px hsla(0, 1%, 28%, 0.2); } .input { box-shadow: inset 0 5px 2px hsla(0, 0%, 0%, 0.1), - 1px 5px 4px hsla(0, 1%, 90%, 0.15),inset 0 4px 1px hsla(0, 0%, 0%, 0.1),inset -4px 0 4px hsla(0, 0%, 0%, 0.1); + 1px 5px 4px hsla(0, 1%, 90%, 0.15), inset 0 4px 1px hsla(0, 0%, 0%, 0.1), + inset -4px 0 4px hsla(0, 0%, 0%, 0.1); } .frostCord { - filter: drop-shadow(0 2px 6px rgba(237, 232, 232, 0.904)) + filter: drop-shadow(0 2px 3px rgba(237, 232, 232, 0.904)) drop-shadow(0 10px 8px rgba(227, 214, 214, 0.08)); } .logo { box-shadow: inset 0 2px 1px hsl(194, 71%, 50%), - 0 20px 25px hsla(0, 0%, 100%, 0.649), 0 15px 25px hsla(0, 3%, 46%, 0.649); + 2px 10px 8px hsla(0, 0%, 16%, 0.649), 5px 20px 20px hsla(0, 0%, 16%, 0.649); } From e145494965942e21094df46eb2fc9cdf0e151b14 Mon Sep 17 00:00:00 2001 From: Stanley Tsonev Date: Sun, 29 Jan 2023 08:20:45 -0500 Subject: [PATCH 27/29] placeholder opacity --- components/forms/Styles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/forms/Styles.ts b/components/forms/Styles.ts index b987fa1..a358299 100644 --- a/components/forms/Styles.ts +++ b/components/forms/Styles.ts @@ -5,7 +5,7 @@ self-start text-base font-normal placeholder:text-white -placeholder:opacity-60 +placeholder:opacity-80 rounded-2xl transition ease-in-out From 5420fb542fbac7ab0e42eb97a695a0c603492384 Mon Sep 17 00:00:00 2001 From: Stanley Tsonev Date: Mon, 30 Jan 2023 09:24:32 -0500 Subject: [PATCH 28/29] style changes --- pages/login.tsx | 4 ++-- pages/passwordreset.tsx | 6 +++--- styles/Auth.module.css | 31 ++++++++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/pages/login.tsx b/pages/login.tsx index 0073779..34e8d30 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -19,12 +19,12 @@ export default function Login() { -
+
diff --git a/pages/passwordreset.tsx b/pages/passwordreset.tsx index ff29510..d583a1c 100644 --- a/pages/passwordreset.tsx +++ b/pages/passwordreset.tsx @@ -18,7 +18,7 @@ export default function Passwordreset() { >
-
Unauthorized
-
return to Unauthorized
+
return to router.push('/login')}>login
diff --git a/styles/Auth.module.css b/styles/Auth.module.css index 7932bf9..825f897 100644 --- a/styles/Auth.module.css +++ b/styles/Auth.module.css @@ -48,11 +48,36 @@ grid-template-rows: minmax(8px, 1fr) minmax(640px, 1fr) minmax(32px, 1fr); } + + .mainContainer { + filter: drop-shadow(0 2px 10px rgba(51, 50, 50, 0.904)) + drop-shadow(0 10px 8px rgba(75, 73, 73, 0.08)); + background-color: #354045; + } } -.mainContainer { - filter: drop-shadow(0 2px 10px rgba(51, 50, 50, 0.904)) - drop-shadow(0 10px 8px rgba(75, 73, 73, 0.08)); +@media only screen and (max-width: 1280px) { + .mainBackground { + background-image: linear-gradient( + to top left, + hsla(197, 79%, 74%, 10%), + hsla(197, 81%, 39%, 10%) + ), + linear-gradient( + to top, + hsla(197, 79%, 74%, 100%), + hsla(197, 81%, 39%, 70%) + ), + url('../public/bubbles.svg'), + linear-gradient( + to top, + hsla(197, 79%, 74%, 90%), + hsla(197, 81%, 39%, 100%) + ); + box-shadow: inset 0 10px 4px hsla(197, 81%, 44%, 30%), + 17px 17px 4px hsla(0, 0%, 18%, 0.749), + 18px 25px 20px hsla(0, 0%, 21%, 0.749); + } } .icon { From d14763e302b2daf6e73c029ec5b35d70cc1b4423 Mon Sep 17 00:00:00 2001 From: Stanley Tsonev Date: Mon, 30 Jan 2023 09:34:51 -0500 Subject: [PATCH 29/29] more style changes --- styles/Auth.module.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/styles/Auth.module.css b/styles/Auth.module.css index 825f897..b147c80 100644 --- a/styles/Auth.module.css +++ b/styles/Auth.module.css @@ -31,7 +31,8 @@ ); box-shadow: inset 0 10px 4px hsla(197, 81%, 44%, 30%), 17px 17px 4px hsla(0, 0%, 18%, 0.749), - 18px 25px 20px hsla(0, 0%, 21%, 0.749); + 18px 25px 20px hsla(0, 0%, 21%, 0.749), + -12px 1px 4px hsla(0, 0%, 21%, 0.749); } } @@ -106,7 +107,7 @@ .input { box-shadow: inset 0 5px 2px hsla(0, 0%, 0%, 0.1), - 1px 5px 4px hsla(0, 1%, 90%, 0.15), inset 0 4px 1px hsla(0, 0%, 0%, 0.1), + 1px 5px 4px hsla(0, 1%, 90%, 0.18), inset 0 4px 1px hsla(0, 0%, 0%, 0.1), inset -4px 0 4px hsla(0, 0%, 0%, 0.1); }