323 lines
7.8 KiB
TypeScript
323 lines
7.8 KiB
TypeScript
import { createRootRoute, createRoute, createRouter, RouterProvider, Outlet, redirect, useLocation } from "@tanstack/react-router"
|
|
import Dashboard from "./pages/Dashboard"
|
|
import Login from "./pages/Login"
|
|
import ForgotPassword from "./pages/ForgotPassword"
|
|
import ResetPassword from "./pages/ResetPassword"
|
|
import TimeEntries from "./pages/TimeEntries"
|
|
import Customers from "./pages/Customers"
|
|
import CustomerDetail from "./pages/CustomerDetail"
|
|
import Projects from "./pages/Projects"
|
|
import ProjectDetail from "./pages/ProjectDetail"
|
|
import Profile from "./pages/Profile"
|
|
import AdminUsers from "./pages/AdminUsers"
|
|
import Settings from "./pages/Settings"
|
|
import Calendar from "./pages/Calendar"
|
|
import AuditLog from "./pages/AuditLog"
|
|
import Documents from "./pages/Documents"
|
|
import Webhooks from "./pages/Webhooks"
|
|
import TwoFactorAuth from "./pages/TwoFactorAuth"
|
|
import Billing from "./pages/Billing"
|
|
import Integrations from "./pages/Integrations"
|
|
import ProjectTemplates from "./pages/ProjectTemplates"
|
|
import TimeEntryTemplates from "./pages/TimeEntryTemplates"
|
|
import Invoices from "./pages/Invoices"
|
|
import ApiKeys from "./pages/ApiKeys"
|
|
import AcceptInvite from "./pages/AcceptInvite"
|
|
import Holidays from "./pages/Holidays"
|
|
import RolePermissions from "./pages/RolePermissions"
|
|
import NotFound from "./pages/NotFound"
|
|
import Nav from "./components/Nav"
|
|
import CommandPalette from "./components/CommandPalette"
|
|
import KeyboardHelp from "./components/KeyboardHelp"
|
|
import OnboardingTour from "./components/OnboardingTour"
|
|
import VersionBadge from "./components/VersionBadge"
|
|
import QuickAdd from "./components/QuickAdd"
|
|
import IdleDetector from "./components/IdleDetector"
|
|
import UndoStack from "./components/UndoStack"
|
|
import ApiErrorBanner from "./components/ApiErrorBanner"
|
|
import { ToastProvider } from "./components/Toast"
|
|
import ErrorBoundary from "./components/ErrorBoundary"
|
|
import { api } from "./lib/api"
|
|
|
|
const rootRoute = createRootRoute({
|
|
component: () => {
|
|
const location = useLocation()
|
|
return (
|
|
<ToastProvider>
|
|
<div className="min-h-screen flex flex-col bg-slate-50">
|
|
<div className="flex-grow">
|
|
<IdleDetector />
|
|
<Nav />
|
|
<ApiErrorBanner />
|
|
<CommandPalette />
|
|
<KeyboardHelp />
|
|
<OnboardingTour />
|
|
<QuickAdd />
|
|
<UndoStack />
|
|
<div className="page-enter" key={location.pathname}>
|
|
<Outlet />
|
|
</div>
|
|
</div>
|
|
<footer className="border-t bg-white py-2 text-center">
|
|
<VersionBadge />
|
|
</footer>
|
|
</div>
|
|
</ToastProvider>
|
|
)
|
|
}
|
|
})
|
|
|
|
const loginRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/login",
|
|
component: Login
|
|
})
|
|
|
|
const forgotPasswordRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/forgot-password",
|
|
component: ForgotPassword
|
|
})
|
|
|
|
const resetPasswordRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/reset-password",
|
|
component: ResetPassword
|
|
})
|
|
|
|
const acceptInviteRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/accept-invite",
|
|
component: AcceptInvite
|
|
})
|
|
|
|
const authCheck = async () => {
|
|
try {
|
|
await api.getMe()
|
|
} catch (error: any) {
|
|
if (error.status === 401) {
|
|
throw redirect({ to: "/login" })
|
|
}
|
|
}
|
|
}
|
|
|
|
const adminCheck = async () => {
|
|
try {
|
|
const user = await api.getMe()
|
|
if (user.role !== "admin") {
|
|
throw redirect({ to: "/" })
|
|
}
|
|
} catch (error: any) {
|
|
if (error.status === 401) {
|
|
throw redirect({ to: "/login" })
|
|
} else if (error.status === 302 || error.status === 403) {
|
|
throw error
|
|
}
|
|
throw redirect({ to: "/" })
|
|
}
|
|
}
|
|
|
|
const indexRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/",
|
|
beforeLoad: authCheck,
|
|
component: Dashboard
|
|
})
|
|
|
|
const timeEntriesRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/time-entries",
|
|
beforeLoad: authCheck,
|
|
component: TimeEntries
|
|
})
|
|
|
|
const timeEntryTemplatesRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/time-entry-templates",
|
|
beforeLoad: authCheck,
|
|
component: TimeEntryTemplates
|
|
})
|
|
|
|
const customersRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/customers",
|
|
beforeLoad: authCheck,
|
|
component: Customers
|
|
})
|
|
|
|
const customerDetailRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/customers/$customerId",
|
|
beforeLoad: authCheck,
|
|
component: CustomerDetail
|
|
})
|
|
|
|
const projectsRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/projects",
|
|
beforeLoad: authCheck,
|
|
component: Projects
|
|
})
|
|
|
|
const projectDetailRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/projects/$projectId",
|
|
beforeLoad: authCheck,
|
|
component: ProjectDetail
|
|
})
|
|
|
|
const projectTemplatesRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/project-templates",
|
|
beforeLoad: authCheck,
|
|
component: ProjectTemplates
|
|
})
|
|
|
|
const profileRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/profile",
|
|
beforeLoad: authCheck,
|
|
component: Profile
|
|
})
|
|
|
|
const settingsRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/settings",
|
|
beforeLoad: authCheck,
|
|
component: Settings
|
|
})
|
|
|
|
const twoFactorRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/settings/2fa",
|
|
beforeLoad: authCheck,
|
|
component: TwoFactorAuth
|
|
})
|
|
|
|
const apiKeysRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/settings/api-keys",
|
|
beforeLoad: authCheck,
|
|
component: ApiKeys
|
|
})
|
|
|
|
const calendarRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/calendar",
|
|
beforeLoad: authCheck,
|
|
component: Calendar
|
|
})
|
|
|
|
const holidaysRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/holidays",
|
|
beforeLoad: authCheck,
|
|
component: Holidays
|
|
})
|
|
|
|
const invoicesRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/invoices",
|
|
beforeLoad: authCheck,
|
|
component: Invoices
|
|
})
|
|
|
|
const billingRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/billing",
|
|
beforeLoad: authCheck,
|
|
component: Billing
|
|
})
|
|
|
|
const integrationsRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/integrations",
|
|
beforeLoad: authCheck,
|
|
component: Integrations
|
|
})
|
|
|
|
const documentsRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/documents",
|
|
beforeLoad: authCheck,
|
|
component: Documents
|
|
})
|
|
|
|
const webhooksRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/webhooks",
|
|
beforeLoad: authCheck,
|
|
component: Webhooks
|
|
})
|
|
|
|
const adminUsersRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/admin/users",
|
|
beforeLoad: adminCheck,
|
|
component: AdminUsers
|
|
})
|
|
|
|
const rolePermissionsRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/admin/permissions",
|
|
beforeLoad: adminCheck,
|
|
component: RolePermissions
|
|
})
|
|
|
|
const auditLogRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/admin/audit-log",
|
|
beforeLoad: adminCheck,
|
|
component: AuditLog
|
|
})
|
|
|
|
const notFoundRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "*",
|
|
component: NotFound
|
|
})
|
|
|
|
const routeTree = [
|
|
indexRoute,
|
|
loginRoute,
|
|
forgotPasswordRoute,
|
|
resetPasswordRoute,
|
|
acceptInviteRoute,
|
|
timeEntriesRoute,
|
|
timeEntryTemplatesRoute,
|
|
customersRoute,
|
|
customerDetailRoute,
|
|
projectsRoute,
|
|
projectDetailRoute,
|
|
projectTemplatesRoute,
|
|
profileRoute,
|
|
settingsRoute,
|
|
twoFactorRoute,
|
|
apiKeysRoute,
|
|
calendarRoute,
|
|
holidaysRoute,
|
|
invoicesRoute,
|
|
billingRoute,
|
|
integrationsRoute,
|
|
documentsRoute,
|
|
webhooksRoute,
|
|
adminUsersRoute,
|
|
rolePermissionsRoute,
|
|
auditLogRoute,
|
|
notFoundRoute
|
|
]
|
|
|
|
const router = createRouter({
|
|
routeTree,
|
|
defaultPreload: 'intent'
|
|
})
|
|
|
|
declare module "@tanstack/react-router" {
|
|
interface Register {
|
|
router: typeof router
|
|
}
|
|
}
|
|
|
|
export default function App() {
|
|
return <RouterProvider router={router} />
|
|
} |