feat(lst): tan stack routes added with protected routes
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"types": [
|
||||
{ "type": "feat", "section": "🌟 Enhancements" },
|
||||
{ "type": "fix", "section": "🐛 Bug fixes" },
|
||||
{ "type": "chore", "hidden": false, "section": "📝 Chore" },
|
||||
{ "type": "docs", "section": "📚 Documentation" },
|
||||
{ "type": "style", "hidden": true },
|
||||
{ "type": "refactor", "section": "🛠️ Code Refactor" },
|
||||
{ "type": "perf", "hidden": false, "section": "🚀 Code Refactor" },
|
||||
{ "type": "test", "section": "📝 Testing Code" },
|
||||
{ "type": "ci", "section": "📈 Project changes" }
|
||||
],
|
||||
"commitUrlFormat": "https://git.tuffraid.net/cowch/Lst_Backend/commits{{hash}}",
|
||||
"compareUrlFormat": "https://git.tuffraid.net/cowch/Lst_Backend/compare/{{previousTag}}...{{currentTag}}",
|
||||
"header": "# All notable changes to the LST project will be documented in this file.\n`"
|
||||
"types": [
|
||||
{"type": "feat", "section": "🌟 Enhancements"},
|
||||
{"type": "fix", "section": "🐛 Bug fixes"},
|
||||
{"type": "chore", "hidden": false, "section": "📝 Chore"},
|
||||
{"type": "docs", "section": "📚 Documentation"},
|
||||
{"type": "style", "hidden": true},
|
||||
{"type": "refactor", "section": "🛠️ Code Refactor"},
|
||||
{"type": "perf", "hidden": false, "section": "🚀 Code Refactor"},
|
||||
{"type": "test", "section": "📝 Testing Code"},
|
||||
{"type": "ci", "section": "📈 Project changes"}
|
||||
],
|
||||
"commitUrlFormat": "https://git.tuffraid.net/cowch/lstV2/commits{{hash}}",
|
||||
"compareUrlFormat": "https://git.tuffraid.net/cowch/lstV2/compare/{{previousTag}}...{{currentTag}}",
|
||||
"header": "# All CHanges to LST can be found below.\n`"
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React + TS</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/lst.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Logistics Support Tool</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"@radix-ui/react-slot": "^1.1.2",
|
||||
"@tailwindcss/vite": "^4.0.6",
|
||||
"@tanstack/react-query": "^5.66.5",
|
||||
"@tanstack/react-router": "^1.106.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.475.0",
|
||||
@@ -27,6 +28,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.19.0",
|
||||
"@tanstack/router-devtools": "^1.106.0",
|
||||
"@tanstack/router-plugin": "^1.106.0",
|
||||
"@types/node": "^22.13.4",
|
||||
"@types/react": "^19.0.8",
|
||||
"@types/react-dom": "^19.0.3",
|
||||
|
||||
BIN
frontend/public/lst.ico
Normal file
BIN
frontend/public/lst.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@@ -1,31 +0,0 @@
|
||||
import LoginForm from "./components/LoginForm";
|
||||
import {Button} from "./components/ui/button";
|
||||
import {useSession} from "./lib/hooks/useSession";
|
||||
import {useLogout} from "./lib/hooks/useLogout";
|
||||
import "./styles.css";
|
||||
|
||||
function App() {
|
||||
const {session, status} = useSession();
|
||||
const logout = useLogout();
|
||||
|
||||
if (!session || status === "error") {
|
||||
return (
|
||||
<p>
|
||||
no session please login <LoginForm />
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* <p>Logged in user: {session.user.username}</p> */}
|
||||
<>Session: {JSON.stringify(session)}</>
|
||||
<p>Status: {JSON.stringify(status)}</p>
|
||||
<p>
|
||||
<Button onClick={() => logout()}>Logout</Button>
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
@@ -1,5 +1,5 @@
|
||||
import {useState} from "react";
|
||||
import {useSessionStore} from "../lib/store/sessionStore";
|
||||
import {useSessionStore} from "../../lib/store/sessionStore";
|
||||
import {useQueryClient} from "@tanstack/react-query";
|
||||
|
||||
const LoginForm = () => {
|
||||
@@ -36,7 +36,7 @@ const LoginForm = () => {
|
||||
setSession(data.data.token);
|
||||
|
||||
// Refetch the session data to reflect the logged-in state
|
||||
queryClient.invalidateQueries(["session"]);
|
||||
queryClient.invalidateQueries();
|
||||
|
||||
setUsername("");
|
||||
setPassword("");
|
||||
@@ -15,7 +15,7 @@ const fetchSession = async () => {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
console.log(res);
|
||||
// console.log(res);
|
||||
if (!res.ok) {
|
||||
throw new Error("Session not found");
|
||||
}
|
||||
@@ -31,7 +31,7 @@ export const useSession = () => {
|
||||
queryKey: ["session"],
|
||||
queryFn: fetchSession,
|
||||
enabled: !!token, // Prevents query if token is null
|
||||
staleTime: 5 * 60 * 1000, // 5 mins
|
||||
staleTime: 60 * 1000,
|
||||
gcTime: 10 * 60 * 1000, // 10 mins
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
@@ -47,3 +47,5 @@ export const useSession = () => {
|
||||
|
||||
return {session: data && token ? {user: data.user, token: data.token} : null, status, error};
|
||||
};
|
||||
|
||||
export type SessionType = ReturnType<typeof useSession>;
|
||||
|
||||
@@ -1,13 +1,38 @@
|
||||
import {StrictMode} from "react";
|
||||
import {createRoot} from "react-dom/client";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import "./styles.css";
|
||||
import App from "./App.tsx";
|
||||
import {SessionProvider} from "./components/providers/Providers.tsx";
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<SessionProvider>
|
||||
<App />
|
||||
</SessionProvider>
|
||||
</StrictMode>
|
||||
);
|
||||
import {SessionProvider} from "./components/providers/Providers.tsx";
|
||||
import {RouterProvider, createRouter} from "@tanstack/react-router";
|
||||
|
||||
// Import the generated route tree
|
||||
import {routeTree} from "./routeTree.gen";
|
||||
import {useSession} from "./lib/hooks/useSession.ts";
|
||||
|
||||
// Create a new router instance
|
||||
const router = createRouter({routeTree, context: {sessionType: undefined!}});
|
||||
|
||||
// Register the router instance for type safety
|
||||
declare module "@tanstack/react-router" {
|
||||
interface Register {
|
||||
router: typeof router;
|
||||
}
|
||||
}
|
||||
|
||||
function App() {
|
||||
const sessionType = useSession();
|
||||
return <RouterProvider router={router} context={{sessionType}} />;
|
||||
}
|
||||
|
||||
// Render the app
|
||||
const rootElement = document.getElementById("root")!;
|
||||
if (!rootElement.innerHTML) {
|
||||
const root = ReactDOM.createRoot(rootElement);
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<SessionProvider>
|
||||
<App />
|
||||
</SessionProvider>
|
||||
</StrictMode>
|
||||
);
|
||||
}
|
||||
|
||||
311
frontend/src/routeTree.gen.ts
Normal file
311
frontend/src/routeTree.gen.ts
Normal file
@@ -0,0 +1,311 @@
|
||||
/* eslint-disable */
|
||||
|
||||
// @ts-nocheck
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
// This file was automatically generated by TanStack Router.
|
||||
// You should NOT make any changes in this file as it will be overwritten.
|
||||
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
||||
|
||||
// Import Routes
|
||||
|
||||
import { Route as rootRoute } from './routes/__root'
|
||||
import { Route as LoginImport } from './routes/login'
|
||||
import { Route as AboutImport } from './routes/about'
|
||||
import { Route as AuthImport } from './routes/_auth'
|
||||
import { Route as IndexImport } from './routes/index'
|
||||
import { Route as OcpIndexImport } from './routes/ocp/index'
|
||||
import { Route as OcpLotsImport } from './routes/ocp/lots'
|
||||
import { Route as OcpLineIDImport } from './routes/ocp/$lineID'
|
||||
import { Route as AuthProfileImport } from './routes/_auth/profile'
|
||||
import { Route as AuthDashboardImport } from './routes/_auth/dashboard'
|
||||
|
||||
// Create/Update Routes
|
||||
|
||||
const LoginRoute = LoginImport.update({
|
||||
id: '/login',
|
||||
path: '/login',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const AboutRoute = AboutImport.update({
|
||||
id: '/about',
|
||||
path: '/about',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const AuthRoute = AuthImport.update({
|
||||
id: '/_auth',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const IndexRoute = IndexImport.update({
|
||||
id: '/',
|
||||
path: '/',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const OcpIndexRoute = OcpIndexImport.update({
|
||||
id: '/ocp/',
|
||||
path: '/ocp/',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const OcpLotsRoute = OcpLotsImport.update({
|
||||
id: '/ocp/lots',
|
||||
path: '/ocp/lots',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const OcpLineIDRoute = OcpLineIDImport.update({
|
||||
id: '/ocp/$lineID',
|
||||
path: '/ocp/$lineID',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const AuthProfileRoute = AuthProfileImport.update({
|
||||
id: '/profile',
|
||||
path: '/profile',
|
||||
getParentRoute: () => AuthRoute,
|
||||
} as any)
|
||||
|
||||
const AuthDashboardRoute = AuthDashboardImport.update({
|
||||
id: '/dashboard',
|
||||
path: '/dashboard',
|
||||
getParentRoute: () => AuthRoute,
|
||||
} as any)
|
||||
|
||||
// Populate the FileRoutesByPath interface
|
||||
|
||||
declare module '@tanstack/react-router' {
|
||||
interface FileRoutesByPath {
|
||||
'/': {
|
||||
id: '/'
|
||||
path: '/'
|
||||
fullPath: '/'
|
||||
preLoaderRoute: typeof IndexImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/_auth': {
|
||||
id: '/_auth'
|
||||
path: ''
|
||||
fullPath: ''
|
||||
preLoaderRoute: typeof AuthImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/about': {
|
||||
id: '/about'
|
||||
path: '/about'
|
||||
fullPath: '/about'
|
||||
preLoaderRoute: typeof AboutImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/login': {
|
||||
id: '/login'
|
||||
path: '/login'
|
||||
fullPath: '/login'
|
||||
preLoaderRoute: typeof LoginImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/_auth/dashboard': {
|
||||
id: '/_auth/dashboard'
|
||||
path: '/dashboard'
|
||||
fullPath: '/dashboard'
|
||||
preLoaderRoute: typeof AuthDashboardImport
|
||||
parentRoute: typeof AuthImport
|
||||
}
|
||||
'/_auth/profile': {
|
||||
id: '/_auth/profile'
|
||||
path: '/profile'
|
||||
fullPath: '/profile'
|
||||
preLoaderRoute: typeof AuthProfileImport
|
||||
parentRoute: typeof AuthImport
|
||||
}
|
||||
'/ocp/$lineID': {
|
||||
id: '/ocp/$lineID'
|
||||
path: '/ocp/$lineID'
|
||||
fullPath: '/ocp/$lineID'
|
||||
preLoaderRoute: typeof OcpLineIDImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/ocp/lots': {
|
||||
id: '/ocp/lots'
|
||||
path: '/ocp/lots'
|
||||
fullPath: '/ocp/lots'
|
||||
preLoaderRoute: typeof OcpLotsImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/ocp/': {
|
||||
id: '/ocp/'
|
||||
path: '/ocp'
|
||||
fullPath: '/ocp'
|
||||
preLoaderRoute: typeof OcpIndexImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create and export the route tree
|
||||
|
||||
interface AuthRouteChildren {
|
||||
AuthDashboardRoute: typeof AuthDashboardRoute
|
||||
AuthProfileRoute: typeof AuthProfileRoute
|
||||
}
|
||||
|
||||
const AuthRouteChildren: AuthRouteChildren = {
|
||||
AuthDashboardRoute: AuthDashboardRoute,
|
||||
AuthProfileRoute: AuthProfileRoute,
|
||||
}
|
||||
|
||||
const AuthRouteWithChildren = AuthRoute._addFileChildren(AuthRouteChildren)
|
||||
|
||||
export interface FileRoutesByFullPath {
|
||||
'/': typeof IndexRoute
|
||||
'': typeof AuthRouteWithChildren
|
||||
'/about': typeof AboutRoute
|
||||
'/login': typeof LoginRoute
|
||||
'/dashboard': typeof AuthDashboardRoute
|
||||
'/profile': typeof AuthProfileRoute
|
||||
'/ocp/$lineID': typeof OcpLineIDRoute
|
||||
'/ocp/lots': typeof OcpLotsRoute
|
||||
'/ocp': typeof OcpIndexRoute
|
||||
}
|
||||
|
||||
export interface FileRoutesByTo {
|
||||
'/': typeof IndexRoute
|
||||
'': typeof AuthRouteWithChildren
|
||||
'/about': typeof AboutRoute
|
||||
'/login': typeof LoginRoute
|
||||
'/dashboard': typeof AuthDashboardRoute
|
||||
'/profile': typeof AuthProfileRoute
|
||||
'/ocp/$lineID': typeof OcpLineIDRoute
|
||||
'/ocp/lots': typeof OcpLotsRoute
|
||||
'/ocp': typeof OcpIndexRoute
|
||||
}
|
||||
|
||||
export interface FileRoutesById {
|
||||
__root__: typeof rootRoute
|
||||
'/': typeof IndexRoute
|
||||
'/_auth': typeof AuthRouteWithChildren
|
||||
'/about': typeof AboutRoute
|
||||
'/login': typeof LoginRoute
|
||||
'/_auth/dashboard': typeof AuthDashboardRoute
|
||||
'/_auth/profile': typeof AuthProfileRoute
|
||||
'/ocp/$lineID': typeof OcpLineIDRoute
|
||||
'/ocp/lots': typeof OcpLotsRoute
|
||||
'/ocp/': typeof OcpIndexRoute
|
||||
}
|
||||
|
||||
export interface FileRouteTypes {
|
||||
fileRoutesByFullPath: FileRoutesByFullPath
|
||||
fullPaths:
|
||||
| '/'
|
||||
| ''
|
||||
| '/about'
|
||||
| '/login'
|
||||
| '/dashboard'
|
||||
| '/profile'
|
||||
| '/ocp/$lineID'
|
||||
| '/ocp/lots'
|
||||
| '/ocp'
|
||||
fileRoutesByTo: FileRoutesByTo
|
||||
to:
|
||||
| '/'
|
||||
| ''
|
||||
| '/about'
|
||||
| '/login'
|
||||
| '/dashboard'
|
||||
| '/profile'
|
||||
| '/ocp/$lineID'
|
||||
| '/ocp/lots'
|
||||
| '/ocp'
|
||||
id:
|
||||
| '__root__'
|
||||
| '/'
|
||||
| '/_auth'
|
||||
| '/about'
|
||||
| '/login'
|
||||
| '/_auth/dashboard'
|
||||
| '/_auth/profile'
|
||||
| '/ocp/$lineID'
|
||||
| '/ocp/lots'
|
||||
| '/ocp/'
|
||||
fileRoutesById: FileRoutesById
|
||||
}
|
||||
|
||||
export interface RootRouteChildren {
|
||||
IndexRoute: typeof IndexRoute
|
||||
AuthRoute: typeof AuthRouteWithChildren
|
||||
AboutRoute: typeof AboutRoute
|
||||
LoginRoute: typeof LoginRoute
|
||||
OcpLineIDRoute: typeof OcpLineIDRoute
|
||||
OcpLotsRoute: typeof OcpLotsRoute
|
||||
OcpIndexRoute: typeof OcpIndexRoute
|
||||
}
|
||||
|
||||
const rootRouteChildren: RootRouteChildren = {
|
||||
IndexRoute: IndexRoute,
|
||||
AuthRoute: AuthRouteWithChildren,
|
||||
AboutRoute: AboutRoute,
|
||||
LoginRoute: LoginRoute,
|
||||
OcpLineIDRoute: OcpLineIDRoute,
|
||||
OcpLotsRoute: OcpLotsRoute,
|
||||
OcpIndexRoute: OcpIndexRoute,
|
||||
}
|
||||
|
||||
export const routeTree = rootRoute
|
||||
._addFileChildren(rootRouteChildren)
|
||||
._addFileTypes<FileRouteTypes>()
|
||||
|
||||
/* ROUTE_MANIFEST_START
|
||||
{
|
||||
"routes": {
|
||||
"__root__": {
|
||||
"filePath": "__root.tsx",
|
||||
"children": [
|
||||
"/",
|
||||
"/_auth",
|
||||
"/about",
|
||||
"/login",
|
||||
"/ocp/$lineID",
|
||||
"/ocp/lots",
|
||||
"/ocp/"
|
||||
]
|
||||
},
|
||||
"/": {
|
||||
"filePath": "index.tsx"
|
||||
},
|
||||
"/_auth": {
|
||||
"filePath": "_auth.tsx",
|
||||
"children": [
|
||||
"/_auth/dashboard",
|
||||
"/_auth/profile"
|
||||
]
|
||||
},
|
||||
"/about": {
|
||||
"filePath": "about.tsx"
|
||||
},
|
||||
"/login": {
|
||||
"filePath": "login.tsx"
|
||||
},
|
||||
"/_auth/dashboard": {
|
||||
"filePath": "_auth/dashboard.tsx",
|
||||
"parent": "/_auth"
|
||||
},
|
||||
"/_auth/profile": {
|
||||
"filePath": "_auth/profile.tsx",
|
||||
"parent": "/_auth"
|
||||
},
|
||||
"/ocp/$lineID": {
|
||||
"filePath": "ocp/$lineID.tsx"
|
||||
},
|
||||
"/ocp/lots": {
|
||||
"filePath": "ocp/lots.tsx"
|
||||
},
|
||||
"/ocp/": {
|
||||
"filePath": "ocp/index.tsx"
|
||||
}
|
||||
}
|
||||
}
|
||||
ROUTE_MANIFEST_END */
|
||||
42
frontend/src/routes/__root.tsx
Normal file
42
frontend/src/routes/__root.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import {createRootRouteWithContext, Link, Outlet} from "@tanstack/react-router";
|
||||
import {TanStackRouterDevtools} from "@tanstack/router-devtools";
|
||||
import {SessionType} from "../lib/hooks/useSession";
|
||||
|
||||
type RouterContext = {
|
||||
sessionType: SessionType;
|
||||
};
|
||||
// same as the layout
|
||||
export const Route = createRootRouteWithContext<RouterContext>()({
|
||||
component: () => {
|
||||
return (
|
||||
<>
|
||||
<div className="p-2 flex gap-2">
|
||||
<Link to="/" className="[&.active]:font-bold">
|
||||
Home
|
||||
</Link>{" "}
|
||||
<Link to="/about" className="[&.active]:font-bold">
|
||||
About
|
||||
</Link>
|
||||
<Link to="/dashboard" className="[&.active]:font-bold">
|
||||
dashboard
|
||||
</Link>
|
||||
<Link to="/profile" className="[&.active]:font-bold">
|
||||
{({isActive}) => <>Profile {isActive && "~"}</>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/ocp"
|
||||
search={{q: "1"}}
|
||||
activeProps={{style: {fontWeight: "bold"}}}
|
||||
className="[&.active]:font-bold"
|
||||
>
|
||||
{({isActive}) => <>OCP {isActive && "~"}</>}
|
||||
</Link>
|
||||
</div>
|
||||
<hr />
|
||||
<Outlet />
|
||||
|
||||
<TanStackRouterDevtools />
|
||||
</>
|
||||
);
|
||||
},
|
||||
});
|
||||
12
frontend/src/routes/_auth.tsx
Normal file
12
frontend/src/routes/_auth.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import {createFileRoute, redirect} from "@tanstack/react-router";
|
||||
|
||||
// src/routes/_authenticated.tsx
|
||||
export const Route = createFileRoute("/_auth")({
|
||||
beforeLoad: async ({context}) => {
|
||||
if (!context.sessionType.session) {
|
||||
throw redirect({
|
||||
to: "/",
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
9
frontend/src/routes/_auth/dashboard.tsx
Normal file
9
frontend/src/routes/_auth/dashboard.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/_auth/dashboard')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
function RouteComponent() {
|
||||
return <div>Hello "/_auth/dashboard"!</div>
|
||||
}
|
||||
9
frontend/src/routes/_auth/profile.tsx
Normal file
9
frontend/src/routes/_auth/profile.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import {createFileRoute} from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/_auth/profile")({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return <div>Hello "/profile"!</div>;
|
||||
}
|
||||
13
frontend/src/routes/about.tsx
Normal file
13
frontend/src/routes/about.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import {createFileRoute} from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/about")({
|
||||
component: About,
|
||||
});
|
||||
|
||||
function About() {
|
||||
return (
|
||||
<div className="m-auto">
|
||||
<h2>About page to come.</h2>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
29
frontend/src/routes/index.tsx
Normal file
29
frontend/src/routes/index.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import {createFileRoute} from "@tanstack/react-router";
|
||||
import LoginForm from "../components/auth/LoginForm";
|
||||
import {Button} from "../components/ui/button";
|
||||
import {useLogout} from "../lib/hooks/useLogout";
|
||||
import {useSession} from "../lib/hooks/useSession";
|
||||
|
||||
export const Route = createFileRoute("/")({
|
||||
component: Index,
|
||||
});
|
||||
|
||||
function Index() {
|
||||
const {session} = useSession();
|
||||
const logout = useLogout();
|
||||
return (
|
||||
<div className="p-2">
|
||||
<h3>Welcome Home!</h3>
|
||||
<br></br>
|
||||
<p>
|
||||
{session ? (
|
||||
<>
|
||||
<Button onClick={() => logout()}>Logout</Button>{" "}
|
||||
</>
|
||||
) : (
|
||||
<LoginForm />
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
38
frontend/src/routes/login.tsx
Normal file
38
frontend/src/routes/login.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import {createFileRoute, useRouter} from "@tanstack/react-router";
|
||||
import {isAuthenticated, signIn, signOut} from "../utils/auth";
|
||||
import {Button} from "../components/ui/button";
|
||||
|
||||
export const Route = createFileRoute("/login")({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const router = useRouter();
|
||||
return (
|
||||
<div>
|
||||
<h2>Ligin</h2>
|
||||
{isAuthenticated() ? (
|
||||
<>
|
||||
<p>Hello User!</p>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
signOut();
|
||||
router.invalidate();
|
||||
}}
|
||||
>
|
||||
signOut
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<Button
|
||||
onClick={async () => {
|
||||
signIn();
|
||||
router.invalidate();
|
||||
}}
|
||||
>
|
||||
Sign in
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
17
frontend/src/routes/ocp/$lineID.tsx
Normal file
17
frontend/src/routes/ocp/$lineID.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import {createFileRoute} from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/ocp/$lineID")({
|
||||
component: RouteComponent,
|
||||
loader: async ({params}) => {
|
||||
await new Promise((r) => setTimeout(r, 1500));
|
||||
//throw new Error();
|
||||
return {lineID: params.lineID};
|
||||
},
|
||||
pendingComponent: () => <div className="m-auto">Loading....</div>,
|
||||
errorComponent: () => <div className="m-auto">Error....</div>,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const {lineID} = Route.useLoaderData();
|
||||
return <div>Hello "/ocp/{lineID}"!</div>;
|
||||
}
|
||||
34
frontend/src/routes/ocp/index.tsx
Normal file
34
frontend/src/routes/ocp/index.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import {createFileRoute, Link} from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/ocp/")({
|
||||
component: RouteComponent,
|
||||
validateSearch: (search) => {
|
||||
return {
|
||||
q: (search.q as string) || "",
|
||||
};
|
||||
},
|
||||
loaderDeps: ({search: {q}}) => ({q}),
|
||||
loader: async ({deps: {q}}) => {
|
||||
return {line: q};
|
||||
},
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const {line} = Route.useLoaderData();
|
||||
|
||||
const lines = ["l", "2", "3"];
|
||||
return (
|
||||
<div>
|
||||
<h2>Hello "/ocp/{line}/something"!</h2>
|
||||
{lines.map((line) => {
|
||||
return (
|
||||
<div key={line}>
|
||||
<Link to="/ocp/$lineID" params={{lineID: line}}>
|
||||
Post
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
9
frontend/src/routes/ocp/lots.tsx
Normal file
9
frontend/src/routes/ocp/lots.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/ocp/lots')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
function RouteComponent() {
|
||||
return <div>Hello "/ocp/lots"!</div>
|
||||
}
|
||||
11
frontend/src/utils/auth.ts
Normal file
11
frontend/src/utils/auth.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export function isAuthenticated() {
|
||||
return localStorage.getItem("isAuthenticated") === "true";
|
||||
}
|
||||
|
||||
export function signIn() {
|
||||
return localStorage.setItem("isAuthenticated", "true");
|
||||
}
|
||||
|
||||
export function signOut() {
|
||||
return localStorage.removeItem("isAuthenticated");
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
import {defineConfig} from "vite";
|
||||
import react from "@vitejs/plugin-react-swc";
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
import {TanStackRouterVite} from "@tanstack/router-plugin/vite";
|
||||
import path from "path";
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react(), tailwindcss()],
|
||||
plugins: [react(), tailwindcss(), TanStackRouterVite({autoCodeSplitting: true})],
|
||||
// build: {
|
||||
// outDir: path.resolve(__dirname, "../../dist/frontend/dist"),
|
||||
// emptyOutDir: true,
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"build:server": "cd apps/server && bun build index.js --outdir ../../dist/server",
|
||||
"build:ocme": "rimraf dist/ocme && cd apps/ocme && bun build index.js --outdir ../../dist/ocme",
|
||||
"build:front": "cd frontend && rimraf frontend/dist && bun run build",
|
||||
"start": "bun --env-file .env run ./server/index.js",
|
||||
"start": "cd server && bun run --env-file ../.env ./index.js",
|
||||
"commit": "cz",
|
||||
"clean": "rimraf dist/server",
|
||||
"deploy": "standard-version --conventional-commits"
|
||||
|
||||
@@ -52,8 +52,8 @@ routes.forEach((route) => {
|
||||
// return c.json({success: true, message: "is authenticated"});
|
||||
// });
|
||||
|
||||
app.get("*", serveStatic({root: "./frontend/dist"}));
|
||||
app.get("*", serveStatic({path: "./frontend/dist/index.html"}));
|
||||
app.get("*", serveStatic({root: "../frontend/dist"}));
|
||||
app.get("*", serveStatic({path: "../frontend/dist/index.html"}));
|
||||
|
||||
export default app;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user