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

+115
View File
@@ -564,3 +564,118 @@ td {
.admin-badge.danger {
background: color-mix(in srgb, #ef4444 22%, transparent);
}
/* Dashboard: live-status tiles, server info, diagnostics */
.admin-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 0.9rem;
margin-bottom: 1.4rem;
}
.admin-stat-card {
background: var(--color-surface);
border: 1px solid var(--border);
border-left: 4px solid var(--color-text-muted);
border-radius: 12px;
padding: 0.85rem 1rem;
box-shadow: var(--shadow-card);
}
.admin-stat-card.ok {
border-left-color: #16a34a;
}
.admin-stat-card.warn {
border-left-color: var(--color-primary, #eeb425);
}
.admin-stat-card.danger {
border-left-color: #ef4444;
}
.admin-stat-top {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.5rem;
}
.admin-stat-label {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--color-text-muted);
}
.admin-stat-icon {
font-size: 1.1rem;
line-height: 1;
}
.admin-stat-value {
font-size: 1.7rem;
font-weight: 800;
line-height: 1.1;
margin-top: 0.3rem;
}
.admin-stat-hint {
font-size: 0.78rem;
color: var(--color-text-muted);
margin-top: 0.15rem;
}
.admin-info-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 0.6rem 1.2rem;
}
.admin-info-item {
display: flex;
flex-direction: column;
gap: 0.1rem;
font-size: 0.88rem;
}
.admin-diag {
display: flex;
flex-direction: column;
}
.admin-diag-row {
display: flex;
align-items: center;
gap: 0.6rem;
padding: 0.5rem 0.1rem;
border-top: 1px solid color-mix(in srgb, var(--color-text-muted) 12%, transparent);
}
.admin-diag-row:first-child {
border-top: none;
}
.admin-diag-label {
font-weight: 700;
font-size: 0.88rem;
}
.admin-diag-detail {
flex: 1;
font-size: 0.82rem;
}
.admin-dot {
flex: none;
width: 9px;
height: 9px;
border-radius: 999px;
background: var(--color-text-muted);
}
.admin-dot.ok {
background: #16a34a;
box-shadow: 0 0 0 3px color-mix(in srgb, #16a34a 22%, transparent);
}
.admin-dot.warn {
background: var(--color-primary, #eeb425);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 22%, transparent);
}
.admin-dot.danger {
background: #ef4444;
box-shadow: 0 0 0 3px color-mix(in srgb, #ef4444 22%, transparent);
}
.admin-section {
margin-top: 1.6rem;
}
.admin-section > h2 {
margin: 0 0 0.7rem;
font-size: 1.15rem;
}