diff --git a/.gitignore b/.gitignore index 7b6caf34..25d51d80 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,6 @@ share/python-wheels/ .installed.cfg *.egg MANIFEST - # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. diff --git a/submit-web/.gitignore b/submit-web/.gitignore index a0e3b0fa..ecfdc93d 100644 --- a/submit-web/.gitignore +++ b/submit-web/.gitignore @@ -22,5 +22,4 @@ dist-ssr *.njsproj *.sln *.sw? - .idea diff --git a/submit-web/package.json b/submit-web/package.json index 46397bbc..cb180de4 100644 --- a/submit-web/package.json +++ b/submit-web/package.json @@ -17,15 +17,16 @@ "@mui/icons-material": "^5.15.21", "@mui/material": "^5.15.20", "@tanstack/react-query": "^5.45.1", + "@tanstack/react-router": "^1.44.4", "axios": "^1.7.2", "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router-dom": "^6.24.0" + "react-dom": "^18.2.0" }, "devDependencies": { "@tanstack/eslint-plugin-query": "^5.43.1", "@tanstack/react-query-devtools": "^5.45.1", - "@tanstack/router-devtools": "^1.39.4", + "@tanstack/router-devtools": "^1.44.4", + "@tanstack/router-plugin": "^1.44.3", "@tanstack/router-vite-plugin": "^1.39.5", "@types/node": "^20.14.9", "@types/react": "^18.2.66", diff --git a/submit-web/src/App.cy.tsx b/submit-web/src/App.cy.tsx index f7c26782..6237242f 100644 --- a/submit-web/src/App.cy.tsx +++ b/submit-web/src/App.cy.tsx @@ -1,14 +1,12 @@ -import React from 'react' -import App from './App' -import { BrowserRouter } from 'react-router-dom' +import { routeTree } from "./routeTree.gen.ts"; +import { createRouter, RouterProvider } from "@tanstack/react-router"; -describe('', () => { - it('renders', () => { +// Create a new router instance +const router = createRouter({ routeTree }); + +describe("", () => { + it("renders", () => { // see: https://on.cypress.io/mounting-react - cy.mount( - - - - ) - }) -}) \ No newline at end of file + cy.mount(); + }); +}); diff --git a/submit-web/src/App.tsx b/submit-web/src/App.tsx index 4b4c508a..357e86ca 100644 --- a/submit-web/src/App.tsx +++ b/submit-web/src/App.tsx @@ -1,7 +1,8 @@ import EAOAppBar from "@/components/EAOAppBar"; import SideNavBar from "@/components/SideNavBar"; import { Box } from "@mui/material"; -import { Outlet } from "react-router-dom"; +import { Outlet } from "@tanstack/react-router"; +import { TanStackRouterDevtools } from "@tanstack/router-devtools"; function App() { return ( @@ -9,10 +10,16 @@ function App() { - + + ); } diff --git a/submit-web/src/components/SideNavBar.tsx b/submit-web/src/components/SideNavBar.tsx index 298cf573..26db31b7 100644 --- a/submit-web/src/components/SideNavBar.tsx +++ b/submit-web/src/components/SideNavBar.tsx @@ -1,10 +1,10 @@ -import { Box, List, ListItem, ListItemButton, useTheme } from "@mui/material"; -import { useLocation, useNavigate } from "react-router-dom"; +import { useState } from "react"; +import { Box, List, ListItem, ListItemButton } from "@mui/material"; +import { Link } from "@tanstack/react-router"; +import { theme } from "@/styles/theme"; export default function SideNavBar() { - const navigate = useNavigate(); - const location = useLocation(); - const theme = useTheme(); + const [currentPath, setCurrentPath] = useState(window.location.pathname); const routes = [ { @@ -31,22 +31,31 @@ export default function SideNavBar() { {routes.map((route) => ( - navigate(route.path)} - sx={{ - fontWeight: "700", - backgroundColor: - location.pathname === route.path - ? "rgba(0, 0, 0, 0.1)" - : "transparent", - borderLeft: - location.pathname === route.path - ? `4px solid ${theme.palette.primary.main}` - : "none", + setCurrentPath(route.path)} + style={{ + color: theme.palette.primary.main, + fontWeight: currentPath === route.path ? "bold" : "normal", + textDecoration: "none", + width: "100%", }} > - {route.routeName} - + + {route.routeName} + + ))} diff --git a/submit-web/src/main.tsx b/submit-web/src/main.tsx index 9f8d0289..94cd74c3 100644 --- a/submit-web/src/main.tsx +++ b/submit-web/src/main.tsx @@ -2,16 +2,26 @@ import { StrictMode } from "react"; import ReactDOM from "react-dom/client"; import { ThemeProvider } from "@mui/material"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; -import { RouterProvider } from "react-router-dom"; +import { RouterProvider, createRouter } from '@tanstack/react-router' import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; - +import { routeTree } from './routeTree.gen.ts' import { theme } from "@/styles/theme"; import "@/styles/App.scss"; -import router from "@/routes/router"; + +// Create a new router instance +const router = createRouter({ routeTree }) const queryClient = new QueryClient(); +// Register the router instance for type safety +declare module '@tanstack/react-router' { + interface Register { + router: typeof router + } +} + + // Render the app const rootElement = document.getElementById("root")!; if (!rootElement.innerHTML) { @@ -20,7 +30,7 @@ if (!rootElement.innerHTML) { - + diff --git a/submit-web/src/pages/Plans/PlanListPage.tsx b/submit-web/src/pages/Plans/PlanListPage.tsx index 60ebf519..921eab8a 100644 --- a/submit-web/src/pages/Plans/PlanListPage.tsx +++ b/submit-web/src/pages/Plans/PlanListPage.tsx @@ -11,7 +11,7 @@ import { import { usePlansData } from "@/hooks/usePlans"; import { AxiosResponse } from "axios"; import { Plan } from "@/models/Plan"; -import { Link } from "react-router-dom"; +import { Link } from "@tanstack/react-router"; export default function PlanListPage() { const { isLoading, data, isError, error } = usePlansData(); @@ -39,13 +39,18 @@ export default function PlanListPage() { - {plans.map((row: Plan) => ( + {plans?.map((row: Plan) => ( - {row.name} + + {row.name} + {row.submittedDate} {row.submittedBy} diff --git a/submit-web/src/pages/Plans/PlanPage.tsx b/submit-web/src/pages/Plans/PlanPage.tsx index 5256149f..444006a2 100644 --- a/submit-web/src/pages/Plans/PlanPage.tsx +++ b/submit-web/src/pages/Plans/PlanPage.tsx @@ -2,20 +2,16 @@ import { usePlanById } from "@/hooks/usePlans"; import { Plan } from "@/models/Plan"; import { Box, Button, Chip } from "@mui/material"; import { AxiosResponse } from "axios"; -import { useNavigate, useParams } from "react-router-dom"; +import { Link, useParams } from "@tanstack/react-router"; export default function PlanPage() { - const navigate = useNavigate(); - const { planIdParam } = useParams(); - + const { planId: planIdParam } = useParams({ strict: false }); const planId = Number(planIdParam); const { status, data, isError, error, isFetching, isLoading } = usePlanById(planId); const plan: Plan = (data as AxiosResponse)?.data; - console.log(plan); - if (isLoading) { return

