diff --git a/app/configs/pages.ts b/app/configs/pages.ts
new file mode 100644
index 0000000..42b3ff4
--- /dev/null
+++ b/app/configs/pages.ts
@@ -0,0 +1,6 @@
+export const AUTH_PAGES = [
+ '/lg-admin/login',
+ '/lg-admin/forgot-password',
+ '/lg-admin/reset-password',
+ '/lg-admin/register',
+]
diff --git a/app/pages/admin-login/index.tsx b/app/pages/admin-login/index.tsx
new file mode 100644
index 0000000..2698423
--- /dev/null
+++ b/app/pages/admin-login/index.tsx
@@ -0,0 +1,107 @@
+import { useState } from 'react'
+import { Link } from 'react-router'
+
+import { EyeIcon } from '~/components/icons/eye'
+import { Button } from '~/components/ui/button'
+import { APP } from '~/configs/meta'
+
+export const AdminLoginPage = () => {
+ const [showPassword, setShowPassword] = useState(false)
+
+ return (
+
+
+
+
+

+
+
+
+ Selamat Datang, silakan masukkan akun Anda untuk melanjutkan!
+
+
+
+ {/* Link Daftar */}
+
+ Belum punya akun?{' '}
+
+
+
+ )
+}
diff --git a/app/routes/_admin.lg-admin._auth.login.tsx b/app/routes/_admin.lg-admin._auth.login.tsx
index a99db97..0113752 100644
--- a/app/routes/_admin.lg-admin._auth.login.tsx
+++ b/app/routes/_admin.lg-admin._auth.login.tsx
@@ -1,108 +1,4 @@
-import { useState } from 'react'
-import { Link } from 'react-router'
+import { AdminLoginPage } from '~/pages/admin-login'
-import { EyeIcon } from '~/components/icons/eye'
-import { Button } from '~/components/ui/button'
-import { APP } from '~/configs/meta'
-
-const AuthLayout = () => {
- const [showPassword, setShowPassword] = useState(false)
-
- return (
-
-
-
-
-

-
-
-
- Selamat Datang, silakan masukkan akun Anda untuk melanjutkan!
-
-
-
- {/* Link Daftar */}
-
- Belum punya akun?{' '}
-
-
-
- )
-}
+const AuthLayout = () =>
export default AuthLayout
diff --git a/app/routes/_admin.lg-admin._dashboard._index.tsx b/app/routes/_admin.lg-admin._dashboard._index.tsx
index 7fc1b2d..23875ef 100644
--- a/app/routes/_admin.lg-admin._dashboard._index.tsx
+++ b/app/routes/_admin.lg-admin._dashboard._index.tsx
@@ -1,6 +1,4 @@
import { DashboardPage } from '~/pages/dashboard'
-const DashboardIndexLayout = () => {
- return
-}
+const DashboardIndexLayout = () =>
export default DashboardIndexLayout
diff --git a/app/routes/_admin.lg-admin._dashboard.admins.tsx b/app/routes/_admin.lg-admin._dashboard.admins.tsx
index 9173750..312cc47 100644
--- a/app/routes/_admin.lg-admin._dashboard.admins.tsx
+++ b/app/routes/_admin.lg-admin._dashboard.admins.tsx
@@ -1,4 +1,2 @@
-const DashboardAdminsLayout = () => {
- return Admins Page
-}
+const DashboardAdminsLayout = () => Admins Page
export default DashboardAdminsLayout
diff --git a/app/routes/_admin.lg-admin._dashboard.advertisements.tsx b/app/routes/_admin.lg-admin._dashboard.advertisements.tsx
index d452a18..5bd076d 100644
--- a/app/routes/_admin.lg-admin._dashboard.advertisements.tsx
+++ b/app/routes/_admin.lg-admin._dashboard.advertisements.tsx
@@ -1,6 +1,4 @@
import { AdvertisementsPage } from '~/pages/dashboard-advertisements'
-const DashboardAdvertisementsLayout = () => {
- return
-}
+const DashboardAdvertisementsLayout = () =>
export default DashboardAdvertisementsLayout
diff --git a/app/routes/_admin.lg-admin._dashboard.contents.tsx b/app/routes/_admin.lg-admin._dashboard.contents.tsx
index 081af43..f0d4595 100644
--- a/app/routes/_admin.lg-admin._dashboard.contents.tsx
+++ b/app/routes/_admin.lg-admin._dashboard.contents.tsx
@@ -1,6 +1,4 @@
import { ContentsPage } from '~/pages/dashboard-contents'
-const DashboardContentsLayout = () => {
- return
-}
+const DashboardContentsLayout = () =>
export default DashboardContentsLayout
diff --git a/app/routes/_admin.lg-admin._dashboard.settings.tsx b/app/routes/_admin.lg-admin._dashboard.settings.tsx
index 52fbb11..4e2632a 100644
--- a/app/routes/_admin.lg-admin._dashboard.settings.tsx
+++ b/app/routes/_admin.lg-admin._dashboard.settings.tsx
@@ -1,4 +1,2 @@
-const DashboardSettingsLayout = () => {
- return Settings Page
-}
+const DashboardSettingsLayout = () => Settings Page
export default DashboardSettingsLayout
diff --git a/app/routes/_admin.lg-admin._dashboard.site-data.tsx b/app/routes/_admin.lg-admin._dashboard.site-data.tsx
index 78a0838..3c0702f 100644
--- a/app/routes/_admin.lg-admin._dashboard.site-data.tsx
+++ b/app/routes/_admin.lg-admin._dashboard.site-data.tsx
@@ -1,4 +1,2 @@
-const DashboardSiteDataLayout = () => {
- return Site Data Page
-}
+const DashboardSiteDataLayout = () => Site Data Page
export default DashboardSiteDataLayout
diff --git a/app/routes/_admin.lg-admin._dashboard.subscriptions.tsx b/app/routes/_admin.lg-admin._dashboard.subscriptions.tsx
index fdff80d..de9e320 100644
--- a/app/routes/_admin.lg-admin._dashboard.subscriptions.tsx
+++ b/app/routes/_admin.lg-admin._dashboard.subscriptions.tsx
@@ -1,6 +1,4 @@
import { SubscriptionsPage } from '~/pages/dashboard-subscriptions'
-const DashboardSubscriptionsLayout = () => {
- return
-}
+const DashboardSubscriptionsLayout = () =>
export default DashboardSubscriptionsLayout
diff --git a/app/routes/_admin.lg-admin._dashboard.users.tsx b/app/routes/_admin.lg-admin._dashboard.users.tsx
index e3edc82..8c3838b 100644
--- a/app/routes/_admin.lg-admin._dashboard.users.tsx
+++ b/app/routes/_admin.lg-admin._dashboard.users.tsx
@@ -1,6 +1,4 @@
import { UsersPage } from '~/pages/dashboard-users'
-const DashboardUsersLayout = () => {
- return
-}
+const DashboardUsersLayout = () =>
export default DashboardUsersLayout
diff --git a/app/routes/_admin.lg-admin.tsx b/app/routes/_admin.lg-admin.tsx
index 6e75f52..5eb7a6f 100644
--- a/app/routes/_admin.lg-admin.tsx
+++ b/app/routes/_admin.lg-admin.tsx
@@ -1,6 +1,7 @@
-import { Outlet } from 'react-router'
+import { Outlet, redirect } from 'react-router'
import { getStaff } from '~/apis/admin/get-staff'
+import { AUTH_PAGES } from '~/configs/pages'
import { AdminProvider } from '~/contexts/admin'
import { AdminDefaultLayout } from '~/layouts/admin/default'
import { handleCookie } from '~/libs/cookies'
@@ -9,7 +10,14 @@ import type { Route } from './+types/_admin.lg-admin'
export const loader = async ({ request }: Route.LoaderArgs) => {
const { adminToken } = await handleCookie(request)
+ const { pathname } = new URL(request.url)
+ const isAuthPage = AUTH_PAGES.includes(pathname)
let adminData
+
+ if (!isAuthPage && !adminToken) {
+ throw redirect('/lg-admin/login')
+ }
+
if (adminToken) {
const { data } = await getStaff({
accessToken: adminToken,
diff --git a/app/routes/_layout._index.tsx b/app/routes/_layout._index.tsx
index 0038b88..ffa7627 100644
--- a/app/routes/_layout._index.tsx
+++ b/app/routes/_layout._index.tsx
@@ -1,7 +1,5 @@
import { NewsPage } from '~/pages/news'
-const NewsIndexLayout = () => {
- return
-}
+const NewsIndexLayout = () =>
export default NewsIndexLayout
diff --git a/app/routes/_layout.category.$name.tsx b/app/routes/_layout.category.$name.tsx
index a0fdb3b..ac046f3 100644
--- a/app/routes/_layout.category.$name.tsx
+++ b/app/routes/_layout.category.$name.tsx
@@ -1,7 +1,5 @@
import { NewsCategoriesPage } from '~/pages/news-categories'
-const NewsCategoriesLayout = () => {
- return
-}
+const NewsCategoriesLayout = () =>
export default NewsCategoriesLayout
diff --git a/app/routes/_layout.detail.$slug.tsx b/app/routes/_layout.detail.$slug.tsx
index 93d567b..8bbc788 100644
--- a/app/routes/_layout.detail.$slug.tsx
+++ b/app/routes/_layout.detail.$slug.tsx
@@ -1,7 +1,5 @@
import { NewsDetailPage } from '~/pages/news-detail'
-const NewsDetailLayout = () => {
- return
-}
+const NewsDetailLayout = () =>
export default NewsDetailLayout
diff --git a/app/routes/actions.admin.login.ts b/app/routes/actions.admin.login.ts
new file mode 100644
index 0000000..6923511
--- /dev/null
+++ b/app/routes/actions.admin.login.ts
@@ -0,0 +1,72 @@
+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 { userLoginRequest } from '~/apis/news/login-user'
+import { loginSchema, type TLoginSchema } from '~/layouts/news/form-login'
+import { generateTokenCookie } from '~/utils/token'
+
+import type { Route } from './+types/actions.login'
+
+export const action = async ({ request }: Route.ActionArgs) => {
+ try {
+ const {
+ errors,
+ data: payload,
+ receivedValues: defaultValues,
+ } = await getValidatedFormData(
+ request,
+ zodResolver(loginSchema),
+ false,
+ )
+
+ if (errors) {
+ return data({ success: false, errors, defaultValues }, { status: 400 })
+ }
+
+ const { data: loginData } = await userLoginRequest(payload)
+ const { token } = loginData
+ 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 },
+ )
+ }
+}