Skip to content

Commit

Permalink
feat: add login page (#23)
Browse files Browse the repository at this point in the history
* feat: add slicing login page

* feat: integrate login page

* feat: add withauth hoc

* fix: disable missing suspense in useSearchParams
  • Loading branch information
ainunns authored Mar 9, 2024
1 parent a7d8366 commit 3df31b6
Show file tree
Hide file tree
Showing 16 changed files with 425 additions and 34 deletions.
6 changes: 5 additions & 1 deletion next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {
experimental: {
missingSuspenseWithCSRBailout: false,
},
};

export default nextConfig;
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@tanstack/react-query": "^5.25.0",
"axios": "^1.6.7",
"clsx": "^2.1.0",
"immer": "^10.0.3",
"lodash.get": "^4.4.2",
"next": "14.1.1",
"react": "^18",
Expand All @@ -30,7 +31,8 @@
"react-icons": "^5.0.1",
"react-select": "^5.8.0",
"tailwind-merge": "^2.2.1",
"universal-cookie": "^7.1.0"
"universal-cookie": "^7.1.0",
"zustand": "^4.5.2"
},
"devDependencies": {
"@commitlint/cli": "^19.0.3",
Expand Down
39 changes: 39 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added public/images/auth/sign-in.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 60 additions & 0 deletions src/app/(auth)/login/container/LoginForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use client';
import * as React from 'react';
import { FormProvider, useForm } from 'react-hook-form';

import { useLoginMutation } from '@/app/(auth)/login/hooks/mutation';
import Button from '@/components/buttons/Button';
import Input from '@/components/forms/Input';

type LoginForm = {
email: string;
password: string;
};

export default function LoginForm() {
const methods = useForm<LoginForm>({
mode: 'onTouched',
});

const { handleSubmit } = methods;

const { handleLogin, isPending } = useLoginMutation();

const onSubmit = (data: LoginForm) => {
handleLogin({
...data,
});
};

return (
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmit)} className='flex flex-col gap-3'>
<Input
id='email'
label='Email'
placeholder='Masukkan Email'
validation={{
required: 'Email tidak boleh kosong!',
}}
/>
<Input
id='password'
type='password'
label='Password'
placeholder='Masukkan Password'
validation={{
required: 'Password tidak boleh kosong!',
}}
/>
<Button
type='submit'
variant='primary'
className='w-full'
isLoading={isPending}
>
Login
</Button>
</form>
</FormProvider>
);
}
37 changes: 37 additions & 0 deletions src/app/(auth)/login/container/LoginPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use client';
import * as React from 'react';

import LoginForm from '@/app/(auth)/login/container/LoginForm';
import withAuth from '@/components/hoc/withAuth';
import PrimaryLink from '@/components/links/PrimaryLink';
import NextImage from '@/components/NextImage';
import Typography from '@/components/Typography';

export default withAuth(LoginContainer, ['authed']);
function LoginContainer() {
return (
<main className='flex min-h-screen w-full flex-col items-center justify-center'>
<div className='mx-auto flex w-10/12 flex-row items-center justify-between'>
<section className='flex w-full flex-col gap-12 lg:w-2/5'>
<Typography variant='h3' color='primary-typo' weight='semibold'>
Sign In
</Typography>
<LoginForm />
<Typography variant='c1' color='secondary' weight='regular'>
Belum punya akun?{' '}
<PrimaryLink href='/register'>Register</PrimaryLink>
</Typography>
</section>
<section className='hidden w-2/5 lg:block'>
<NextImage
src='/auth/sign-up.png'
alt='hero'
width='609'
height='575'
className='mx-auto w-[90%]'
/>
</section>
</div>
</main>
);
}
45 changes: 45 additions & 0 deletions src/app/(auth)/login/hooks/mutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useMutation } from '@tanstack/react-query';
import { useRouter } from 'next/navigation';