Loading...

; } @@ -43,13 +39,11 @@ export default function PlanPage() {

On {plan.submittedDate}

{isFetching ? "Background Updating..." : " "}
- + + + )} diff --git a/submit-web/src/pages/Plans/Plans.tsx b/submit-web/src/pages/Plans/Plans.tsx deleted file mode 100644 index effcbe45..00000000 --- a/submit-web/src/pages/Plans/Plans.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { Outlet } from "react-router-dom"; - -export default function Plans() { - return ( - - ) -} diff --git a/submit-web/src/routeTree.gen.ts b/submit-web/src/routeTree.gen.ts new file mode 100644 index 00000000..e2870275 --- /dev/null +++ b/submit-web/src/routeTree.gen.ts @@ -0,0 +1,134 @@ +/* prettier-ignore-start */ + +/* eslint-disable */ + +// @ts-nocheck + +// noinspection JSUnusedGlobalSymbols + +// This file is auto-generated by TanStack Router + +import { createFileRoute } from "@tanstack/react-router"; + +// Import Routes + +import { Route as rootRoute } from "./routes/__root"; +import { Route as NewPageImport } from "./routes/NewPage"; +import { Route as PlanPageImport } from "./routes/Plans/$planId.lazy"; +// Create Virtual Routes + +const PlansListLazyImport = createFileRoute("/PlansList")(); +const AboutLazyImport = createFileRoute("/About")(); +const IndexLazyImport = createFileRoute("/")(); +const PlanPageImport = createFileRoute("/planslist/$planId")(); + +// Create/Update Routes + +const PlansListLazyRoute = PlansListLazyImport.update({ + path: "/PlansList", + getParentRoute: () => rootRoute, +} as any).lazy(() => + import("./routes/Plans/PlansList.lazy").then((d) => d.Route) +); + +const PlanPageRoute = PlanPageImport.update({ + path: "/planslist/$planId", + getParentRoute: () => rootRoute, +} as any).lazy(() => import("./routes/Plans/$planId.lazy").then((d) => d.Route)); + +const AboutLazyRoute = AboutLazyImport.update({ + path: "/About", + getParentRoute: () => rootRoute, +} as any).lazy(() => import("./routes/About.lazy").then((d) => d.Route)); + +const NewPageRoute = NewPageImport.update({ + path: "/NewPage", + getParentRoute: () => rootRoute, +} as any); + +const IndexLazyRoute = IndexLazyImport.update({ + path: "/", + getParentRoute: () => rootRoute, +} as any).lazy(() => import("./routes/index.lazy").then((d) => d.Route)); + +// Populate the FileRoutesByPath interface + +declare module "@tanstack/react-router" { + interface FileRoutesByPath { + "/": { + id: "/"; + path: "/"; + fullPath: "/"; + preLoaderRoute: typeof IndexLazyImport; + parentRoute: typeof rootRoute; + }; + "/NewPage": { + id: "/NewPage"; + path: "/NewPage"; + fullPath: "/NewPage"; + preLoaderRoute: typeof NewPageImport; + parentRoute: typeof rootRoute; + }; + "/About": { + id: "/About"; + path: "/About"; + fullPath: "/About"; + preLoaderRoute: typeof AboutLazyImport; + parentRoute: typeof rootRoute; + }; + "/PlansList": { + id: "/PlansList"; + path: "/PlansList"; + fullPath: "/PlansList"; + preLoaderRoute: typeof PlansListLazyImport; + parentRoute: typeof rootRoute; + }; + "/planslist/$planId": { + id: "/planslist/$planId"; + path: "/planslist/$planId"; + fullPath: "/planslist/$planId"; + preLoaderRoute: typeof PlanPageImport; + parentRoute: typeof rootRoute; + }; + } +} + +// Create and export the route tree + +export const routeTree = rootRoute.addChildren({ + IndexLazyRoute, + NewPageRoute, + AboutLazyRoute, + PlansListLazyRoute, + PlanPageRoute, +}); + +/* prettier-ignore-end */ + +/* ROUTE_MANIFEST_START +{ + "routes": { + "__root__": { + "filePath": "__root.tsx", + "children": [ + "/", + "/NewPage", + "/About", + "/PlansList" + ] + }, + "/": { + "filePath": "index.lazy.tsx" + }, + "/NewPage": { + "filePath": "NewPage.tsx" + }, + "/About": { + "filePath": "About.lazy.tsx" + }, + "/PlansList": { + "filePath": "PlansList.lazy.tsx" + } + } +} +ROUTE_MANIFEST_END */ diff --git a/submit-web/src/routes/About.lazy.tsx b/submit-web/src/routes/About.lazy.tsx new file mode 100644 index 00000000..a06489d4 --- /dev/null +++ b/submit-web/src/routes/About.lazy.tsx @@ -0,0 +1,6 @@ +import { createLazyFileRoute } from "@tanstack/react-router"; +import About from "@/pages/About"; + +export const Route = createLazyFileRoute("/About")({ + component: () => , +}); diff --git a/submit-web/src/routes/NewPage.tsx b/submit-web/src/routes/NewPage.tsx new file mode 100644 index 00000000..1edbe56f --- /dev/null +++ b/submit-web/src/routes/NewPage.tsx @@ -0,0 +1,15 @@ +import { Container } from "@mui/material"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/NewPage")({ + component: NewPage, +}); + +function NewPage() { + return ( + +

