89 lines
2.3 KiB
TypeScript
89 lines
2.3 KiB
TypeScript
import { useMemo, useState } from "react";
|
|
import { analyze, autoLayout, compile, tidyLayout } from "./api/client";
|
|
import { CanvasArea } from "./components/CanvasArea";
|
|
import { LeftPanel } from "./components/LeftPanel";
|
|
import { RightInspector } from "./components/RightInspector";
|
|
import { TopBar } from "./components/TopBar";
|
|
|
|
const SAMPLE_PAYLOAD = {
|
|
symbols: {
|
|
r_std: { template_name: "resistor" }
|
|
},
|
|
instances: [
|
|
{
|
|
ref: "R1",
|
|
symbol: "r_std",
|
|
properties: { value: "10k" },
|
|
placement: { x: null, y: null, rotation: 0, locked: false }
|
|
}
|
|
],
|
|
nets: []
|
|
};
|
|
|
|
export function App() {
|
|
const [status, setStatus] = useState("Idle");
|
|
const [lastApiVersion, setLastApiVersion] = useState("-");
|
|
|
|
const actions = useMemo(
|
|
() => [
|
|
{
|
|
id: "compile",
|
|
label: "Compile",
|
|
run: async () => compile(SAMPLE_PAYLOAD)
|
|
},
|
|
{
|
|
id: "analyze",
|
|
label: "Analyze",
|
|
run: async () => analyze(SAMPLE_PAYLOAD)
|
|
},
|
|
{
|
|
id: "layout-auto",
|
|
label: "Auto Layout",
|
|
run: async () => autoLayout(SAMPLE_PAYLOAD)
|
|
},
|
|
{
|
|
id: "layout-tidy",
|
|
label: "Auto Tidy",
|
|
run: async () => tidyLayout(SAMPLE_PAYLOAD)
|
|
}
|
|
],
|
|
[]
|
|
);
|
|
|
|
async function runAction(actionId: string) {
|
|
const action = actions.find((item) => item.id === actionId);
|
|
if (!action) {
|
|
return;
|
|
}
|
|
|
|
setStatus(`${action.label}...`);
|
|
try {
|
|
const result = await action.run();
|
|
setLastApiVersion(result.api_version ?? "-");
|
|
setStatus(`${action.label} complete`);
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : "Unknown error";
|
|
setStatus(`${action.label} failed: ${message}`);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="app-shell">
|
|
<TopBar title="React Frontend Skeleton" />
|
|
<div className="toolbar" role="toolbar" aria-label="API actions">
|
|
{actions.map((action) => (
|
|
<button key={action.id} type="button" onClick={() => runAction(action.id)}>
|
|
{action.label}
|
|
</button>
|
|
))}
|
|
<div className="toolbar__meta">Status: {status} | API: {lastApiVersion}</div>
|
|
</div>
|
|
<div className="workspace-grid">
|
|
<LeftPanel />
|
|
<CanvasArea />
|
|
<RightInspector />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|