From 72027a302434a2562fb28899006bd510bbdbb5e4 Mon Sep 17 00:00:00 2001 From: plenarius Date: Mon, 20 Apr 2026 22:11:37 -0400 Subject: [PATCH] feat: upgrade Dashboard with server status, repo summary, and quick actions --- packages/frontend/src/pages/Dashboard.tsx | 242 +++++++++++++++++++++- 1 file changed, 233 insertions(+), 9 deletions(-) diff --git a/packages/frontend/src/pages/Dashboard.tsx b/packages/frontend/src/pages/Dashboard.tsx index dd0ae88..e336b24 100644 --- a/packages/frontend/src/pages/Dashboard.tsx +++ b/packages/frontend/src/pages/Dashboard.tsx @@ -1,13 +1,237 @@ -export function Dashboard() { +import { useState, useEffect } from "react"; +import { useNavigate } from "react-router-dom"; +import { api } from "../services/api"; + +function StatusBadge({ status }: { status: string }) { + const color = + status === "running" + ? "#4ade80" + : status === "stopped" + ? "#f87171" + : "#fbbf24"; + return ( -
-
-

- Layonara Forge -

-

- NWN Development Environment -

+ + + {status} + + ); +} + +function ServerCard() { + const [status, setStatus] = useState<{ nwserver: string; mariadb: string }>({ + nwserver: "unknown", + mariadb: "unknown", + }); + const [loading, setLoading] = useState(false); + + const poll = () => { + api.server + .status() + .then(setStatus) + .catch(() => setStatus({ nwserver: "error", mariadb: "error" })); + }; + + useEffect(() => { + poll(); + const id = setInterval(poll, 10000); + return () => clearInterval(id); + }, []); + + const toggle = async () => { + setLoading(true); + try { + if (status.nwserver === "running") { + await api.server.stop(); + } else { + await api.server.start(); + } + poll(); + } catch { + // ignore + } finally { + setLoading(false); + } + }; + + return ( +
+

+ Server Status +

+
+
+
+ + NWServer + + +
+
+ + MariaDB + + +
+
+
+
+ +
+
+ ); +} + +function ReposSummary() { + const repos = ["nwn-module", "nwn-haks", "unified"]; + const [repoStatus, setRepoStatus] = useState>>({}); + + useEffect(() => { + for (const repo of repos) { + api.repos + .status(repo) + .then((s) => setRepoStatus((prev) => ({ ...prev, [repo]: s }))) + .catch(() => {}); + } + }, []); + + return ( +
+

+ Repositories +

+
+ {repos.map((repo) => { + const s = repoStatus[repo]; + const branch = (s?.branch as string) || "\u2014"; + const clean = s?.clean !== false; + return ( +
+ + {repo} + +
+ + {branch} + + +
+
+ ); + })} +
+
+ ); +} + +function QuickActions() { + const navigate = useNavigate(); + + const actions = [ + { label: "Build Module", onClick: () => navigate("/build") }, + { label: "Build Haks", onClick: () => navigate("/build") }, + { label: "Open Editor", onClick: () => navigate("/editor") }, + { + label: "Open Terminal", + onClick: () => { + /* terminal is toggled from IDELayout via Ctrl+` */ + navigate("/editor"); + }, + }, + ]; + + return ( +
+

+ Quick Actions +

+
+ {actions.map((a) => ( + + ))} +
+
+ ); +} + +export function Dashboard() { + return ( +
+
+

+ Layonara Forge +

+

+ NWN Development Environment +

+
+
+ +
+ + +
);