From c033befca41d9c959f88cbe642d7f37ab1e92077 Mon Sep 17 00:00:00 2001 From: Firman Ramdhani <33869609+firmanramdhani@users.noreply.github.com> Date: Thu, 30 Jul 2026 16:53:29 +0700 Subject: [PATCH] feat: setup auth schema --- .../auth/login/components/android-icon.tsx | 6 + .../auth/login/components/chrome-icon.tsx | 16 + .../auth/login/components/google-icon.tsx | 20 + .../auth/login/components/icon-circle.tsx | 12 + .../auth/login/components/microsoft-icon.tsx | 8 + .../auth/login/components/right-section.tsx | 121 ++++++ .../src/apps/auth/login/components/ring.tsx | 6 + apps/web/src/apps/auth/login/index.tsx | 344 +++++++----------- .../apps/auth/login/languages/en/login.json | 12 + .../apps/auth/login/languages/id/login.json | 12 + .../auth/login/validators/login.validator.ts | 9 + packages/brand/public/logo-primary.svg | 6 + 12 files changed, 357 insertions(+), 215 deletions(-) create mode 100644 apps/web/src/apps/auth/login/components/android-icon.tsx create mode 100644 apps/web/src/apps/auth/login/components/chrome-icon.tsx create mode 100644 apps/web/src/apps/auth/login/components/google-icon.tsx create mode 100644 apps/web/src/apps/auth/login/components/icon-circle.tsx create mode 100644 apps/web/src/apps/auth/login/components/microsoft-icon.tsx create mode 100644 apps/web/src/apps/auth/login/components/right-section.tsx create mode 100644 apps/web/src/apps/auth/login/components/ring.tsx create mode 100644 apps/web/src/apps/auth/login/languages/en/login.json create mode 100644 apps/web/src/apps/auth/login/languages/id/login.json create mode 100644 apps/web/src/apps/auth/login/validators/login.validator.ts create mode 100644 packages/brand/public/logo-primary.svg diff --git a/apps/web/src/apps/auth/login/components/android-icon.tsx b/apps/web/src/apps/auth/login/components/android-icon.tsx new file mode 100644 index 0000000..17110c7 --- /dev/null +++ b/apps/web/src/apps/auth/login/components/android-icon.tsx @@ -0,0 +1,6 @@ +export const AndroidIcon = (props: any) => ( + + + + +); diff --git a/apps/web/src/apps/auth/login/components/chrome-icon.tsx b/apps/web/src/apps/auth/login/components/chrome-icon.tsx new file mode 100644 index 0000000..1143373 --- /dev/null +++ b/apps/web/src/apps/auth/login/components/chrome-icon.tsx @@ -0,0 +1,16 @@ +export const ChromeIcon = (props: any) => ( + + + + + + +); diff --git a/apps/web/src/apps/auth/login/components/google-icon.tsx b/apps/web/src/apps/auth/login/components/google-icon.tsx new file mode 100644 index 0000000..ddb1a8f --- /dev/null +++ b/apps/web/src/apps/auth/login/components/google-icon.tsx @@ -0,0 +1,20 @@ +export const GoogleIcon = (props: any) => ( + + + + + + +); diff --git a/apps/web/src/apps/auth/login/components/icon-circle.tsx b/apps/web/src/apps/auth/login/components/icon-circle.tsx new file mode 100644 index 0000000..c39efa7 --- /dev/null +++ b/apps/web/src/apps/auth/login/components/icon-circle.tsx @@ -0,0 +1,12 @@ +export const IconCircle = ({ x, y, children }: { x: number; y: number; children: React.ReactNode }) => ( +
+ {children} +
+); diff --git a/apps/web/src/apps/auth/login/components/microsoft-icon.tsx b/apps/web/src/apps/auth/login/components/microsoft-icon.tsx new file mode 100644 index 0000000..34f6413 --- /dev/null +++ b/apps/web/src/apps/auth/login/components/microsoft-icon.tsx @@ -0,0 +1,8 @@ +export const MicrosoftIcon = (props: any) => ( + + + + + + +); diff --git a/apps/web/src/apps/auth/login/components/right-section.tsx b/apps/web/src/apps/auth/login/components/right-section.tsx new file mode 100644 index 0000000..9d8d49e --- /dev/null +++ b/apps/web/src/apps/auth/login/components/right-section.tsx @@ -0,0 +1,121 @@ +import { Apple, Globe, Mail, MessageCircle } from 'lucide-react'; +import { IconCircle } from './icon-circle'; +import { Ring } from './ring'; +import { AndroidIcon } from './android-icon'; +import { ChromeIcon } from './chrome-icon'; + +export function RightSection() { + return ( + //
+
+ {/* 1. Glossy & Glassmorphic Orbs */} +
+
+
+ +

+ Write Better {/* Wrapper luar KHUSUS untuk Drop Shadow */} + + {/* Elemen dalam KHUSUS untuk Gradien Teks */} + + Everywhere + + +

+ + {/* Graphics Area */} +
+ {/* Concentric Rings */} + + + + + + {/* Center Logo */} +
+
+ {/* Glowing backdrop */} +
+ {/* Custom P/Pen Logo from reference */} + + + + + +
+
+ + {/* Orbiting Icons */} + + {/* Ring 1 (r=100) */} +
+ + + +
+ +
+ + + +
+ + {/* Ring 2 (r=150) */} +
+ + + +
+ +
+ + y! + +
+ + {/* Ring 3 (r=210) */} +
+ + + +
+ +
+ + + +
+ + {/* Ring 4 (r=270) */} +
+ + + +
+
+ +

+ Compatible with{' '} + Gmail, Outlook Web, LinkedIn and most web editors for a + smooth writing experience anywhere online. +

+ + {/* Pagination Indicators */} +
+
+
+
+
+
+ ); +} diff --git a/apps/web/src/apps/auth/login/components/ring.tsx b/apps/web/src/apps/auth/login/components/ring.tsx new file mode 100644 index 0000000..fb9e283 --- /dev/null +++ b/apps/web/src/apps/auth/login/components/ring.tsx @@ -0,0 +1,6 @@ +export const Ring = ({ size }: { size: number }) => ( +
+); diff --git a/apps/web/src/apps/auth/login/index.tsx b/apps/web/src/apps/auth/login/index.tsx index 4667697..0642ffd 100644 --- a/apps/web/src/apps/auth/login/index.tsx +++ b/apps/web/src/apps/auth/login/index.tsx @@ -1,104 +1,115 @@ -import { TextInput, PasswordInput, Checkbox, Button, Divider } from '@repo/ui/components'; -import { Mail, Lock, LogIn, Apple, Globe, MessageCircle } from 'lucide-react'; +import { + FieldTextInput, + FieldPasswordInput, + Checkbox, + Button, + Divider, + Select, + Image, + notifications, +} from '@repo/ui/components'; +import { Lock, Apple, LogInIcon, UserRound, Globe } from 'lucide-react'; +import { GoogleIcon } from './components/google-icon'; +import { MicrosoftIcon } from './components/microsoft-icon'; +import { RightSection } from './components/right-section'; +import { useTranslation, registerModuleNamespace } from '@repo/core-i18n'; +import { AppStorageKey, appStorage } from '../../../core/storage/local'; +import { useForm } from 'react-hook-form'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { createLoginSchema } from './validators/login.validator'; +import { useMemo, useState } from 'react'; -const GoogleIcon = (props: any) => ( - - - - - - -); +import loginEn from './languages/en/login.json'; +import loginId from './languages/id/login.json'; +import { CommonRemoteDataServices } from '@repo/core-api/data-services'; +import { apiClient } from '../../../core/lib/api-client'; +import { initiateAuthSession } from '../../../core/lib/auth.helper'; -const MicrosoftIcon = (props: any) => ( - - - - - - -); +registerModuleNamespace('auth-login', { + en: loginEn, + id: loginId, +}); -const AndroidIcon = (props: any) => ( - - - - -); - -const ChromeIcon = (props: any) => ( - - - - - - -); - -const Ring = ({ size }: { size: number }) => ( -
-); - -const IconCircle = ({ x, y, children }: { x: number; y: number; children: React.ReactNode }) => ( -
- {children} -
-); +export const authDataService = new CommonRemoteDataServices(apiClient, {}); export default function LoginPage() { + const { t, i18n } = useTranslation('auth-login'); + const [loadingLogin, setLoadingLogin] = useState(false); + + const validator = useMemo(() => { + return createLoginSchema(t); + }, [t, i18n.language]); + + const formControl = useForm({ + resolver: zodResolver(validator), + defaultValues: { username: '', password: '' }, + }); + const { control } = formControl; + + const onSubmit = async (data: any) => { + setLoadingLogin(true); + try { + const response = await authDataService.customRequest({ url: '/api/v1/auth', method: 'POST', data }); + await initiateAuthSession(response.data); + } catch (error: any) { + const message = error?.response?.data?.message; + notifications.show({ + title: t('common:notifications.errorTitle'), + message: message ?? error?.message ?? 'Login failed', + color: 'red', + }); + } finally { + setLoadingLogin(false); + } + }; + return (
{/* Left Column - Login Form */}
- {/* Logo (Top Left) */} -
- {/* Image Logo (Uncomment and set src to your logo path) */} - {/* Logo */} +
+ {/* Logo (Top Left) */} +
+ Logo +
- {/* Text Logo (Remove if using image) */} -
- E + {/* Language Switcher (Top Right) */} +
+ +