From 83afee2a2547075d02bdefcdaea93de20db0c654 Mon Sep 17 00:00:00 2001 From: Jaronim Pracht Date: Thu, 22 May 2025 11:53:15 +0200 Subject: [PATCH] Add React frontend with TanStack and Material UI --- project/frontend/.dockerignore | 15 + project/frontend/.gitignore | 5 + project/frontend/.vscode/settings.json | 35 +++ project/frontend/Dockerfile | 15 + project/frontend/README.md | 295 ++++++++++++++++++ project/frontend/biome.json | 31 ++ project/frontend/bun.lockb | Bin 0 -> 141205 bytes project/frontend/docker/nginx.conf | 23 ++ project/frontend/index.html | 20 ++ project/frontend/package.json | 42 +++ project/frontend/public/favicon.ico | Bin 0 -> 3870 bytes project/frontend/public/logo192.png | Bin 0 -> 5347 bytes project/frontend/public/logo512.png | Bin 0 -> 9664 bytes project/frontend/public/manifest.json | 25 ++ project/frontend/public/robots.txt | 3 + project/frontend/src/components/Header.tsx | 17 + .../integrations/tanstack-query/layout.tsx | 5 + .../tanstack-query/root-provider.tsx | 15 + project/frontend/src/main.tsx | 63 ++++ project/frontend/src/routeTree.gen.ts | 111 +++++++ project/frontend/src/routes/__root.tsx | 25 ++ project/frontend/src/routes/demo.tsx | 26 ++ project/frontend/src/routes/index.tsx | 9 + project/frontend/tsconfig.json | 28 ++ project/frontend/vite.config.js | 12 + 25 files changed, 820 insertions(+) create mode 100644 project/frontend/.dockerignore create mode 100644 project/frontend/.gitignore create mode 100644 project/frontend/.vscode/settings.json create mode 100644 project/frontend/Dockerfile create mode 100644 project/frontend/README.md create mode 100644 project/frontend/biome.json create mode 100755 project/frontend/bun.lockb create mode 100644 project/frontend/docker/nginx.conf create mode 100644 project/frontend/index.html create mode 100644 project/frontend/package.json create mode 100644 project/frontend/public/favicon.ico create mode 100644 project/frontend/public/logo192.png create mode 100644 project/frontend/public/logo512.png create mode 100644 project/frontend/public/manifest.json create mode 100644 project/frontend/public/robots.txt create mode 100644 project/frontend/src/components/Header.tsx create mode 100644 project/frontend/src/integrations/tanstack-query/layout.tsx create mode 100644 project/frontend/src/integrations/tanstack-query/root-provider.tsx create mode 100644 project/frontend/src/main.tsx create mode 100644 project/frontend/src/routeTree.gen.ts create mode 100644 project/frontend/src/routes/__root.tsx create mode 100644 project/frontend/src/routes/demo.tsx create mode 100644 project/frontend/src/routes/index.tsx create mode 100644 project/frontend/tsconfig.json create mode 100644 project/frontend/vite.config.js diff --git a/project/frontend/.dockerignore b/project/frontend/.dockerignore new file mode 100644 index 0000000..f965aed --- /dev/null +++ b/project/frontend/.dockerignore @@ -0,0 +1,15 @@ +node_modules +Dockerfile* +docker-compose* +.dockerignore +.git +.gitignore +README.md +LICENSE +.vscode +Makefile +helm-charts +.env +.editorconfig +.idea +coverage* diff --git a/project/frontend/.gitignore b/project/frontend/.gitignore new file mode 100644 index 0000000..d451ff1 --- /dev/null +++ b/project/frontend/.gitignore @@ -0,0 +1,5 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local diff --git a/project/frontend/.vscode/settings.json b/project/frontend/.vscode/settings.json new file mode 100644 index 0000000..b001961 --- /dev/null +++ b/project/frontend/.vscode/settings.json @@ -0,0 +1,35 @@ +{ + "files.watcherExclude": { + "**/routeTree.gen.ts": true + }, + "search.exclude": { + "**/routeTree.gen.ts": true + }, + "files.readonlyInclude": { + "**/routeTree.gen.ts": true + }, + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[javascriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[jsonc]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[css]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "editor.codeActionsOnSave": { + "source.organizeImports.biome": "explicit" + } +} diff --git a/project/frontend/Dockerfile b/project/frontend/Dockerfile new file mode 100644 index 0000000..617e964 --- /dev/null +++ b/project/frontend/Dockerfile @@ -0,0 +1,15 @@ +FROM oven/bun:1 AS base +WORKDIR /usr/src/app + +# install dependencies into temp directory +# this will cache them and speed up future builds +COPY package.json bun.lockb ./ +RUN bun install --frozen-lockfile + +COPY . . + +RUN bun run build + +FROM nginx:1.28.0-alpine3.21 +COPY docker/nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=base /usr/src/app/dist /usr/share/nginx/html diff --git a/project/frontend/README.md b/project/frontend/README.md new file mode 100644 index 0000000..9c45ff3 --- /dev/null +++ b/project/frontend/README.md @@ -0,0 +1,295 @@ +Welcome to your new TanStack app! + +# Getting Started + +To run this application: + +```bash +bun install +bunx --bun run start +``` + +# Building For Production + +To build this application for production: + +```bash +bunx --bun run build +``` + +## Testing + +This project uses [Vitest](https://vitest.dev/) for testing. You can run the tests with: + +```bash +bunx --bun run test +``` + +## Linting & Formatting + +This project uses [Biome](https://biomejs.dev/) for linting and formatting. The following scripts are available: + + +```bash +bunx --bun run lint +bunx --bun run format +bunx --bun run check +``` + + +## Routing +This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`. + +### Adding A Route + +To add a new route to your application just add another a new file in the `./src/routes` directory. + +TanStack will automatically generate the content of the route file for you. + +Now that you have two routes you can use a `Link` component to navigate between them. + +### Adding Links + +To use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`. + +```tsx +import { Link } from "@tanstack/react-router"; +``` + +Then anywhere in your JSX you can use it like so: + +```tsx +About +``` + +This will create a link that will navigate to the `/about` route. + +More information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent). + +### Using A Layout + +In the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `` component. + +Here is an example layout that includes a header: + +```tsx +import { Outlet, createRootRoute } from '@tanstack/react-router' +import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' + +import { Link } from "@tanstack/react-router"; + +export const Route = createRootRoute({ + component: () => ( + <> +
+ +
+ + + + ), +}) +``` + +The `` component is not required so you can remove it if you don't want it in your layout. + +More information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts). + + +## Data Fetching + +There are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered. + +For example: + +```tsx +const peopleRoute = createRoute({ + getParentRoute: () => rootRoute, + path: "/people", + loader: async () => { + const response = await fetch("https://swapi.dev/api/people"); + return response.json() as Promise<{ + results: { + name: string; + }[]; + }>; + }, + component: () => { + const data = peopleRoute.useLoaderData(); + return ( +
    + {data.results.map((person) => ( +
  • {person.name}
  • + ))} +
+ ); + }, +}); +``` + +Loaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters). + +### React-Query + +React-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze. + +First add your dependencies: + +```bash +bun install @tanstack/react-query @tanstack/react-query-devtools +``` + +Next we'll need to create a query client and provider. We recommend putting those in `main.tsx`. + +```tsx +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; + +// ... + +const queryClient = new QueryClient(); + +// ... + +if (!rootElement.innerHTML) { + const root = ReactDOM.createRoot(rootElement); + + root.render( + + + + ); +} +``` + +You can also add TanStack Query Devtools to the root route (optional). + +```tsx +import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; + +const rootRoute = createRootRoute({ + component: () => ( + <> + + + + + ), +}); +``` + +Now you can use `useQuery` to fetch your data. + +```tsx +import { useQuery } from "@tanstack/react-query"; + +import "./App.css"; + +function App() { + const { data } = useQuery({ + queryKey: ["people"], + queryFn: () => + fetch("https://swapi.dev/api/people") + .then((res) => res.json()) + .then((data) => data.results as { name: string }[]), + initialData: [], + }); + + return ( +
+
    + {data.map((person) => ( +
  • {person.name}
  • + ))} +
