From 92842c29bb02065042fad3b1b4474e90c5dffe53 Mon Sep 17 00:00:00 2001 From: arraysid Date: Tue, 27 May 2025 03:35:41 +0700 Subject: [PATCH] feat: add signin --- .../(auth)/signin/_actions/signin-action.ts | 24 +++++++ .../(auth)/signin/_components/signin-form.tsx | 69 +++++++++++++++++++ .../(auth)/signin/_hooks/use-form-signin.ts | 16 +++++ .../(auth)/signin/_hooks/use-post-signin.ts | 18 +++++ .../(auth)/signin/_http/fetch-post-signin.ts | 24 +++++++ .../signin/_validation/signin-validation.ts | 18 +++++ apps/landing/src/app/(auth)/signin/page.tsx | 37 +++++++++- 7 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 apps/landing/src/app/(auth)/signin/_actions/signin-action.ts create mode 100644 apps/landing/src/app/(auth)/signin/_components/signin-form.tsx create mode 100644 apps/landing/src/app/(auth)/signin/_hooks/use-form-signin.ts create mode 100644 apps/landing/src/app/(auth)/signin/_hooks/use-post-signin.ts create mode 100644 apps/landing/src/app/(auth)/signin/_http/fetch-post-signin.ts create mode 100644 apps/landing/src/app/(auth)/signin/_validation/signin-validation.ts diff --git a/apps/landing/src/app/(auth)/signin/_actions/signin-action.ts b/apps/landing/src/app/(auth)/signin/_actions/signin-action.ts new file mode 100644 index 0000000..0a42b5f --- /dev/null +++ b/apps/landing/src/app/(auth)/signin/_actions/signin-action.ts @@ -0,0 +1,24 @@ +'use server'; + +import { setAccessToken, setRefreshToken } from '@/lib/cookies'; +import { fetchPostSignin } from '../_http/fetch-post-signin'; +import { + type SignInValidationType, + signInValidationSchema, +} from '../_validation/signin-validation'; + +export async function SigninAction(request: SignInValidationType) { + console.log(request); + + const validRequest = signInValidationSchema.parse(request); + + const { data } = await fetchPostSignin(validRequest); + + const accessToken = data.token.access_token; + const refreshToken = data.token.refresh_token; + + await setAccessToken(accessToken); + await setRefreshToken(refreshToken); + + return data; +} diff --git a/apps/landing/src/app/(auth)/signin/_components/signin-form.tsx b/apps/landing/src/app/(auth)/signin/_components/signin-form.tsx new file mode 100644 index 0000000..3b08022 --- /dev/null +++ b/apps/landing/src/app/(auth)/signin/_components/signin-form.tsx @@ -0,0 +1,69 @@ +'use client'; + +import { + Button, + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, + Input, +} from '@components'; +import { LuLoader } from 'react-icons/lu'; +import { useFormSignin } from '../_hooks/use-form-signin'; +import { usePostSignin } from '../_hooks/use-post-signin'; +import { type SignInValidationType } from '../_validation/signin-validation'; + +export function SigninForm() { + const form = useFormSignin(); + const { mutate, isPending, error } = usePostSignin(form); + + const onSubmit = (values: SignInValidationType) => { + mutate(values); + }; + + return ( +
+ + {error && ( +
+ {(error as Error).message} +
+ )} + + ( + + Email + + + + + + )} + /> + + ( + + Password + + + + + + )} + /> + + + + + ); +} diff --git a/apps/landing/src/app/(auth)/signin/_hooks/use-form-signin.ts b/apps/landing/src/app/(auth)/signin/_hooks/use-form-signin.ts new file mode 100644 index 0000000..76af058 --- /dev/null +++ b/apps/landing/src/app/(auth)/signin/_hooks/use-form-signin.ts @@ -0,0 +1,16 @@ +import { zodResolver } from '@hookform/resolvers/zod'; +import { useForm } from 'react-hook-form'; +import { + signInValidationSchema, + type SignInValidationType, +} from '../_validation/signin-validation'; + +export function useFormSignin() { + return useForm({ + resolver: zodResolver(signInValidationSchema), + defaultValues: { + email: '', + password: '', + }, + }); +} diff --git a/apps/landing/src/app/(auth)/signin/_hooks/use-post-signin.ts b/apps/landing/src/app/(auth)/signin/_hooks/use-post-signin.ts new file mode 100644 index 0000000..217b35e --- /dev/null +++ b/apps/landing/src/app/(auth)/signin/_hooks/use-post-signin.ts @@ -0,0 +1,18 @@ +import { useMutation } from '@tanstack/react-query'; +import { useRouter } from 'next/navigation'; +import { SigninAction } from '../_actions/signin-action'; +import { useFormSignin } from './use-form-signin'; + +export function usePostSignin(form: ReturnType) { + const router = useRouter(); + + return useMutation({ + mutationFn: SigninAction, + onSuccess: () => { + router.push('/'); + }, + onError: () => { + form.resetField('password'); + }, + }); +} diff --git a/apps/landing/src/app/(auth)/signin/_http/fetch-post-signin.ts b/apps/landing/src/app/(auth)/signin/_http/fetch-post-signin.ts new file mode 100644 index 0000000..52fbab2 --- /dev/null +++ b/apps/landing/src/app/(auth)/signin/_http/fetch-post-signin.ts @@ -0,0 +1,24 @@ +import { fetcher } from '@/lib/fetcher'; +import { SignInValidationType } from '../_validation/signin-validation'; + +export async function fetchPostSignin({ + email, + password, +}: SignInValidationType) { + const { data, error, response } = await fetcher.POST('/v1/auth/login', { + body: { + email, + password, + }, + }); + + if (error) { + throw new Error(error.message); + } + + if (!response.ok) { + throw new Error('Someting went wrong, please try again later'); + } + + return data; +} diff --git a/apps/landing/src/app/(auth)/signin/_validation/signin-validation.ts b/apps/landing/src/app/(auth)/signin/_validation/signin-validation.ts new file mode 100644 index 0000000..0bb050b --- /dev/null +++ b/apps/landing/src/app/(auth)/signin/_validation/signin-validation.ts @@ -0,0 +1,18 @@ +import { z } from 'zod'; + +export const signInValidationSchema = z.object({ + email: z + .string({ + required_error: 'Email tidak boleh kosong', + invalid_type_error: 'Email harus berupa string', + }) + .min(1, 'Email tidak boleh kosong') + .email('Email harus valid'), + password: z + .string({ + required_error: 'Password tidak boleh kosong', + invalid_type_error: 'Password harus berupa string', + }) + .min(1, 'Password tidak boleh kosong'), +}); +export type SignInValidationType = z.infer; diff --git a/apps/landing/src/app/(auth)/signin/page.tsx b/apps/landing/src/app/(auth)/signin/page.tsx index 7d1e0b7..40647b1 100644 --- a/apps/landing/src/app/(auth)/signin/page.tsx +++ b/apps/landing/src/app/(auth)/signin/page.tsx @@ -1,3 +1,38 @@ +import { LogoSimple } from '@/app/_components/logo'; +import { Metadata } from 'next'; +import Link from 'next/link'; +import { SigninForm } from './_components/signin-form'; + +export const metadata: Metadata = { + title: 'IMPHNEN - Signin', + description: + 'Komunitas Ingin Menjadi Programmer Handal Namung Enggan Ngonding', +}; + export default function Page() { - return <>; + return ( + <> +
+ + +

+ Masuk untuk mengakses akunmu +

+
+ + + +
+

+ Belum punya akun?{' '} + + Daftar + +

+
+ + ); }