Build a live status dashboard for Commandocentrum + admin home

The Commandocentrum (AtomCMS's verification/diagnostics hub) was just RCON
buttons + an error table. Rebuilt it as a real status dashboard, and gave
the admin home the same treatment, with reusable StatusCard / DiagnosticRow
/ InfoItem components and a scoped CSS layer:

Commandocentrum now shows:
- Live status tiles: players online, emulator (RCON ping), database,
  emulator error count — colour-accented by state.
- Server info: Node version, platform, app/host uptime, heap/RSS, load,
  CPUs (from node:os / process).
- System diagnostics: DB, emulator RCON, RCON config, APP_KEY (2FA),
  SMTP, maintenance mode — each with an ok/warn/error dot + pill.
- Existing RCON controls + hotel alert, a recent staff-activity feed
  (staff_activities, now a real table), and the emulator error log.

Admin home: four status tiles (online/articles/active bans/database) +
recent staff activity, replacing the three plain count cards.

Verified in a real authed admin session (prod, amx_test): both pages
render the tiles/diagnostics with live data (Node v22, real memory/uptime,
APP_KEY/SMTP correctly flagged WARN). tsc 0, vitest 49/49, next build 0.
This commit is contained in:
Simo committed 2026-06-28 18:45:48 +02:00
1 parent f4e0924e71
commit d419731566
4 files changed
+433 -25

No files matched your search

+66
View File
@@ -0,0 +1,66 @@
import type { ReactNode } from "react";
type State = "ok" | "warn" | "danger" | "neutral";
/** A single live-status tile (online users, emulator, DB, …). */
export function StatusCard({
label,
value,
hint,
state = "neutral",
icon,
}: {
label: string;
value: ReactNode;
hint?: string;
state?: State;
icon?: string;
}) {
return (
<div className={`admin-stat-card ${state}`}>
<div className="admin-stat-top">
<span className="admin-stat-label">{label}</span>
{icon ? (
<span className="admin-stat-icon" aria-hidden>
{icon}
</span>
) : null}
</div>
<div className="admin-stat-value">{value}</div>
{hint ? <div className="admin-stat-hint">{hint}</div> : null}
</div>
);
}
/** A row in the system-diagnostics list with an ok/warn/error pill. */
export function DiagnosticRow({
label,
detail,
state,
}: {
label: string;
detail: string;
state: Exclude<State, "neutral">;
}) {
const text = state === "ok" ? "OK" : state === "warn" ? "WARN" : "ERROR";
return (
<div className="admin-diag-row">
<span className={`admin-dot ${state}`} aria-hidden />
<span className="admin-diag-label">{label}</span>
<span className="admin-diag-detail muted">{detail}</span>
<span className={`admin-badge ${state === "ok" ? "ok" : state === "danger" ? "danger" : ""}`}>
{text}
</span>
</div>
);
}
/** Small labelled key/value used in the server-info card. */
export function InfoItem({ label, value }: { label: string; value: ReactNode }) {
return (
<div className="admin-info-item">
<span className="muted">{label}</span>
<strong>{value}</strong>
</div>
);
}