From 562a6001b5ae315c24bdc2ac342ea61d401c8c87 Mon Sep 17 00:00:00 2001 From: Amanuel Abera Date: Tue, 17 Dec 2024 01:03:13 +0300 Subject: [PATCH 1/2] Login, register and logout logic completed --- app/(auth)/login/page.tsx | 111 +++++++++--- app/(auth)/register/page.tsx | 81 +++++++-- app/(profile)/create-post/page.tsx | 80 +++++++++ app/(profile)/dashboard/page.tsx | 114 ++++++++++++ app/(profile)/layout.tsx | 16 ++ app/(profile)/subscribers/page.tsx | 95 ++++++++++ app/api/decoded/route.ts | 21 +++ app/api/logout/route.ts | 11 ++ app/globals.css | 46 ++++- app/layout.tsx | 15 +- components/Header.tsx | 54 +++++- components/SideMenu.tsx | 60 +++++++ context/context.tsx | 49 +++++ middleware.ts | 27 +++ package-lock.json | 98 +++++++--- package.json | 11 +- prisma/dev.db | Bin 0 -> 24576 bytes .../migration.sql | 9 + .../migrations/20241212085138_/migration.sql | 8 + .../migration.sql | 2 + prisma/migrations/migration_lock.toml | 3 + prisma/schema.prisma | 24 +++ public/images/blog1.png | Bin 0 -> 484803 bytes utils/actions.ts | 169 ++++++++++++++++++ utils/blogActions.ts | 0 utils/db.ts | 15 ++ 26 files changed, 1030 insertions(+), 89 deletions(-) create mode 100644 app/(profile)/create-post/page.tsx create mode 100644 app/(profile)/dashboard/page.tsx create mode 100644 app/(profile)/layout.tsx create mode 100644 app/(profile)/subscribers/page.tsx create mode 100644 app/api/decoded/route.ts create mode 100644 app/api/logout/route.ts create mode 100644 components/SideMenu.tsx create mode 100644 context/context.tsx create mode 100644 middleware.ts create mode 100644 prisma/dev.db create mode 100644 prisma/migrations/20241211153138_initial_user_model/migration.sql create mode 100644 prisma/migrations/20241212085138_/migration.sql create mode 100644 prisma/migrations/20241212111426_add_refresh_token/migration.sql create mode 100644 prisma/migrations/migration_lock.toml create mode 100644 prisma/schema.prisma create mode 100644 public/images/blog1.png create mode 100644 utils/actions.ts create mode 100644 utils/blogActions.ts create mode 100644 utils/db.ts diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx index a28346a..dbc937f 100644 --- a/app/(auth)/login/page.tsx +++ b/app/(auth)/login/page.tsx @@ -1,59 +1,112 @@ 'use client' - +import { useRouter } from 'next/navigation'; +import { login } from "@/utils/actions"; import Image from "next/image" import Link from "next/link"; -import { useState } from "react"; +import { useEffect, useState } from "react"; +import { useActionState } from "react"; import { FaEye } from "react-icons/fa"; import { IoCheckbox } from "react-icons/io5"; import { MdCheckBoxOutlineBlank } from "react-icons/md"; +import { startTransition } from "react"; +import { useGlobalContext } from '@/context/context'; + +const initialState: { + message:string | null, errors?: Record, + isLoggedIn?:boolean, + accessToken?: string | null, + userId?: string | null +} = { + message:null, + isLoggedIn:false, + errors:{}, + accessToken: null, + userId: null +} const Login = () => { const [isChecked, setIsChecked] = useState(false); const [togglePassword, setTogglePassword] = useState(false); + const [state, formAction] = useActionState(login, initialState); + const [loading, setLoading] = useState(false); + const {setUserId} = useGlobalContext(); + const router = useRouter(); + + const handleCheckboxToggle = () => { + setIsChecked((prev) => !prev); + }; + + const handleSubmit = async (e:React.FormEvent) => { + e.preventDefault(); + setLoading(true); + const formData = new FormData(e.currentTarget as HTMLFormElement) + startTransition(() => { + formAction(formData); + setLoading(false); + }); + + } + + useEffect(()=>{ + if(state?.isLoggedIn){ + const userId = state?.userId as string + setUserId(userId) + router.push("/") + } + },[state]) - const handleCheckboxToggle = () => { - setIsChecked((prev) => !prev); - }; - - return ( +return (
-
+

Welcome!

Log In your account.

+ {(state?.errors?.root) && <> +
+

+ {state?.errors?.root} +

+
+ }
- + + {state.errors && state.errors.email && ( +

{state.errors.email}

+ )}
- +
setTogglePassword(!togglePassword)}>
+ {state.errors && state.errors.password && ( +

{state.errors.password}

+ )}
- +
- +

Don't have any account? SignUp

diff --git a/app/(auth)/register/page.tsx b/app/(auth)/register/page.tsx index 91323da..48fd32e 100644 --- a/app/(auth)/register/page.tsx +++ b/app/(auth)/register/page.tsx @@ -3,57 +3,105 @@ import Image from "next/image" import Link from "next/link"; import { useState } from "react"; +import { useFormState } from "react-dom"; import { FaEye } from "react-icons/fa"; -import { IoCheckbox } from "react-icons/io5"; -import { MdCheckBoxOutlineBlank } from "react-icons/md"; +import { startTransition } from "react"; + + + +// actions +import { createUser } from "@/utils/actions"; + +const initialState: { message: string | null; errors?: Record } = { + message: null, + errors: {}, +}; const Register = () => { - const [isChecked, setIsChecked] = useState(false); const [togglePassword, setTogglePassword] = useState(false); const [toggleConfirmPassword, setToggleConfirmPasword] = useState(false); + const [loading, setLoading] = useState(false); + const [state,formAction] = useFormState(createUser,initialState) + const handleSubmit = async (e:React.FormEvent) => { + e.preventDefault(); + setLoading(true); + const formData = new FormData(e.currentTarget as HTMLFormElement) + startTransition(() => { + formAction(formData); + setLoading(false); + }); - const handleCheckboxToggle = () => { - setIsChecked((prev) => !prev); - }; + } return (
-
+

Register!

Create a new account.

+ + {(state?.message) && <> +
+

+ {state?.message} +

+ Login here +
+ } + {(state?.errors?.root) && <> +
+

+ {state?.errors?.root} +

+
+ }
- + + {state.errors && state.errors.firstName && ( +

{state.errors.firstName}

+ )}
- + + {state.errors && state.errors.lastName && ( +

{state.errors.lastName}

+ )}
- + + {state.errors && state.errors.email && ( +

{state.errors.email}

+ )}
-
+
- +
setTogglePassword(!togglePassword)}>
+ {state.errors && state.errors.password && ( +

{state.errors.password}

+ )}
- +
setToggleConfirmPasword(!toggleConfirmPassword)}>
+ {state.errors && state.errors.confirmPassword && ( +

{state.errors.confirmPassword}

+ )}
-
+ {/*
-
- +
*/} + +

Do you have an account? SignIn

diff --git a/app/(profile)/create-post/page.tsx b/app/(profile)/create-post/page.tsx new file mode 100644 index 0000000..4045cda --- /dev/null +++ b/app/(profile)/create-post/page.tsx @@ -0,0 +1,80 @@ +import React from 'react' +import { FaImage } from "react-icons/fa"; + +const CreateBlog = () => { + return ( +
+

Create a new blog

+
+

Upload blog cover *

+ +
+ + + {/* {state.errors && state.errors.email && ( +

{state.errors.email}

+ )} */} +
+
+ + + {/* {state.errors && state.errors.email && ( +

{state.errors.email}

+ )} */} +
+
+ +