Render transactions on <table>
Use react-router in data mode to layout the application. Do a SSR to the datastore API /transactions.
This commit is contained in:
parent
56d3c2a5a7
commit
4160886cf5
@ -4,7 +4,7 @@
|
||||
<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>
|
||||
<title>Personal Finance tools web app</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
49
package-lock.json
generated
49
package-lock.json
generated
@ -2309,6 +2309,21 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-tsconfig": {
|
||||
"version": "4.10.0",
|
||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz",
|
||||
"integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"resolve-pkg-maps": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
||||
@ -2868,6 +2883,18 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-pkg-maps": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
|
||||
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/reusify": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
|
||||
@ -3049,6 +3076,28 @@
|
||||
"typescript": ">=4.8.4"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx": {
|
||||
"version": "4.19.3",
|
||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz",
|
||||
"integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "~0.25.0",
|
||||
"get-tsconfig": "^4.7.5"
|
||||
},
|
||||
"bin": {
|
||||
"tsx": "dist/cli.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/turbo-stream": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
|
||||
|
||||
35
src/App.tsx
35
src/App.tsx
@ -1,35 +0,0 @@
|
||||
import { useState } from 'react'
|
||||
import reactLogo from './assets/react.svg'
|
||||
import viteLogo from '/vite.svg'
|
||||
import './App.css'
|
||||
|
||||
function App() {
|
||||
const [count, setCount] = useState(0)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<a href="https://vite.dev" target="_blank">
|
||||
<img src={viteLogo} className="logo" alt="Vite logo" />
|
||||
</a>
|
||||
<a href="https://react.dev" target="_blank">
|
||||
<img src={reactLogo} className="logo react" alt="React logo" />
|
||||
</a>
|
||||
</div>
|
||||
<h1>Vite + React</h1>
|
||||
<div className="card">
|
||||
<button onClick={() => setCount((count) => count + 1)}>
|
||||
count is {count}
|
||||
</button>
|
||||
<p>
|
||||
Edit <code>src/App.tsx</code> and save to test HMR
|
||||
</p>
|
||||
</div>
|
||||
<p className="read-the-docs">
|
||||
Click on the Vite and React logos to learn more
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
17
src/main.tsx
17
src/main.tsx
@ -1,10 +1,11 @@
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import './index.css'
|
||||
import App from './App.tsx'
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { RouterProvider } from "react-router";
|
||||
import "./index.css";
|
||||
import { router } from "./routes.ts";
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
)
|
||||
<RouterProvider router={router} />
|
||||
</StrictMode>
|
||||
);
|
||||
|
||||
14
src/root.tsx
Normal file
14
src/root.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import "./root.css";
|
||||
import { NavLink, Outlet } from "react-router";
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<>
|
||||
<h1>Personal Finance</h1>
|
||||
<nav>
|
||||
<NavLink to="/transactions">Transactions</NavLink>
|
||||
</nav>
|
||||
<Outlet />
|
||||
</>
|
||||
);
|
||||
}
|
||||
17
src/routes.ts
Normal file
17
src/routes.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { createBrowserRouter } from "react-router";
|
||||
import Transactions, { loader } from "./routes/transactions";
|
||||
import App from "./root";
|
||||
|
||||
export const router = createBrowserRouter([
|
||||
{
|
||||
path: "/",
|
||||
Component: App,
|
||||
children: [
|
||||
{
|
||||
path: "transactions",
|
||||
Component: Transactions,
|
||||
loader: loader,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
37
src/routes/transactions.tsx
Normal file
37
src/routes/transactions.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import { useLoaderData } from "react-router";
|
||||
|
||||
export async function loader() {
|
||||
return await fetch(`http://localhost:9000/transactions`).then((response) => {
|
||||
return response.json();
|
||||
});
|
||||
}
|
||||
|
||||
export default function Transactions() {
|
||||
const transactions: {
|
||||
id: number;
|
||||
date: string;
|
||||
description: string;
|
||||
value: number;
|
||||
}[] = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">date</th>
|
||||
<th scope="col">description</th>
|
||||
<th scope="col">value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{transactions.map((t) => (
|
||||
<tr>
|
||||
<th>{t.date}</th>
|
||||
<td>{t.description}</td>
|
||||
<td>{t.value}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user