New Page

+

File based routing - Auto Creation!

+
+ ); +} \ No newline at end of file diff --git a/submit-web/src/routes/Plans/$planId.lazy.tsx b/submit-web/src/routes/Plans/$planId.lazy.tsx new file mode 100644 index 00000000..302be681 --- /dev/null +++ b/submit-web/src/routes/Plans/$planId.lazy.tsx @@ -0,0 +1,7 @@ +import { createFileRoute } from "@tanstack/react-router"; +import PlanPage from "@/pages/Plans/PlanPage"; + + +export const Route = createFileRoute("/planslist/$planId")({ + component: PlanPage, +}); diff --git a/submit-web/src/routes/Plans/PlansList.lazy.tsx b/submit-web/src/routes/Plans/PlansList.lazy.tsx new file mode 100644 index 00000000..6427c28b --- /dev/null +++ b/submit-web/src/routes/Plans/PlansList.lazy.tsx @@ -0,0 +1,6 @@ +import { createLazyFileRoute } from "@tanstack/react-router"; +import PlanListPage from "@/pages/Plans/PlanListPage"; + +export const Route = createLazyFileRoute("/PlansList")({ + component: PlanListPage, +}); diff --git a/submit-web/src/routes/__root.tsx b/submit-web/src/routes/__root.tsx new file mode 100644 index 00000000..fdd5d27d --- /dev/null +++ b/submit-web/src/routes/__root.tsx @@ -0,0 +1,6 @@ +import App from "@/App"; +import { createRootRoute } from "@tanstack/react-router"; + +export const Route = createRootRoute({ + component: () => , +}); diff --git a/submit-web/src/routes/index.lazy.tsx b/submit-web/src/routes/index.lazy.tsx new file mode 100644 index 00000000..0d5b3656 --- /dev/null +++ b/submit-web/src/routes/index.lazy.tsx @@ -0,0 +1,10 @@ +import { createLazyFileRoute } from "@tanstack/react-router"; +import Home from "@/pages/Home"; + +export const Route = createLazyFileRoute("/")({ + component: Index, +}); + +function Index() { + return ; +} diff --git a/submit-web/src/routes/router.tsx b/submit-web/src/routes/router.tsx deleted file mode 100644 index 11b48081..00000000 --- a/submit-web/src/routes/router.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import Home from "@/pages/Home"; -import { createBrowserRouter } from "react-router-dom"; -import PageNotFound from "@/pages/PageNotFound"; -import About from "@/pages/About"; -import App from "@/App"; -import PlanListPage from "@/pages/Plans/PlanListPage"; -import PlanPage from "@/pages/Plans/PlanPage"; -import Plans from "@/pages/Plans/Plans"; - -const router = createBrowserRouter([ - { - id: "root", - path: "/", - // loader() { - // // Our root route always provides the user, if logged in - // return { user: fakeAuthProvider.username }; - // }, - Component: App, - errorElement: , - children: [ - { - index: true, - Component: Home, - }, - { - path: "about", - // action: loginAction, - // loader: loginLoader, - Component: About, - }, - { - path: "planslist", - Component: Plans, - children: [ - { - index: true, - Component: PlanListPage, - }, - { - path: ":planIdParam", - Component: PlanPage, - }, - ], - }, - // { - // path: "protected", - // loader: protectedLoader, - // Component: ProtectedPage, - // }, - ], - }, - // { - // path: "/logout", - // async action() { - // // We signout in a "resource route" that we can hit from a fetcher.Form - // await fakeAuthProvider.signout(); - // return redirect("/"); - // }, - // }, -]); - -export default router; diff --git a/submit-web/vite.config.ts b/submit-web/vite.config.ts index 3365f342..d0376577 100644 --- a/submit-web/vite.config.ts +++ b/submit-web/vite.config.ts @@ -1,12 +1,13 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react-swc' - +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react-swc"; +import { TanStackRouterVite } from "@tanstack/router-plugin/vite"; // https://vitejs.dev/config/ + export default defineConfig({ - plugins: [react()], + plugins: [TanStackRouterVite(), react()], resolve: { alias: { - '@': '/src' - } - } -}) + "@": "/src", + }, + }, +});