Files
imphnen-frontend-service/apps/qrcampaign/src/routes/_authenticated.tsx
T
maulanasdqnandClaude Opus 4.6 4240e8eb51 feat: migrate all 5 Vite apps from react-router to TanStack Router
Migrated backoffice, hackathon, dimentorin, gacha, qrcampaign, and
infra from custom react-router file-based routing to TanStack Router
file-based routing following the tanstack-frontend-best-practice
convention.

Key changes per app:
- New routes/ directory with __root.tsx, _public.tsx, _authenticated.tsx
- Auth guards via beforeLoad (replaces old middleware.ts)
- createFileRoute pattern for all page components
- TanStackRouterVite plugin in vite.config for auto route generation
- _components/_hooks folders colocated with routes (ignored by router)
- routeTree.gen.ts auto-generated on dev/build

Convention:
- _public/* routes redirect to dashboard if authenticated
- _authenticated/* routes redirect to /auth/login if not authenticated
- $param for dynamic segments (was [param] in old convention)
- _layout suffix for pathless layout routes

Removed:
- Old src/app/ directories from all apps
- Old src/middleware.ts files
- Custom convertPagesToRoute utility (no longer needed)
- react-router dependency usage (kept in package.json for shared libs)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 17:04:14 +07:00

47 lines
1.5 KiB
TypeScript

import { createFileRoute, Outlet, redirect } from '@tanstack/react-router'
import { useAuthStore } from '../app/features/auth/store/auth.store'
import { Sidebar } from '../components/Sidebar'
import { MenuOutlined } from '@ant-design/icons'
import { useState } from 'react'
export const Route = createFileRoute('/_authenticated')({
beforeLoad: () => {
const { isAuthenticated } = useAuthStore.getState()
if (!isAuthenticated) {
throw redirect({ to: '/auth/login' })
}
},
component: AuthenticatedLayout,
})
function AuthenticatedLayout() {
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false)
return (
<div className="flex min-h-screen bg-gray-50">
<Sidebar
isOpen={mobileSidebarOpen}
onClose={() => setMobileSidebarOpen(false)}
/>
<div className="flex-1 flex flex-col min-w-0 overflow-hidden">
<header className="lg:hidden bg-white border-b border-gray-200 px-4 py-3 flex items-center justify-between sticky top-0 z-30">
<div className="flex items-center gap-3">
<button
onClick={() => setMobileSidebarOpen(true)}
className="p-2 -ml-2 rounded-md hover:bg-gray-100 text-gray-700"
>
<MenuOutlined className="text-lg" />
</button>
<h1 className="font-semibold text-gray-900">QR Campaign</h1>
</div>
</header>
<main className="flex-1 overflow-y-auto p-4 md:p-8">
<Outlet />
</main>
</div>
</div>
)
}