From 26026572012283dcbff3e931c7cdf248fb031d22 Mon Sep 17 00:00:00 2001 From: Hafid Nur Date: Wed, 2 Apr 2025 22:42:02 +0700 Subject: [PATCH 1/4] feat(backoffice): send login request - buat .env untuk menyimpan API dan memberikan .env.example juga untuk contohnya. Tambah .gitignore juga - tambah fungsi login pada Backoffice --- .env.example | 1 + .gitignore | 4 ++- apps/backoffice/src/app/page.tsx | 55 +++++++++++++++++++++--------- libs/service/src/api/auth/index.ts | 2 +- 4 files changed, 44 insertions(+), 18 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..49d9f6e --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +VITE_API_URL=https://api.example.com diff --git a/.gitignore b/.gitignore index 77912e8..0ddc0e9 100644 --- a/.gitignore +++ b/.gitignore @@ -44,4 +44,6 @@ Thumbs.db vite.config.*.timestamp* vitest.config.*.timestamp* -storybook-static \ No newline at end of file +storybook-static + +.env diff --git a/apps/backoffice/src/app/page.tsx b/apps/backoffice/src/app/page.tsx index b92bf58..7ba7fee 100644 --- a/apps/backoffice/src/app/page.tsx +++ b/apps/backoffice/src/app/page.tsx @@ -1,10 +1,27 @@ -import { FC, ReactElement } from 'react'; +import { FC, ReactElement, useState } from 'react'; import { useNavigate } from 'react-router'; import { Button } from '@imphnen-frontend-service/ui/atoms'; import { InputForm } from '@imphnen-frontend-service/ui/molecules'; +import { postLogin } from '@imphnen-frontend-service/service'; export const Components: FC = (): ReactElement => { const navigate = useNavigate(); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + + const handleLogin = async (e: React.FormEvent) => { + e.preventDefault(); + try { + const payload = { email, password }; + console.log(payload); // for debugging + const response = await postLogin(payload); + + console.log('Login successful:', response); // for debugging + navigate('/dashboard'); + } catch (error) { + console.log('Login error:', error); // for debugging + } + }; return (
@@ -13,21 +30,27 @@ export const Components: FC = (): ReactElement => {

Welcome to IMPHNEN Backoffice

- - - +
+ setEmail(e.target.value)} + /> + setPassword(e.target.value)} + /> + +
); diff --git a/libs/service/src/api/auth/index.ts b/libs/service/src/api/auth/index.ts index e925dd1..ded271b 100644 --- a/libs/service/src/api/auth/index.ts +++ b/libs/service/src/api/auth/index.ts @@ -12,7 +12,7 @@ export const postLogin = async ( ): Promise => { const { data } = await api({ method: 'POST', - url: '/auth/login', + url: '/v1/auth/login', data: payload, }); return data; From a9cc728ade1f9a037b1d9b01fa247873b8523158 Mon Sep 17 00:00:00 2001 From: Hafid Nur Date: Thu, 3 Apr 2025 06:10:07 +0700 Subject: [PATCH 2/4] feat(backoffice): implement login and logout - Tambah fitur login dan logout pada Backoffice - Ubah port development server dan atasi CORS - Update type login response - Update component Input agar toggle password berfungsi dengan benar --- apps/backoffice/src/app/page.tsx | 5 +++++ apps/backoffice/vite.config.ts | 4 ++-- libs/service/src/types/auth/index.ts | 18 ++++++++++++++++++ libs/ui/src/atoms/input/input.tsx | 4 +++- .../backoffice-sidebar/backoffice-sidebar.tsx | 11 ++++++++--- 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/apps/backoffice/src/app/page.tsx b/apps/backoffice/src/app/page.tsx index 7ba7fee..dc8a0c8 100644 --- a/apps/backoffice/src/app/page.tsx +++ b/apps/backoffice/src/app/page.tsx @@ -16,6 +16,10 @@ export const Components: FC = (): ReactElement => { console.log(payload); // for debugging const response = await postLogin(payload); + const { access_token, refresh_token } = response.data.token; + sessionStorage.setItem('access_token', access_token); + localStorage.setItem('refresh_token', refresh_token); + console.log('Login successful:', response); // for debugging navigate('/dashboard'); } catch (error) { @@ -39,6 +43,7 @@ export const Components: FC = (): ReactElement => { className="w-full" value={email} onChange={(e) => setEmail(e.target.value)} + autoFocus /> ({ root: __dirname, cacheDir: '../../node_modules/.vite/apps/backoffice', server: { - port: 4200, + port: 3000, host: 'localhost', }, preview: { - port: 4300, + port: 3001, host: 'localhost', }, plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])], diff --git a/libs/service/src/types/auth/index.ts b/libs/service/src/types/auth/index.ts index bf094ec..03fc5a7 100644 --- a/libs/service/src/types/auth/index.ts +++ b/libs/service/src/types/auth/index.ts @@ -10,9 +10,27 @@ export type TLoginResponse = { refresh_token: string; }; user: { + role: { + id: string; + name: string; + permission: [ + { + id: string; + name: string; + created_at: string; + updated_at: string; + } + ] + created_at: string; + updated_at: string; + }; fullname: string; email: string; + avatar: string; + phone_number: string; is_active: boolean; + gender: string; + birthdate: string; }; }; }; diff --git a/libs/ui/src/atoms/input/input.tsx b/libs/ui/src/atoms/input/input.tsx index ae0e849..e780059 100644 --- a/libs/ui/src/atoms/input/input.tsx +++ b/libs/ui/src/atoms/input/input.tsx @@ -40,7 +40,8 @@ export const Input: FC = ({ }): ReactElement => { const [showPassword, setShowPassword] = useState(false); // State for password visibility - const togglePasswordVisibility = () => { + const togglePasswordVisibility = (e: React.FormEvent) => { + e.preventDefault(); if (!disabled) setShowPassword((prev) => !prev); }; @@ -63,6 +64,7 @@ export const Input: FC = ({ {type === 'password' && (
+
+ + + +
); diff --git a/libs/ui/src/molecules/input-field/input-field.tsx b/libs/ui/src/molecules/input-field/input-field.tsx index 0db7b16..0245843 100644 --- a/libs/ui/src/molecules/input-field/input-field.tsx +++ b/libs/ui/src/molecules/input-field/input-field.tsx @@ -75,10 +75,15 @@ export const InputField: FC = ({ {...rest} /> {error ? ( -

{error}

+

{error}

) : ( helperText && ( -

+

{helperText}

) From 988476b4090db47778ce6c622711f7cf73dd3806 Mon Sep 17 00:00:00 2001 From: Hafid Nur Date: Thu, 3 Apr 2025 21:59:31 +0700 Subject: [PATCH 4/4] refactor auth and logout - Pindah hard-code API version ke environment variable - Gunakan helper untuk logout --- libs/service/src/api/auth/index.ts | 2 +- .../backoffice-sidebar/backoffice-sidebar.tsx | 18 ++++-------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/libs/service/src/api/auth/index.ts b/libs/service/src/api/auth/index.ts index 16ea25c..0241638 100644 --- a/libs/service/src/api/auth/index.ts +++ b/libs/service/src/api/auth/index.ts @@ -12,7 +12,7 @@ export const postLogin = async ( ): Promise => { const { data } = await api({ method: 'POST', - url: '/v1/auth/login', + url: '/auth/login', data: payload, }); return data; diff --git a/libs/ui/src/organisms/backoffice-sidebar/backoffice-sidebar.tsx b/libs/ui/src/organisms/backoffice-sidebar/backoffice-sidebar.tsx index a7aace0..3ceb18e 100644 --- a/libs/ui/src/organisms/backoffice-sidebar/backoffice-sidebar.tsx +++ b/libs/ui/src/organisms/backoffice-sidebar/backoffice-sidebar.tsx @@ -7,27 +7,19 @@ import { } from '@ant-design/icons'; import { Button } from '../../atoms'; import { FC, ReactElement } from 'react'; -import { Link, useLocation, useNavigate } from 'react-router-dom'; +import { Link, useLocation } from 'react-router-dom'; +import { useSession } from '@imphnen-frontend-service/utils'; export const BackofficeSidebar: FC = (): ReactElement => { + const { signOut } = useSession(); const location = useLocation(); - const navigate = useNavigate(); const isActive = (path: string) => location.pathname.includes(path); - const handleLogout = () => { - sessionStorage.removeItem('access_token'); - localStorage.removeItem('refresh_token'); - - navigate('/'); - }; - return (