Dashboard: hide unreachable servers by default + keep card height consistent
All checks were successful
Deploy GSM / deploy (push) Successful in 30s

- Unreachable cards now show a disabled 'Starten' button so moderator cards
  stay the same height as reachable ones
- Dashboard hides unreachable servers by default; a toggle button (bottom
  of header area, only visible when unreachable count > 0) flips the view
  and persists the preference in localStorage

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-19 21:34:55 +02:00
parent 975fb77845
commit dfbcc2da82
2 changed files with 40 additions and 5 deletions

View File

@@ -288,10 +288,18 @@ export default function ServerCard({ server, onClick, isAuthenticated, isGuest,
)}
{/* Server Controls - only for moderators */}
{isModerator && !isUnreachable && (
{isModerator && (
<div className="mt-3 pt-3 border-t border-neutral-800">
<div className="flex flex-wrap gap-2">
{(server.status === 'online' || (server.running && server.status !== 'starting' && server.status !== 'stopping')) ? (
{isUnreachable ? (
<button
disabled
title="Host nicht erreichbar"
className="btn btn-primary btn-sm"
>
Starten
</button>
) : (server.status === 'online' || (server.running && server.status !== 'starting' && server.status !== 'stopping')) ? (
<>
<button
onClick={(e) => handleActionClick('stop', e)}

View File

@@ -20,6 +20,17 @@ export default function Dashboard({ onLogout }) {
const [showLogin, setShowLogin] = useState(false)
const [showSendUpdate, setShowSendUpdate] = useState(false)
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
const [showUnreachable, setShowUnreachable] = useState(() => {
try { return localStorage.getItem('gsm:showUnreachable') === '1' } catch { return false }
})
const toggleShowUnreachable = () => {
setShowUnreachable(v => {
const next = !v
try { localStorage.setItem('gsm:showUnreachable', next ? '1' : '0') } catch {}
return next
})
}
const isGuest = user?.isGuest || role === 'guest'
@@ -72,6 +83,8 @@ export default function Dashboard({ onLogout }) {
const onlineCount = servers.filter(s => s.running).length
document.title = 'Dashboard | Zeasy GSM'
const totalPlayers = servers.reduce((sum, s) => sum + (s.players?.online || 0), 0)
const unreachableCount = servers.filter(s => s.status === 'unreachable').length
const visibleServers = showUnreachable ? servers : servers.filter(s => s.status !== 'unreachable')
return (
<div className="min-h-screen page-enter">
@@ -260,8 +273,21 @@ export default function Dashboard({ onLogout }) {
<div className="text-neutral-400">Lade Server...</div>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{servers.map((server, index) => (
<>
{unreachableCount > 0 && (
<div className="mb-4 flex justify-end">
<button
onClick={toggleShowUnreachable}
className="btn btn-ghost btn-sm text-sm text-neutral-400 hover:text-white"
>
{showUnreachable
? `Nicht erreichbare ausblenden (${unreachableCount})`
: `Nicht erreichbare anzeigen (${unreachableCount})`}
</button>
</div>
)}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{visibleServers.map((server, index) => (
<div
key={server.id}
className="fade-in-up"
@@ -279,7 +305,8 @@ export default function Dashboard({ onLogout }) {
/>
</div>
))}
</div>
</div>
</>
)}
{/* Discord Bot Invite Section */}