From 42eb159a5257f9a05ed76e85ae2e6d67be12efdc Mon Sep 17 00:00:00 2001 From: Ardeman Date: Sat, 1 Mar 2025 01:00:52 +0800 Subject: [PATCH] feat: implement user registration functionality with form validation and API integration --- app/apis/news/register.ts | 20 ++++ app/layouts/news/form-login.tsx | 4 +- app/layouts/news/form-register.tsx | 182 +++++++++++++++-------------- app/routes/actions.register.ts | 75 ++++++++++++ 4 files changed, 191 insertions(+), 90 deletions(-) create mode 100644 app/apis/news/register.ts create mode 100644 app/routes/actions.register.ts diff --git a/app/apis/news/register.ts b/app/apis/news/register.ts new file mode 100644 index 0000000..7004157 --- /dev/null +++ b/app/apis/news/register.ts @@ -0,0 +1,20 @@ +import { z } from 'zod' + +import type { TRegisterSchema } from '~/layouts/news/form-register' +import { HttpServer } from '~/libs/http-server' + +const loginResponseSchema = z.object({ + data: z.object({ + token: z.string(), + }), +}) + +export const newsRegisterRequest = async (payload: TRegisterSchema) => { + try { + const { data } = await HttpServer().post('/api/user/register', payload) + return loginResponseSchema.parse(data) + } catch (error) { + // eslint-disable-next-line unicorn/no-useless-promise-resolve-reject + return Promise.reject(error) + } +} diff --git a/app/layouts/news/form-login.tsx b/app/layouts/news/form-login.tsx index 797985b..551ae72 100644 --- a/app/layouts/news/form-login.tsx +++ b/app/layouts/news/form-login.tsx @@ -63,7 +63,7 @@ export const FormLogin = () => { > @@ -80,7 +80,6 @@ export const FormLogin = () => {
{error}
)} - {/* Lupa Kata Sandi */}
Lupa Kata Sandi?
- {/* Tombol Masuk */} - - {/* Reinput Password */} -
- - - -
- {/* No Telepon */} -
- - -
- {/* Subscribe*/} -
-
*/} + + {error && ( +
{error}
+ )} + + - + Daftar + + + {/* Link Login */}
diff --git a/app/routes/actions.register.ts b/app/routes/actions.register.ts new file mode 100644 index 0000000..ae30723 --- /dev/null +++ b/app/routes/actions.register.ts @@ -0,0 +1,75 @@ +import { zodResolver } from '@hookform/resolvers/zod' +import { data } from 'react-router' +import { getValidatedFormData } from 'remix-hook-form' +import { XiorError } from 'xior' + +import { getUser } from '~/apis/news/get-user' +import { newsRegisterRequest } from '~/apis/news/register' +import { + registerSchema, + type TRegisterSchema, +} from '~/layouts/news/form-register' +import { generateTokenCookie } from '~/utils/token' + +import type { Route } from './+types/actions.register' + +export const action = async ({ request }: Route.ActionArgs) => { + try { + const { + errors, + data: payload, + receivedValues: defaultValues, + } = await getValidatedFormData( + request, + zodResolver(registerSchema), + false, + ) + + if (errors) { + return data({ success: false, errors, defaultValues }, { status: 400 }) + } + + const { data: registerData } = await newsRegisterRequest(payload) + const { token } = registerData + const { data: userData } = await getUser({ + accessToken: token, + }) + const tokenCookie = generateTokenCookie({ + token, + }) + + const headers = new Headers() + headers.append('Set-Cookie', await tokenCookie) + + return data( + { + success: true, + user: userData, + }, + { + headers, + status: 200, + statusText: 'OK', + }, + ) + } catch (error) { + if (error instanceof XiorError) { + return data( + { + success: false, + message: error?.response?.data?.error?.message || error.message, + }, + { + status: error?.response?.status || 500, + }, + ) + } + return data( + { + success: false, + message: 'Internal server error', + }, + { status: 500 }, + ) + } +}