From a465154fecf39a00b8e5183e53596e830b640dc1 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Tue, 11 Nov 2025 09:44:54 -0600 Subject: [PATCH] web: Add routes, solve button --- web/frontend/package-lock.json | 38 +++++++++++++++++++ web/frontend/package.json | 1 + web/frontend/public/index.html | 2 +- .../components/CaseBuilder/CaseBuilder.tsx | 5 +++ .../src/components/CaseBuilder/Header.tsx | 6 +++ .../Buttons/SiteHeaderButton.module.css | 22 +++++++++-- .../Common/Buttons/SiteHeaderButton.tsx | 9 ++++- web/frontend/src/index.tsx | 12 ++++-- web/frontend/tsconfig.json | 1 - 9 files changed, 87 insertions(+), 9 deletions(-) diff --git a/web/frontend/package-lock.json b/web/frontend/package-lock.json index 5a66f8e..08101dc 100644 --- a/web/frontend/package-lock.json +++ b/web/frontend/package-lock.json @@ -28,6 +28,7 @@ "papaparse": "^5.5.2", "react": "^19.1.0", "react-dom": "^19.1.0", + "react-router": "^7.9.5", "react-scripts": "^5.0.1", "tabulator-tables": "^6.3.1", "typescript": "^4.9.5", @@ -14181,6 +14182,37 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.5.tgz", + "integrity": "sha512-JmxqrnBZ6E9hWmf02jzNn9Jm3UqyeimyiwzD69NjxGySG6lIz/1LVPsoTCwN7NBX2XjCEa1LIX5EMz1j2b6u6A==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router/node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -15062,6 +15094,12 @@ "node": ">= 0.8.0" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", diff --git a/web/frontend/package.json b/web/frontend/package.json index 1cd27c5..5f787bf 100644 --- a/web/frontend/package.json +++ b/web/frontend/package.json @@ -23,6 +23,7 @@ "papaparse": "^5.5.2", "react": "^19.1.0", "react-dom": "^19.1.0", + "react-router": "^7.9.5", "react-scripts": "^5.0.1", "tabulator-tables": "^6.3.1", "typescript": "^4.9.5", diff --git a/web/frontend/public/index.html b/web/frontend/public/index.html index ce077e2..b92f780 100644 --- a/web/frontend/public/index.html +++ b/web/frontend/public/index.html @@ -16,7 +16,7 @@ --box-border: 1px solid rgba(0, 0, 0, 0.2); --box-shadow: 0px 2px 4px -3px rgba(0, 0, 0, 0.2); --border-radius: 4px; - --primary: #0d6efd; + --primary: #0097A7; --contrast-100: #202020; --contrast-80: #606060; --contrast-60: #909090; diff --git a/web/frontend/src/components/CaseBuilder/CaseBuilder.tsx b/web/frontend/src/components/CaseBuilder/CaseBuilder.tsx index 868cf1f..003f83e 100644 --- a/web/frontend/src/components/CaseBuilder/CaseBuilder.tsx +++ b/web/frontend/src/components/CaseBuilder/CaseBuilder.tsx @@ -91,6 +91,10 @@ const CaseBuilder = () => { setAndSaveScenario(undoStack[undoStack.length - 1]!, false); }; + const onSolve = () => { + console.log("Solve!"); + }; + return (
{ onSave={onSave} onLoad={onLoad} onUndo={onUndo} + onSolve={onSolve} />
void; onUndo: () => void; onLoad: (data: UnitCommitmentScenario) => void; + onSolve: () => void; } function Header(props: HeaderProps) { @@ -36,6 +37,11 @@ function Header(props: HeaderProps) { +
diff --git a/web/frontend/src/components/Common/Buttons/SiteHeaderButton.module.css b/web/frontend/src/components/Common/Buttons/SiteHeaderButton.module.css index bc7048c..216996a 100644 --- a/web/frontend/src/components/Common/Buttons/SiteHeaderButton.module.css +++ b/web/frontend/src/components/Common/Buttons/SiteHeaderButton.module.css @@ -12,17 +12,33 @@ box-shadow: var(--box-shadow); border-radius: var(--border-radius); cursor: pointer; - color: var(--contrast-80); text-transform: uppercase; font-weight: bold; font-size: 12px; +} + +.light { + color: var(--contrast-80); background: linear-gradient(var(--contrast-0) 25%, var(--contrast-10) 100%); } -.SiteHeaderButton:hover { +.light:hover { background: rgb(245, 245, 245); } -.SiteHeaderButton:active { +.light:active { background: rgba(220, 220, 220); } + +.primary { + color: white; + background: linear-gradient(var(--primary) 25%, color-mix(in hsl, #000, var(--primary) 90%) 100%); +} + +.primary:hover { + background: color-mix(in hsl, #fff, var(--primary) 90%); +} + +.primary:active { + background: color-mix(in hsl, #000, var(--primary) 90%); +} diff --git a/web/frontend/src/components/Common/Buttons/SiteHeaderButton.tsx b/web/frontend/src/components/Common/Buttons/SiteHeaderButton.tsx index 55a1f14..44e43b9 100644 --- a/web/frontend/src/components/Common/Buttons/SiteHeaderButton.tsx +++ b/web/frontend/src/components/Common/Buttons/SiteHeaderButton.tsx @@ -9,12 +9,19 @@ import styles from "./SiteHeaderButton.module.css"; function SiteHeaderButton({ title, onClick, + variant = "light", }: { title: string; onClick?: () => void; + variant?: "light" | "primary"; }) { + const variantClass = variant === "primary" ? styles.primary : styles.light; + return ( - ); diff --git a/web/frontend/src/index.tsx b/web/frontend/src/index.tsx index 0eea569..394e674 100644 --- a/web/frontend/src/index.tsx +++ b/web/frontend/src/index.tsx @@ -8,15 +8,21 @@ import React from "react"; import ReactDOM from "react-dom/client"; import reportWebVitals from "./reportWebVitals"; import CaseBuilder from "./components/CaseBuilder/CaseBuilder"; +import { BrowserRouter, Routes, Route, Navigate } from "react-router"; const root = ReactDOM.createRoot( document.getElementById("root") as HTMLElement, ); root.render( - - - , + + + + } /> + } /> + + + , ); reportWebVitals(); diff --git a/web/frontend/tsconfig.json b/web/frontend/tsconfig.json index a5a6cae..a03549e 100644 --- a/web/frontend/tsconfig.json +++ b/web/frontend/tsconfig.json @@ -29,7 +29,6 @@ "noUncheckedIndexedAccess": true, "noUnusedLocals": false, "noUnusedParameters": false, - "checkJs": true }, "include": ["src"] }