import { showToast, SUCCESS_TOAST } from '@/components/Toast';
import useMutationToast from '@/hooks/useMutationToast';
import api from '@/lib/api';
import { setToken } from '@/lib/cookies';
import useAuthStore from '@/store/useAuthStore';
import { ApiResponseUser } from '@/types/api';
import { UserType } from '@/types/entities/user';

export type LoginForm = {
email: string;
password: string;
};

export const useLoginMutation = () => {
const router = useRouter();
const { login } = useAuthStore();
const {
mutateAsync: handleLogin,
isPending,
isSuccess,
} = useMutationToast<void, LoginForm>(
useMutation({
mutationFn: async (data: LoginForm) => {
const response = await api.post('/user/login', data);
const { accessToken } = response.data;
setToken(accessToken);

const user = await api.get<ApiResponseUser<UserType>>('/user');
if (!user.data.user) {
throw new Error('Sesi login tidak valid');
}

login({ ...user.data.user, token: accessToken });
},
onSuccess: () => {
showToast('Akun berhasil login', SUCCESS_TOAST);
router.push('/board');
},
}),
);
return { handleLogin, isPending, isSuccess };
};
12 changes: 12 additions & 0 deletions src/app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Metadata } from 'next';
import * as React from 'react';

import LoginContainer from '@/app/(auth)/login/container/LoginPage';

export const metadata: Metadata = {
title: 'Login',
};

export default function LoginPage() {
return <LoginContainer />;
}
36 changes: 36 additions & 0 deletions src/app/(auth)/register/container/RegisterPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use client';
import * as React from 'react';

import RegisterForm from '@/app/(auth)/register/container/RegisterForm';
import withAuth from '@/components/hoc/withAuth';
import PrimaryLink from '@/components/links/PrimaryLink';
import NextImage from '@/components/NextImage';
import Typography from '@/components/Typography';

export default withAuth(RegisterContainer, ['authed']);
function RegisterContainer() {
return (
<main className='flex min-h-screen w-full flex-col items-center justify-center'>
<div className='mx-auto flex w-10/12 flex-row items-center justify-between'>
<section className='hidden w-2/5 lg:block'>
<NextImage
src='/auth/sign-up.png'
alt='hero'
width='609'
height='575'
className='mx-auto w-[90%]'
/>
</section>
<section className='flex w-full flex-col gap-12 lg:w-2/5'>
<Typography variant='h3' color='primary-typo' weight='semibold'>
Sign Up
</Typography>
<RegisterForm />
<Typography variant='c1' color='secondary' weight='regular'>
Sudah punya akun? <PrimaryLink href='/login'>Login</PrimaryLink>
</Typography>
</section>
</div>
</main>
);
}
31 changes: 2 additions & 29 deletions src/app/(auth)/register/page.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,11 @@
import { Metadata } from 'next';
import * as React from 'react';

import RegisterForm from '@/app/(auth)/register/container/RegisterForm';
import PrimaryLink from '@/components/links/PrimaryLink';
import NextImage from '@/components/NextImage';
import Typography from '@/components/Typography';
import RegisterContainer from '@/app/(auth)/register/container/RegisterPage';

export const metadata: Metadata = {
title: 'Register',
};

export default function RegisterPage() {
return (
<main className='flex min-h-screen w-full flex-col items-center justify-center'>
<div className='mx-auto flex w-10/12 flex-row items-center justify-between'>
<section className='hidden w-2/5 lg:block'>
<NextImage
src='/auth/sign-up.png'
alt='hero'
width='609'
height='575'
className='mx-auto w-[90%]'
/>
</section>
<section className='flex w-full flex-col gap-12 lg:w-2/5'>
<Typography variant='h3' color='primary-typo' weight='semibold'>
Sign Up
</Typography>
<RegisterForm />
<Typography variant='c1' color='secondary' weight='regular'>
Sudah punya akun? <PrimaryLink href='/login'>Login</PrimaryLink>
</Typography>
</section>
</div>
</main>
);
return <RegisterContainer />;
}
Loading

0 comments on commit 3df31b6

Please sign in to comment.