feat: restructure routing and layouts for admin and news sections, update cookie paths
This commit is contained in:
parent
4b8fc0721e
commit
23e3493a3f
@ -136,7 +136,7 @@ export const Carousel = (properties: TNews) => {
|
||||
},
|
||||
to: '',
|
||||
}
|
||||
: { as: Link, to: `/news/detail/${slug}` })}
|
||||
: { as: Link, to: `/detail/${slug}` })}
|
||||
className={twMerge('', type === 'hero' ? '' : 'mb-5')}
|
||||
>
|
||||
View More
|
||||
|
||||
@ -14,7 +14,7 @@ type TMetaTitleConfig = {
|
||||
|
||||
export const META_TITLE_CONFIG: TMetaTitleConfig = [
|
||||
{
|
||||
path: '/news',
|
||||
path: '/',
|
||||
title: 'Home',
|
||||
},
|
||||
{
|
||||
|
||||
@ -11,7 +11,7 @@ export const Navbar = () => {
|
||||
return (
|
||||
<div className="flex h-20 items-center justify-between border-b border-[#ECECEC] bg-white px-10 py-5">
|
||||
<Link
|
||||
to="/news"
|
||||
to="/"
|
||||
className="h-full"
|
||||
>
|
||||
<img
|
||||
|
||||
@ -9,7 +9,7 @@ export const FooterNewsletter = () => {
|
||||
<div className="col-span-2 hidden gap-y-6 sm:grid">
|
||||
<div className="h-[75px] bg-white p-3">
|
||||
<Link
|
||||
to="/news"
|
||||
to="/"
|
||||
className="h-full"
|
||||
>
|
||||
<img
|
||||
@ -44,7 +44,7 @@ export const FooterNewsletter = () => {
|
||||
<div className="block sm:hidden">
|
||||
<div className="h-[60px] bg-white p-3">
|
||||
<Link
|
||||
to="/news"
|
||||
to="/"
|
||||
className="h-full"
|
||||
>
|
||||
<img
|
||||
|
||||
@ -67,7 +67,7 @@ export const FormLogin = (properties: TProperties) => {
|
||||
method="post"
|
||||
onSubmit={handleSubmit}
|
||||
className="space-y-4"
|
||||
action="/actions/news/login"
|
||||
action="/actions/login"
|
||||
>
|
||||
<Input
|
||||
id="email"
|
||||
|
||||
@ -3,17 +3,17 @@ import { Link, useFetcher, useRouteLoaderData } from 'react-router'
|
||||
import { Button } from '~/components/ui/button'
|
||||
import { APP } from '~/configs/meta'
|
||||
import { useNewsContext } from '~/contexts/news'
|
||||
import type { loader } from '~/routes/_layout.news'
|
||||
import type { loader } from '~/routes/_layout'
|
||||
|
||||
export const HeaderTop = () => {
|
||||
const { setIsLoginOpen } = useNewsContext()
|
||||
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout.news')
|
||||
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout')
|
||||
const fetcher = useFetcher()
|
||||
|
||||
return (
|
||||
<div className="flex h-[60px] items-center justify-between bg-white px-5 align-middle sm:h-[100px] sm:gap-[15px] sm:px-[50px] sm:py-[20px]">
|
||||
<Link
|
||||
to="/news"
|
||||
to="/"
|
||||
className="mt-2 h-full py-2"
|
||||
>
|
||||
<img
|
||||
@ -32,7 +32,7 @@ export const HeaderTop = () => {
|
||||
{loaderData?.userToken ? (
|
||||
<fetcher.Form
|
||||
method="POST"
|
||||
action="/actions/news/logout"
|
||||
action="/actions/logout"
|
||||
>
|
||||
<Button
|
||||
variant="newsSecondary"
|
||||
|
||||
@ -21,31 +21,31 @@ type TFooterMenu = {
|
||||
export const MENU: TMenu[] = [
|
||||
{
|
||||
title: 'Spotlight',
|
||||
url: '/news/category/spotlight',
|
||||
url: '/category/spotlight',
|
||||
},
|
||||
{
|
||||
title: 'Berita',
|
||||
url: '/news/category/berita',
|
||||
url: '/category/berita',
|
||||
},
|
||||
{
|
||||
title: 'Kasus',
|
||||
url: '/news/category/kasus',
|
||||
url: '/category/kasus',
|
||||
},
|
||||
{
|
||||
title: 'Kajian',
|
||||
url: '/news/category/kajian',
|
||||
url: '/category/kajian',
|
||||
},
|
||||
{
|
||||
title: 'Lifestyle',
|
||||
url: '/news/category/lifestyle',
|
||||
url: '/category/lifestyle',
|
||||
},
|
||||
{
|
||||
title: 'Event',
|
||||
url: '/news/category/event',
|
||||
url: '/category/event',
|
||||
},
|
||||
{
|
||||
title: 'Travel',
|
||||
url: '/news/category/travel',
|
||||
url: '/category/travel',
|
||||
},
|
||||
]
|
||||
|
||||
@ -55,23 +55,23 @@ export const FOOTER_MENU: TFooterMenu[] = [
|
||||
items: [
|
||||
{
|
||||
title: 'Popular',
|
||||
url: '/news/list?sort=popular',
|
||||
url: '/list?sort=popular',
|
||||
},
|
||||
{
|
||||
title: 'Trending',
|
||||
url: '/news/list?sort=trending',
|
||||
url: '/list?sort=trending',
|
||||
},
|
||||
{
|
||||
title: 'Contact',
|
||||
url: '/news/contact',
|
||||
url: '/contact',
|
||||
},
|
||||
{
|
||||
title: 'Support/Help',
|
||||
url: '/news/support',
|
||||
url: '/support',
|
||||
},
|
||||
{
|
||||
title: 'Rquest Topic',
|
||||
url: '/news/request-topic',
|
||||
url: '/request-topic',
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -80,23 +80,23 @@ export const FOOTER_MENU: TFooterMenu[] = [
|
||||
items: [
|
||||
{
|
||||
title: 'FAQs',
|
||||
url: '/news/faq',
|
||||
url: '/faq',
|
||||
},
|
||||
{
|
||||
title: 'Terms and Condition',
|
||||
url: '/news/terms-condition',
|
||||
url: '/terms-condition',
|
||||
},
|
||||
{
|
||||
title: 'Support',
|
||||
url: '/news/support',
|
||||
url: '/support',
|
||||
},
|
||||
{
|
||||
title: 'Link Nine',
|
||||
url: '/news',
|
||||
url: '/',
|
||||
},
|
||||
{
|
||||
title: 'Link Ten',
|
||||
url: '/news',
|
||||
url: '/',
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -130,14 +130,14 @@ export const FOOTER_MENU: TFooterMenu[] = [
|
||||
export const COPYRIGHT_MENU: TMenu[] = [
|
||||
{
|
||||
title: 'Privacy Policy',
|
||||
url: '/news/privacy-policy',
|
||||
url: '/privacy-policy',
|
||||
},
|
||||
{
|
||||
title: 'Terms of Service',
|
||||
url: '/news/terms-of-service',
|
||||
url: '/terms-of-service',
|
||||
},
|
||||
{
|
||||
title: 'Cookies Settings',
|
||||
url: '/news/cookies-settings',
|
||||
url: '/cookies-settings',
|
||||
},
|
||||
]
|
||||
|
||||
@ -7,7 +7,7 @@ export const userTokenCookieConfig = createCookie(USER_COOKIES.token, {
|
||||
sameSite: 'lax',
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
secrets: [process.env.VITE_SALT_KEY || 'default-secret'],
|
||||
path: '/news',
|
||||
path: '/',
|
||||
})
|
||||
|
||||
export const adminTokenCookieConfig = createCookie(ADMIN_COOKIES.token, {
|
||||
|
||||
@ -4,7 +4,7 @@ export const setUserLogoutHeaders = () => {
|
||||
const responseHeaders = new Headers()
|
||||
responseHeaders.append(
|
||||
'Set-Cookie',
|
||||
`${USER_COOKIES.token}=; Path=/news; HttpOnly; SameSite=Strict; Max-Age=0`,
|
||||
`${USER_COOKIES.token}=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0`,
|
||||
)
|
||||
|
||||
return responseHeaders
|
||||
|
||||
11
app/root.tsx
11
app/root.tsx
@ -6,7 +6,6 @@ import {
|
||||
Outlet,
|
||||
Scripts,
|
||||
ScrollRestoration,
|
||||
type ShouldRevalidateFunctionArgs,
|
||||
} from 'react-router'
|
||||
|
||||
import type { Route } from './+types/root'
|
||||
@ -37,16 +36,6 @@ export const meta = ({ location }: Route.MetaArgs) => {
|
||||
]
|
||||
}
|
||||
|
||||
export const shouldRevalidate = ({
|
||||
actionResult,
|
||||
defaultShouldRevalidate,
|
||||
}: ShouldRevalidateFunctionArgs) => {
|
||||
if (actionResult?.success) {
|
||||
return true
|
||||
}
|
||||
return defaultShouldRevalidate
|
||||
}
|
||||
|
||||
export const Layout = ({ children }: { children: ReactNode }) => {
|
||||
return (
|
||||
<html lang="en">
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { redirect } from 'react-router'
|
||||
import { NewsPage } from '~/pages/news'
|
||||
|
||||
export async function loader() {
|
||||
return redirect('/news')
|
||||
const NewsIndexLayout = () => {
|
||||
return <NewsPage />
|
||||
}
|
||||
|
||||
export default NewsIndexLayout
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
import { NewsPage } from '~/pages/news'
|
||||
|
||||
const NewsIndexLayout = () => {
|
||||
return <NewsPage />
|
||||
}
|
||||
|
||||
export default NewsIndexLayout
|
||||
@ -4,7 +4,7 @@ import { NewsProvider } from '~/contexts/news'
|
||||
import { NewsDefaultLayout } from '~/layouts/news/default'
|
||||
import { handleCookie } from '~/libs/cookies'
|
||||
|
||||
import type { Route } from './+types/_layout.news'
|
||||
import type { Route } from './+types/_layout'
|
||||
|
||||
export const loader = async ({ request }: Route.LoaderArgs) => {
|
||||
const { userToken } = await handleCookie(request)
|
||||
@ -7,7 +7,7 @@ import { newsLoginRequest } from '~/apis/news/login'
|
||||
import { loginSchema, type TLoginSchema } from '~/layouts/news/form-login'
|
||||
import { generateTokenCookie } from '~/utils/token'
|
||||
|
||||
import type { Route } from './+types/actions.news.login'
|
||||
import type { Route } from './+types/actions.login'
|
||||
|
||||
export const action = async ({ request }: Route.ActionArgs) => {
|
||||
try {
|
||||
@ -46,14 +46,22 @@ export const action = async ({ request }: Route.ActionArgs) => {
|
||||
)
|
||||
} catch (error) {
|
||||
if (error instanceof XiorError) {
|
||||
return data({
|
||||
success: false,
|
||||
message: error?.response?.data?.error?.message || error.message,
|
||||
})
|
||||
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',
|
||||
})
|
||||
return data(
|
||||
{
|
||||
success: false,
|
||||
message: 'Internal server error',
|
||||
},
|
||||
{ status: 500 },
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,5 @@ export default defineConfig({
|
||||
plugins: [tailwindcss(), reactRouter(), tsconfigPaths()],
|
||||
build: {
|
||||
cssMinify: true,
|
||||
ssr: false,
|
||||
},
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user