+
+ ); +} + +export default App; +``` + +You can find out everything you need to know on how to use React-Query in the [React-Query documentation](https://tanstack.com/query/latest/docs/framework/react/overview). + +## State Management + +Another common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project. + +First you need to add TanStack Store as a dependency: + +```bash +bun install @tanstack/store +``` + +Now let's create a simple counter in the `src/App.tsx` file as a demonstration. + +```tsx +import { useStore } from "@tanstack/react-store"; +import { Store } from "@tanstack/store"; +import "./App.css"; + +const countStore = new Store(0); + +function App() { + const count = useStore(countStore); + return ( +
+ +
+ ); +} + +export default App; +``` + +One of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates. + +Let's check this out by doubling the count using derived state. + +```tsx +import { useStore } from "@tanstack/react-store"; +import { Store, Derived } from "@tanstack/store"; +import "./App.css"; + +const countStore = new Store(0); + +const doubledStore = new Derived({ + fn: () => countStore.state * 2, + deps: [countStore], +}); +doubledStore.mount(); + +function App() { + const count = useStore(countStore); + const doubledCount = useStore(doubledStore); + + return ( +
+ +
Doubled - {doubledCount}
+
+ ); +} + +export default App; +``` + +We use the `Derived` class to create a new store that is derived from another store. The `Derived` class has a `mount` method that will start the derived store updating. + +Once we've created the derived store we can use it in the `App` component just like we would any other store using the `useStore` hook. + +You can find out everything you need to know on how to use TanStack Store in the [TanStack Store documentation](https://tanstack.com/store/latest). + +# Demo files + +Files prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed. + +# Learn More + +You can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com). diff --git a/project/frontend/biome.json b/project/frontend/biome.json new file mode 100644 index 0000000..55240aa --- /dev/null +++ b/project/frontend/biome.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": false + }, + "files": { + "ignoreUnknown": false, + "ignore": ["src/routeTree.gen.ts"], + "include": ["src/*", ".vscode/*", "index.html", "vite.config.js"] + }, + "formatter": { + "enabled": true, + "indentStyle": "space" + }, + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double" + } + } +} diff --git a/project/frontend/bun.lockb b/project/frontend/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..776a92207d5869526eecb5c275c4bdc8c08b311f GIT binary patch literal 141205 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 + + + + + + + + + + Create TanStack App - frontend + + +
+ + + diff --git a/project/frontend/package.json b/project/frontend/package.json new file mode 100644 index 0000000..cb88c9a --- /dev/null +++ b/project/frontend/package.json @@ -0,0 +1,42 @@ +{ + "name": "frontend", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "start": "vite", + "build": "vite build && tsc", + "serve": "vite preview", + "test": "vitest run", + "format": "biome format --write", + "lint": "biome lint", + "check": "biome check" + }, + "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@fontsource/roboto": "^5.2.5", + "@mui/icons-material": "^7.1.0", + "@mui/material": "^7.1.0", + "@tanstack/react-query": "^5.66.5", + "@tanstack/react-query-devtools": "^5.66.5", + "@tanstack/react-router": "^1.114.3", + "@tanstack/react-router-devtools": "^1.114.3", + "@tanstack/router-plugin": "^1.114.3", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-pdf": "^9.2.1" + }, + "devDependencies": { + "@biomejs/biome": "1.9.4", + "@testing-library/dom": "^10.4.0", + "@testing-library/react": "^16.2.0", + "@types/react": "^19.0.8", + "@types/react-dom": "^19.0.3", + "@vitejs/plugin-react": "^4.3.4", + "jsdom": "^26.0.0", + "typescript": "^5.7.2", + "vite": "^6.1.0", + "vitest": "^3.0.5" + } +} diff --git a/project/frontend/public/favicon.ico b/project/frontend/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a11777cc471a4344702741ab1c8a588998b1311a GIT binary patch literal 3870 zcma);c{J4h9>;%nil|2-o+rCuEF-(I%-F}ijC~o(k~HKAkr0)!FCj~d>`RtpD?8b; zXOC1OD!V*IsqUwzbMF1)-gEDD=A573Z-&G7^LoAC9|WO7Xc0Cx1g^Zu0u_SjAPB
3vGa^W|sj)80f#V0@M_CAZTIO(t--xg= z!sii`1giyH7EKL_+Wi0ab<)&E_0KD!3Rp2^HNB*K2@PHCs4PWSA32*-^7d{9nH2_E zmC{C*N*)(vEF1_aMamw2A{ZH5aIDqiabnFdJ|y0%aS|64E$`s2ccV~3lR!u<){eS` z#^Mx6o(iP1Ix%4dv`t@!&Za-K@mTm#vadc{0aWDV*_%EiGK7qMC_(`exc>-$Gb9~W!w_^{*pYRm~G zBN{nA;cm^w$VWg1O^^<6vY`1XCD|s_zv*g*5&V#wv&s#h$xlUilPe4U@I&UXZbL z0)%9Uj&@yd03n;!7do+bfixH^FeZ-Ema}s;DQX2gY+7g0s(9;`8GyvPY1*vxiF&|w z>!vA~GA<~JUqH}d;DfBSi^IT*#lrzXl$fNpq0_T1tA+`A$1?(gLb?e#0>UELvljtQ zK+*74m0jn&)5yk8mLBv;=@}c{t0ztT<v;Avck$S6D`Z)^c0(jiwKhQsn|LDRY&w(Fmi91I7H6S;b0XM{e zXp0~(T@k_r-!jkLwd1_Vre^v$G4|kh4}=Gi?$AaJ)3I+^m|Zyj#*?Kp@w(lQdJZf4 z#|IJW5z+S^e9@(6hW6N~{pj8|NO*>1)E=%?nNUAkmv~OY&ZV;m-%?pQ_11)hAr0oAwILrlsGawpxx4D43J&K=n+p3WLnlDsQ$b(9+4 z?mO^hmV^F8MV{4Lx>(Q=aHhQ1){0d*(e&s%G=i5rq3;t{JC zmgbn5Nkl)t@fPH$v;af26lyhH!k+#}_&aBK4baYPbZy$5aFx4}ka&qxl z$=Rh$W;U)>-=S-0=?7FH9dUAd2(q#4TCAHky!$^~;Dz^j|8_wuKc*YzfdAht@Q&ror?91Dm!N03=4=O!a)I*0q~p0g$Fm$pmr$ zb;wD;STDIi$@M%y1>p&_>%?UP($15gou_ue1u0!4(%81;qcIW8NyxFEvXpiJ|H4wz z*mFT(qVx1FKufG11hByuX%lPk4t#WZ{>8ka2efjY`~;AL6vWyQKpJun2nRiZYDij$ zP>4jQXPaP$UC$yIVgGa)jDV;F0l^n(V=HMRB5)20V7&r$jmk{UUIe zVjKroK}JAbD>B`2cwNQ&GDLx8{pg`7hbA~grk|W6LgiZ`8y`{Iq0i>t!3p2}MS6S+ zO_ruKyAElt)rdS>CtF7j{&6rP-#c=7evGMt7B6`7HG|-(WL`bDUAjyn+k$mx$CH;q2Dz4x;cPP$hW=`pFfLO)!jaCL@V2+F)So3}vg|%O*^T1j>C2lx zsURO-zIJC$^$g2byVbRIo^w>UxK}74^TqUiRR#7s_X$e)$6iYG1(PcW7un-va-S&u zHk9-6Zn&>T==A)lM^D~bk{&rFzCi35>UR!ZjQkdSiNX*-;l4z9j*7|q`TBl~Au`5& z+c)*8?#-tgUR$Zd%Q3bs96w6k7q@#tUn`5rj+r@_sAVVLqco|6O{ILX&U-&-cbVa3 zY?ngHR@%l{;`ri%H*0EhBWrGjv!LE4db?HEWb5mu*t@{kv|XwK8?npOshmzf=vZA@ zVSN9sL~!sn?r(AK)Q7Jk2(|M67Uy3I{eRy z_l&Y@A>;vjkWN5I2xvFFTLX0i+`{qz7C_@bo`ZUzDugfq4+>a3?1v%)O+YTd6@Ul7 zAfLfm=nhZ`)P~&v90$&UcF+yXm9sq!qCx3^9gzIcO|Y(js^Fj)Rvq>nQAHI92ap=P z10A4@prk+AGWCb`2)dQYFuR$|H6iDE8p}9a?#nV2}LBCoCf(Xi2@szia7#gY>b|l!-U`c}@ zLdhvQjc!BdLJvYvzzzngnw51yRYCqh4}$oRCy-z|v3Hc*d|?^Wj=l~18*E~*cR_kU z{XsxM1i{V*4GujHQ3DBpl2w4FgFR48Nma@HPgnyKoIEY-MqmMeY=I<%oG~l!f<+FN z1ZY^;10j4M4#HYXP zw5eJpA_y(>uLQ~OucgxDLuf}fVs272FaMxhn4xnDGIyLXnw>Xsd^J8XhcWIwIoQ9} z%FoSJTAGW(SRGwJwb=@pY7r$uQRK3Zd~XbxU)ts!4XsJrCycrWSI?e!IqwqIR8+Jh zlRjZ`UO1I!BtJR_2~7AbkbSm%XQqxEPkz6BTGWx8e}nQ=w7bZ|eVP4?*Tb!$(R)iC z9)&%bS*u(lXqzitAN)Oo=&Ytn>%Hzjc<5liuPi>zC_nw;Z0AE3Y$Jao_Q90R-gl~5 z_xAb2J%eArrC1CN4G$}-zVvCqF1;H;abAu6G*+PDHSYFx@Tdbfox*uEd3}BUyYY-l zTfEsOqsi#f9^FoLO;ChK<554qkri&Av~SIM*{fEYRE?vH7pTAOmu2pz3X?Wn*!ROX ztd54huAk&mFBemMooL33RV-*1f0Q3_(7hl$<#*|WF9P!;r;4_+X~k~uKEqdzZ$5Al zV63XN@)j$FN#cCD;ek1R#l zv%pGrhB~KWgoCj%GT?%{@@o(AJGt*PG#l3i>lhmb_twKH^EYvacVY-6bsCl5*^~L0 zonm@lk2UvvTKr2RS%}T>^~EYqdL1q4nD%0n&Xqr^cK^`J5W;lRRB^R-O8b&HENO||mo0xaD+S=I8RTlIfVgqN@SXDr2&-)we--K7w= zJVU8?Z+7k9dy;s;^gDkQa`0nz6N{T?(A&Iz)2!DEecLyRa&FI!id#5Z7B*O2=PsR0 zEvc|8{NS^)!d)MDX(97Xw}m&kEO@5jqRaDZ!+%`wYOI<23q|&js`&o4xvjP7D_xv@ z5hEwpsp{HezI9!~6O{~)lLR@oF7?J7i>1|5a~UuoN=q&6N}EJPV_GD`&M*v8Y`^2j zKII*d_@Fi$+i*YEW+Hbzn{iQk~yP z>7N{S4)r*!NwQ`(qcN#8SRQsNK6>{)X12nbF`*7#ecO7I)Q$uZsV+xS4E7aUn+U(K baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ literal 0 HcmV?d00001 diff --git a/project/frontend/public/logo192.png b/project/frontend/public/logo192.png new file mode 100644 index 0000000000000000000000000000000000000000..fc44b0a3796c0e0a64c3d858ca038bd4570465d9 GIT binary patch literal 5347 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 b{|{}U^kRn2wo}j7|0ATu<;8xA7zX}7|B6mN literal 0 HcmV?d00001 diff --git a/project/frontend/public/manifest.json b/project/frontend/public/manifest.json new file mode 100644 index 0000000..078ef50 --- /dev/null +++ b/project/frontend/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "TanStack App", + "name": "Create TanStack App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/project/frontend/public/robots.txt b/project/frontend/public/robots.txt new file mode 100644 index 0000000..e9e57dc --- /dev/null +++ b/project/frontend/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/project/frontend/src/components/Header.tsx b/project/frontend/src/components/Header.tsx new file mode 100644 index 0000000..383cf9e --- /dev/null +++ b/project/frontend/src/components/Header.tsx @@ -0,0 +1,17 @@ +import { Link } from "@tanstack/react-router"; + +export default function Header() { + return ( +
+ +
+ ); +} diff --git a/project/frontend/src/integrations/tanstack-query/layout.tsx b/project/frontend/src/integrations/tanstack-query/layout.tsx new file mode 100644 index 0000000..68b9cdd --- /dev/null +++ b/project/frontend/src/integrations/tanstack-query/layout.tsx @@ -0,0 +1,5 @@ +import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; + +export default function LayoutAddition() { + return ; +} diff --git a/project/frontend/src/integrations/tanstack-query/root-provider.tsx b/project/frontend/src/integrations/tanstack-query/root-provider.tsx new file mode 100644 index 0000000..2fb2aa9 --- /dev/null +++ b/project/frontend/src/integrations/tanstack-query/root-provider.tsx @@ -0,0 +1,15 @@ +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; + +const queryClient = new QueryClient(); + +export function getContext() { + return { + queryClient, + }; +} + +export function Provider({ children }: { children: React.ReactNode }) { + return ( + {children} + ); +} diff --git a/project/frontend/src/main.tsx b/project/frontend/src/main.tsx new file mode 100644 index 0000000..ddffcc6 --- /dev/null +++ b/project/frontend/src/main.tsx @@ -0,0 +1,63 @@ +import CssBaseline from "@mui/material/CssBaseline"; +import { ThemeProvider, createTheme } from "@mui/material/styles"; +import { RouterProvider, createRouter } from "@tanstack/react-router"; +import { StrictMode } from "react"; +import ReactDOM from "react-dom/client"; + +import "@fontsource/roboto/300.css"; +import "@fontsource/roboto/400.css"; +import "@fontsource/roboto/500.css"; +import "@fontsource/roboto/700.css"; + +import * as TanStackQueryProvider from "./integrations/tanstack-query/root-provider.tsx"; + +import { pdfjs } from "react-pdf"; +// Import the generated route tree +import { routeTree } from "./routeTree.gen"; + +// Create a new router instance +const router = createRouter({ + routeTree, + context: { + ...TanStackQueryProvider.getContext(), + }, + defaultPreload: "intent", + scrollRestoration: true, + defaultStructuralSharing: true, + defaultPreloadStaleTime: 0, +}); + +// Register the router instance for type safety +declare module "@tanstack/react-router" { + interface Register { + router: typeof router; + } +} + +// Initialize PDF.js worker +pdfjs.GlobalWorkerOptions.workerSrc = new URL( + "pdfjs-dist/build/pdf.worker.min.mjs", + import.meta.url, +).toString(); + +const darkTheme = createTheme({ + palette: { + mode: "dark", + }, +}); + +// Render the app +const rootElement = document.getElementById("app"); +if (rootElement && !rootElement.innerHTML) { + const root = ReactDOM.createRoot(rootElement); + root.render( + + + + + + + + , + ); +} diff --git a/project/frontend/src/routeTree.gen.ts b/project/frontend/src/routeTree.gen.ts new file mode 100644 index 0000000..b19f273 --- /dev/null +++ b/project/frontend/src/routeTree.gen.ts @@ -0,0 +1,111 @@ +/* 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 DemoImport } from './routes/demo' +import { Route as IndexImport } from './routes/index' + +// Create/Update Routes + +const DemoRoute = DemoImport.update({ + id: '/demo', + path: '/demo', + getParentRoute: () => rootRoute, +} as any) + +const IndexRoute = IndexImport.update({ + id: '/', + path: '/', + getParentRoute: () => rootRoute, +} as any) + +// Populate the FileRoutesByPath interface + +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexImport + parentRoute: typeof rootRoute + } + '/demo': { + id: '/demo' + path: '/demo' + fullPath: '/demo' + preLoaderRoute: typeof DemoImport + parentRoute: typeof rootRoute + } + } +} + +// Create and export the route tree + +export interface FileRoutesByFullPath { + '/': typeof IndexRoute + '/demo': typeof DemoRoute +} + +export interface FileRoutesByTo { + '/': typeof IndexRoute + '/demo': typeof DemoRoute +} + +export interface FileRoutesById { + __root__: typeof rootRoute + '/': typeof IndexRoute + '/demo': typeof DemoRoute +} + +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: '/' | '/demo' + fileRoutesByTo: FileRoutesByTo + to: '/' | '/demo' + id: '__root__' | '/' | '/demo' + fileRoutesById: FileRoutesById +} + +export interface RootRouteChildren { + IndexRoute: typeof IndexRoute + DemoRoute: typeof DemoRoute +} + +const rootRouteChildren: RootRouteChildren = { + IndexRoute: IndexRoute, + DemoRoute: DemoRoute, +} + +export const routeTree = rootRoute + ._addFileChildren(rootRouteChildren) + ._addFileTypes() + +/* ROUTE_MANIFEST_START +{ + "routes": { + "__root__": { + "filePath": "__root.tsx", + "children": [ + "/", + "/demo" + ] + }, + "/": { + "filePath": "index.tsx" + }, + "/demo": { + "filePath": "demo.tsx" + } + } +} +ROUTE_MANIFEST_END */ diff --git a/project/frontend/src/routes/__root.tsx b/project/frontend/src/routes/__root.tsx new file mode 100644 index 0000000..0816bdd --- /dev/null +++ b/project/frontend/src/routes/__root.tsx @@ -0,0 +1,25 @@ +import { Outlet, createRootRouteWithContext } from "@tanstack/react-router"; +import { TanStackRouterDevtools } from "@tanstack/react-router-devtools"; + +// import Header from "../components/Header"; + +import TanStackQueryLayout from "../integrations/tanstack-query/layout.tsx"; + +import type { QueryClient } from "@tanstack/react-query"; + +interface MyRouterContext { + queryClient: QueryClient; +} + +export const Route = createRootRouteWithContext()({ + component: () => ( + <> + {/*
*/} + + + + + + + ), +}); diff --git a/project/frontend/src/routes/demo.tsx b/project/frontend/src/routes/demo.tsx new file mode 100644 index 0000000..8d1e906 --- /dev/null +++ b/project/frontend/src/routes/demo.tsx @@ -0,0 +1,26 @@ +import { useQuery } from "@tanstack/react-query"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/demo")({ + component: TanStackQueryDemo, +}); + +function TanStackQueryDemo() { + const { data } = useQuery({ + queryKey: ["people"], + queryFn: () => + Promise.resolve([{ name: "John Doe" }, { name: "Jane Doe" }]), + initialData: [], + }); + + return ( +
+

