feat: out-source footer and header

This commit is contained in:
julius 2025-02-10 16:40:19 +01:00
parent 25bda2bc4d
commit 501811a0b5
Signed by: julius
GPG Key ID: C80A63E6A5FD7092
5 changed files with 135 additions and 5 deletions

104
src/Analysis.tsx Normal file
View File

@ -0,0 +1,104 @@
import { useEffect, useState } from "react";
import { baseUrl } from "./api";
interface Params {
nodeSize: number;
edgeWidth: number;
arrowSize: number;
fontSize: number;
}
export default function Analysis() {
const [image, setImage] = useState("");
const [params, setParams] = useState<Params>({
nodeSize: 1600,
edgeWidth: 1,
arrowSize: 20,
fontSize: 10,
});
const [showControlPanel, setShowControlPanel] = useState(false);
const [loading, setLoading] = useState(false);
// Function to generate and fetch the graph image
async function loadImage() {
setLoading(true);
await fetch(`${baseUrl}analysis/image`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(params)
})
.then((resp) => resp.json())
.then((data) => {
setImage(data.image);
setLoading(false);
});
}
useEffect(() => {
loadImage();
}, []);
return (
<div className="stack column dropdown">
<button onClick={() => setShowControlPanel(!showControlPanel)}>
Parameters {showControlPanel ? "⮝" : "⮟"}
</button>
{showControlPanel && (
<div id="control-panel">
<label>Node Size:</label>
<input
type="range"
min="500"
max="3000"
value={params.nodeSize}
onChange={(evt) => setParams({ ...params, nodeSize: Number(evt.target.value) })}
onMouseUp={() => loadImage()}
/>
<span>{params.nodeSize}</span>
<label>Font Size:</label>
<input
type="range"
min="4"
max="24"
value={params.fontSize}
onChange={(evt) => setParams({ ...params, fontSize: Number(evt.target.value) })}
onMouseUp={() => loadImage()}
/>
<span>{params.fontSize}</span>
<label>Edge Width:</label>
<input
type="range"
min="1"
max="5"
step="0.1"
value={params.edgeWidth}
onChange={(evt) => setParams({ ...params, edgeWidth: Number(evt.target.value) })}
onMouseUp={() => loadImage()}
/>
<span>{params.edgeWidth}</span>
<label>Arrow Size:</label>
<input
type="range"
min="10"
max="50"
value={params.arrowSize}
onChange={(evt) => setParams({ ...params, arrowSize: Number(evt.target.value) })}
onMouseUp={() => loadImage()}
/>
<span>{params.arrowSize}</span>
</div>
)}
{loading ? (
<span className="loader"></span>
) : (
<img src={"data:image/png;base64," + image} width="86%" />
)}
</div>
);
}

View File

@ -1,5 +1,4 @@
import Analysis from "./Analysis"; import Analysis from "./Analysis";
import { baseUrl } from "./api";
import "./App.css"; import "./App.css";
import Footer from "./Footer"; import Footer from "./Footer";
import Header from "./Header"; import Header from "./Header";

14
src/Footer.tsx Normal file
View File

@ -0,0 +1,14 @@
export default function Footer() {
return <footer>
<p className="grey">
something not working?
<br />
message <a href="https://t.me/x0124816">me</a>.
<br />
or fix it here:{" "}
<a href="https://git.0124816.xyz/julius/cutt" key="gitea">
<img src="gitea.svg" alt="gitea" height="16" />
</a>
</p>
</footer>
}

11
src/Header.tsx Normal file
View File

@ -0,0 +1,11 @@
import { baseUrl } from "./api";
export default function Header() {
return <div className="logo">
<a href={baseUrl}>
<img alt="logo" height="66%" src="logo.svg" />
<h3 className="centered">cutt</h3>
</a>
<span className="grey">cool ultimate team tool</span>
</div>
}

View File

@ -2,17 +2,17 @@
"compilerOptions": { "compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2022", "target": "ES2022",
"lib": ["ES2023"], "lib": [
"ES2023"
],
"module": "ESNext", "module": "ESNext",
"skipLibCheck": true, "skipLibCheck": true,
/* Bundler mode */ /* Bundler mode */
"moduleResolution": "bundler", "moduleResolution": "bundler",
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
"isolatedModules": true, "isolatedModules": true,
"moduleDetection": "force", "moduleDetection": "force",
"noEmit": true, "noEmit": true,
/* Linting */ /* Linting */
"strict": true, "strict": true,
"noUnusedLocals": true, "noUnusedLocals": true,
@ -20,5 +20,7 @@
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true "noUncheckedSideEffectImports": true
}, },
"include": ["vite.config.ts"] "include": [
"vite.config.ts"
]
} }