From f5f715175cf0ee2132754cc2a7d5b8e59c3067dd Mon Sep 17 00:00:00 2001 From: arraysid Date: Tue, 20 May 2025 10:00:52 +0700 Subject: [PATCH] feat: restructure signin functionality with new hooks and improved validation --- .../(auth)/signin/_action/signin-action.ts | 29 -------------- .../(auth)/signin/_actions/signin-action.ts | 22 +++++++++++ .../(auth)/signin/_components/signin-form.tsx | 39 ++++++------------- .../(auth)/signin/_hooks/use-form-signin.ts | 16 ++++++++ .../(auth)/signin/_hooks/use-post-signin.ts | 18 +++++++++ .../(auth)/signin/_http/signin-http.ts | 24 ++++++++++++ .../signin/_validation/signin-validation.ts | 1 + .../src/app/(frontend)/(auth)/signin/page.tsx | 2 +- 8 files changed, 93 insertions(+), 58 deletions(-) delete mode 100644 apps/landing/src/app/(frontend)/(auth)/signin/_action/signin-action.ts create mode 100644 apps/landing/src/app/(frontend)/(auth)/signin/_actions/signin-action.ts create mode 100644 apps/landing/src/app/(frontend)/(auth)/signin/_hooks/use-form-signin.ts create mode 100644 apps/landing/src/app/(frontend)/(auth)/signin/_hooks/use-post-signin.ts create mode 100644 apps/landing/src/app/(frontend)/(auth)/signin/_http/signin-http.ts diff --git a/apps/landing/src/app/(frontend)/(auth)/signin/_action/signin-action.ts b/apps/landing/src/app/(frontend)/(auth)/signin/_action/signin-action.ts deleted file mode 100644 index 5ad05f1..0000000 --- a/apps/landing/src/app/(frontend)/(auth)/signin/_action/signin-action.ts +++ /dev/null @@ -1,29 +0,0 @@ -'use server'; - -import { setAccessToken, setRefreshToken } from '@/lib/cookies'; -import { fetcher } from '@/lib/openapi'; -import { z } from 'zod'; -import { signInValidationSchema } from '../_validation/signin-validation'; - -export async function SigninAction( - data: z.infer -) { - const { email, password } = signInValidationSchema.parse(data); - - const { data: json, error } = await fetcher.POST('/v1/auth/login', { - body: { - email, - password, - }, - }); - - if (error) throw new Error(error.message); - - const accessToken = json.data.token.access_token; - const refreshToken = json.data.token.refresh_token; - - await setAccessToken(accessToken); - await setRefreshToken(refreshToken); - - return json; -} diff --git a/apps/landing/src/app/(frontend)/(auth)/signin/_actions/signin-action.ts b/apps/landing/src/app/(frontend)/(auth)/signin/_actions/signin-action.ts new file mode 100644 index 0000000..48afe0d --- /dev/null +++ b/apps/landing/src/app/(frontend)/(auth)/signin/_actions/signin-action.ts @@ -0,0 +1,22 @@ +'use server'; + +import { setAccessToken, setRefreshToken } from '@/lib/cookies'; +import { fetchPostSignin } from '../_http/signin-http'; +import { + type SignInValidationType, + signInValidationSchema, +} from '../_validation/signin-validation'; + +export async function SigninAction(request: SignInValidationType) { + 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/(frontend)/(auth)/signin/_components/signin-form.tsx b/apps/landing/src/app/(frontend)/(auth)/signin/_components/signin-form.tsx index e12a134..e6a6935 100644 --- a/apps/landing/src/app/(frontend)/(auth)/signin/_components/signin-form.tsx +++ b/apps/landing/src/app/(frontend)/(auth)/signin/_components/signin-form.tsx @@ -10,37 +10,16 @@ import { FormMessage, Input, } from '@components/atoms'; -import { zodResolver } from '@hookform/resolvers/zod'; -import { useMutation } from '@tanstack/react-query'; -import { useRouter } from 'next/navigation'; -import { useForm } from 'react-hook-form'; import { LuLoader } from 'react-icons/lu'; -import { z } from 'zod'; -import { SigninAction } from '../_action/signin-action'; -import { signInValidationSchema } from '../_validation/signin-validation'; +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 router = useRouter(); + const form = useFormSignin(); + const { mutate, isPending, error } = usePostSignin(form); - const form = useForm>({ - resolver: zodResolver(signInValidationSchema), - defaultValues: { - email: '', - password: '', - }, - }); - - const { mutate, isPending, error } = useMutation({ - mutationFn: SigninAction, - onSuccess: () => { - router.push('/'); - }, - onError: () => { - form.resetField('password'); - }, - }); - - const onSubmit = (values: z.infer) => { + const onSubmit = (values: SignInValidationType) => { mutate(values); }; @@ -81,7 +60,11 @@ export function SigninForm() { )} /> - diff --git a/apps/landing/src/app/(frontend)/(auth)/signin/_hooks/use-form-signin.ts b/apps/landing/src/app/(frontend)/(auth)/signin/_hooks/use-form-signin.ts new file mode 100644 index 0000000..76af058 --- /dev/null +++ b/apps/landing/src/app/(frontend)/(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/(frontend)/(auth)/signin/_hooks/use-post-signin.ts b/apps/landing/src/app/(frontend)/(auth)/signin/_hooks/use-post-signin.ts new file mode 100644 index 0000000..217b35e --- /dev/null +++ b/apps/landing/src/app/(frontend)/(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/(frontend)/(auth)/signin/_http/signin-http.ts b/apps/landing/src/app/(frontend)/(auth)/signin/_http/signin-http.ts new file mode 100644 index 0000000..8a388a3 --- /dev/null +++ b/apps/landing/src/app/(frontend)/(auth)/signin/_http/signin-http.ts @@ -0,0 +1,24 @@ +import { fetcher } from '@/lib/openapi'; +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/(frontend)/(auth)/signin/_validation/signin-validation.ts b/apps/landing/src/app/(frontend)/(auth)/signin/_validation/signin-validation.ts index a74f034..0bb050b 100644 --- a/apps/landing/src/app/(frontend)/(auth)/signin/_validation/signin-validation.ts +++ b/apps/landing/src/app/(frontend)/(auth)/signin/_validation/signin-validation.ts @@ -15,3 +15,4 @@ export const signInValidationSchema = z.object({ }) .min(1, 'Password tidak boleh kosong'), }); +export type SignInValidationType = z.infer; diff --git a/apps/landing/src/app/(frontend)/(auth)/signin/page.tsx b/apps/landing/src/app/(frontend)/(auth)/signin/page.tsx index 97e22c7..91e2301 100644 --- a/apps/landing/src/app/(frontend)/(auth)/signin/page.tsx +++ b/apps/landing/src/app/(frontend)/(auth)/signin/page.tsx @@ -27,7 +27,7 @@ export default function Page() { Belum punya akun?{' '} Daftar