People list

+
    + {data.map((person) => ( +
  • {person.name}
  • + ))} +
+
+ ); +} diff --git a/project/frontend/src/routes/index.tsx b/project/frontend/src/routes/index.tsx new file mode 100644 index 0000000..7414b29 --- /dev/null +++ b/project/frontend/src/routes/index.tsx @@ -0,0 +1,9 @@ +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/")({ + component: App, +}); + +function App() { + return <>Test; +} diff --git a/project/frontend/tsconfig.json b/project/frontend/tsconfig.json new file mode 100644 index 0000000..7920df9 --- /dev/null +++ b/project/frontend/tsconfig.json @@ -0,0 +1,28 @@ +{ + "include": ["**/*.ts", "**/*.tsx"], + "compilerOptions": { + "target": "ES2022", + "jsx": "react-jsx", + "module": "ESNext", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "types": ["vite/client"], + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + /* Linting */ + "skipLibCheck": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"], + } + } +} diff --git a/project/frontend/vite.config.js b/project/frontend/vite.config.js new file mode 100644 index 0000000..059d9e2 --- /dev/null +++ b/project/frontend/vite.config.js @@ -0,0 +1,12 @@ +import { TanStackRouterVite } from "@tanstack/router-plugin/vite"; +import viteReact from "@vitejs/plugin-react"; +import { defineConfig } from "vite"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [TanStackRouterVite({ autoCodeSplitting: true }), viteReact()], + test: { + globals: true, + environment: "jsdom", + }, +});