Files
usa/src/pages/Dashboard.tsx
2026-03-02 16:29:11 +08:00

100 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useEffect } from 'react'
import { HeaderPanel } from '@/components/HeaderPanel'
import { TimelinePanel } from '@/components/TimelinePanel'
import { ForcePanel } from '@/components/ForcePanel'
import { WarMap } from '@/components/WarMap'
import { CombatLossesPanel } from '@/components/CombatLossesPanel'
import { IranBaseStatusPanel } from '@/components/IranBaseStatusPanel'
import { BaseStatusPanel } from '@/components/BaseStatusPanel'
import { PowerChart } from '@/components/PowerChart'
import { InvestmentTrendChart } from '@/components/InvestmentTrendChart'
import { RetaliationGauge } from '@/components/RetaliationGauge'
import { useSituationStore } from '@/store/situationStore'
import { useReplaySituation } from '@/hooks/useReplaySituation'
import { fetchAndSetSituation, startSituationWebSocket, stopSituationWebSocket } from '@/store/situationStore'
export function Dashboard() {
const situation = useReplaySituation()
const isLoading = useSituationStore((s) => s.isLoading)
const lastError = useSituationStore((s) => s.lastError)
useEffect(() => {
fetchAndSetSituation().finally(() => startSituationWebSocket())
return () => stopSituationWebSocket()
}, [])
return (
<div className="flex h-screen w-full min-h-0 flex-col overflow-hidden bg-military-dark font-orbitron">
{lastError && (
<div className="shrink-0 bg-amber-500/20 px-4 py-2 text-center text-sm text-amber-400">
{lastError}使 API + WebSocket npm run api
</div>
)}
<HeaderPanel />
<TimelinePanel />
<div className="flex min-h-0 flex-1 flex-col overflow-auto lg:flex-row lg:overflow-hidden">
<aside className="flex min-h-0 min-w-0 shrink-0 flex-col gap-2 overflow-y-auto overflow-x-visible border-b border-military-border p-3 lg:min-w-[320px] lg:max-w-[340px] lg:border-b-0 lg:border-r lg:p-4">
<div className="flex h-44 shrink-0 flex-col gap-0 rounded-lg border border-military-us/30 bg-military-panel/80 p-1 lg:h-48">
<div className="h-[55%] min-h-0 shrink-0">
<PowerChart
usPower={situation.usForces.powerIndex}
iranPower={situation.iranForces.powerIndex}
className="h-full w-full"
/>
</div>
<div className="h-[45%] min-h-0 shrink-0">
<InvestmentTrendChart
history={situation.usForces.wallStreetInvestmentTrend}
className="h-full"
/>
</div>
</div>
<ForcePanel
side="us"
summary={situation.usForces.summary}
powerIndex={situation.usForces.powerIndex}
assets={situation.usForces.assets}
/>
</aside>
<main className="flex min-h-[200px] min-w-0 flex-1 flex-col overflow-hidden">
<div className="min-h-0 flex-1">
<WarMap />
</div>
<div className="flex shrink-0 flex-col gap-2 border-t border-military-border bg-military-panel/95 px-4 py-2 lg:flex-row lg:items-stretch">
<BaseStatusPanel keyLocations={situation.usForces.keyLocations} className="shrink-0 lg:min-w-[200px] lg:border-r lg:border-military-border lg:pr-4" />
<CombatLossesPanel
usLosses={situation.usForces.combatLosses}
iranLosses={situation.iranForces.combatLosses}
conflictStats={situation.conflictStats}
civilianTotal={situation.civilianCasualtiesTotal}
className="min-w-0 flex-1 py-1"
/>
<IranBaseStatusPanel
keyLocations={situation.iranForces.keyLocations}
className="min-w-0 shrink-0 lg:min-w-[200px]"
/>
</div>
</main>
<aside className="flex min-h-0 min-w-0 shrink-0 flex-col gap-2 overflow-y-auto overflow-x-visible border-t border-military-border p-3 lg:min-w-[320px] lg:max-w-[340px] lg:border-t-0 lg:border-l lg:p-4">
<div className="h-44 shrink-0 rounded-lg border border-military-iran/30 bg-military-panel/80 p-1 lg:h-48">
<RetaliationGauge
value={situation.iranForces.retaliationSentiment}
history={situation.iranForces.retaliationSentimentHistory}
className="h-full"
/>
</div>
<ForcePanel
side="iran"
summary={situation.iranForces.summary}
powerIndex={situation.iranForces.powerIndex}
assets={situation.iranForces.assets}
/>
</aside>
</div>
</div>
)
}