feat(panel): per-game UI adaptation — sidebar, Server view, and dashboard transform by selected game
All checks were successful
Test Asgard Runner / test (push) Successful in 3s

Drives the panel off the active game (GameSwitcher selection) + the GameProfile registry, so each game visibly differs (not just accent color). Sidebar nav: Rust = full (uMod plugins + plugin configs); Conan/Soulmask/Dune drop uMod + plugin-configs and relabel reset (Wipe World / World Reset / Deep Desert), Dune relabels Console->Broadcast (no RCON) and is Docker-managed. ServerView: management-model badge + game-appropriate panels (Rust deploy + Oxide; Dune Docker/BattleGroup-Sietches; Conan clans/thralls/avatars/purge; Soulmask main-client cluster) with HONEST EmptyStates where no backend data exists yet. Dashboard: per-game reset terminology + stat labels. No invented routes (all map to existing router entries); no fabricated data. Build green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell
2026-06-11 08:37:03 -04:00
parent 8b84bba165
commit 23decd9b08
4 changed files with 349 additions and 88 deletions

View File

@@ -25,6 +25,7 @@ import { useWipeStore } from '@/stores/wipe'
import { useApi } from '@/composables/useApi'
import { useWebSocket, type WebSocketMessage } from '@/composables/useWebSocket'
import { useGameProfile } from '@/config/gameProfiles'
import { useThemeGame } from '@/composables/useThemeGame'
import Panel from '@/components/ds/data/Panel.vue'
import StatCard from '@/components/ds/data/StatCard.vue'
import ConsoleLineDS from '@/components/ds/data/ConsoleLine.vue'
@@ -44,10 +45,14 @@ const server = useServerStore()
const wipeStore = useWipeStore()
const router = useRouter()
const api = useApi()
const { activeGame } = useThemeGame()
// Today every license is Rust. When the backend adds a `game` field to the
// license or server_config, pass it here: useGameProfile(server.config?.game ?? 'rust')
const profile = computed(() => useGameProfile('rust'))
// Profile follows the GameSwitcher selection. 'all' falls back to rust (neutral house skin).
// When the backend adds a `game` field on licenses, swap activeGame for server.config?.game.
const profile = computed(() => {
const game = activeGame.value === 'all' ? 'rust' : activeGame.value
return useGameProfile(game)
})
// ---------------------------------------------------------------------------
// Derived server state — all real, no fallbacks to fabricated values
@@ -298,7 +303,7 @@ function navServer() { router.push('/server') }
<div class="dash__kpis">
<StatCard
icon="users"
:label="profile.statFields[0] + ' online'"
:label="(profile.statFields[0] ?? 'Players') + ' online'"
:value="soloPlayers !== null ? String(soloPlayers) : '—'"
:unit="soloMaxPlayers !== null ? '/' + soloMaxPlayers : ''"
note="live via agent"
@@ -420,8 +425,8 @@ function navServer() { router.push('/server') }
</div>
</Panel>
<!-- Next wipe real schedule from wipeStore -->
<Panel title="Next wipe">
<!-- Next wipe/reset title follows game terminology -->
<Panel :title="'Next ' + profile.terminology.reset.toLowerCase()">
<div v-if="nextWipe" class="solo-wipe">
<div>
<div class="solo-wipe__type">{{ nextWipeType }}</div>
@@ -433,8 +438,8 @@ function navServer() { router.push('/server') }
<EmptyState
v-else
icon="calendar"
title="No wipe scheduled"
description="Configure automatic wipes in the wipe manager."
:title="'No ' + profile.terminology.reset.toLowerCase() + ' scheduled'"
:description="'Configure automatic ' + profile.terminology.reset.toLowerCase() + 's in the wipe manager.'"
>
<template #action>
<Button size="sm" variant="outline" icon="calendar-clock" @click="navWipes">