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
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:
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user