fix(ui): refresh LOCAL SYSTEM after a jump instead of waiting for a page reload (#30)
CI / build + unit + e2e (pull_request) Successful in 2m39s

WorldMapPanel owns the world state and applied the /api/jump response
locally, so MissionControl's lifted /api/system state (LOCAL SYSTEM tab,
CARGO HOLD, SECTOR row) stayed on the previous system until a full refresh.
The panel now takes an onJumped callback that MissionControl wires to an
/api/system refetch after every successful jump.
This commit is contained in:
2026-09-29 10:00:18 +00:00
parent e6c88b10c2
commit e27ff7015e
5 changed files with 48 additions and 5 deletions
+15 -2
View File
@@ -1,6 +1,6 @@
'use client'
import { useEffect, useState } from 'react'
import { useCallback, useEffect, useState } from 'react'
import { Badge } from '@/components/ui/badge'
import { Panel, PanelContent, PanelHeader, PanelTitle } from '@/components/ui/panel'
import { Progress } from '@/components/ui/progress'
@@ -112,6 +112,19 @@ export function MissionControl() {
if (stored && TAB_IDS.includes(stored)) setActiveTab(stored)
}, [])
// #30 — re-fetch /api/system after a jump: WorldMapPanel owns the world state, so without this
// the lifted system state stays on the previous system until a page refresh. Same failure
// policy as the mount fetch — keep the old state on error.
const refreshSystem = useCallback(() => {
fetch('/api/system')
.then(async (res) => {
if (!res.ok) throw new Error(`HTTP ${res.status}`)
return (await res.json()) as SystemState
})
.then((s) => setSystem(s))
.catch(() => {})
}, [])
const timeStr = new Date().toLocaleTimeString('en-GB', { hour12: false })
// Slugs of the researched techs — drives the effective caps + build gates in the SHIP SYSTEMS
@@ -395,7 +408,7 @@ export function MissionControl() {
{/* WORLD MAP TAB — live data from /api/world */}
<TabsContent value="world-map" style={{ margin: 0, padding: '1rem' }}>
<WorldMapPanel height={380} />
<WorldMapPanel height={380} onJumped={refreshSystem} />
</TabsContent>
{/* LOCAL SYSTEM TAB — live data (state owned by MissionControl; scans report up) */}
+4 -2
View File
@@ -11,9 +11,10 @@ import type { WorldState } from '@/lib/game/save'
interface WorldMapPanelProps {
height?: number
onJumped?: () => void // #30 — let the parent refresh /api/system after a successful jump
}
export function WorldMapPanel({ height = 380 }: WorldMapPanelProps) {
export function WorldMapPanel({ height = 380, onJumped }: WorldMapPanelProps) {
const [world, setWorld] = useState<WorldState | null>(null)
const [error, setError] = useState<string | null>(null)
const [jumpingId, setJumpingId] = useState<number | null>(null)
@@ -47,12 +48,13 @@ export function WorldMapPanel({ height = 380 }: WorldMapPanelProps) {
const body = (await res.json()) as WorldState & { error?: string }
if (!res.ok) throw new Error(body.error ?? `HTTP ${res.status}`)
setWorld(body) // fresh state straight from the response — no refetch needed
onJumped?.() // #30 — parent re-fetches /api/system (LOCAL SYSTEM + CARGO HOLD mirror it)
} catch (err: unknown) {
setError(err instanceof Error ? err.message : String(err))
} finally {
setJumpingId(null)
}
}, [])
}, [onJumped])
if (error && !world) {
return (