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

101 lines
4.9 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="landscape-scaler flex h-screen w-full max-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 min-w-0 flex-1 flex-col overflow-auto overflow-x-hidden xl:flex-row xl:overflow-hidden">
{/* xl左|中|右。竖屏:地图→战损→美国基地→伊朗基地→左→右 */}
<main className="flex w-full min-h-[280px] shrink-0 flex-col overflow-hidden xl:order-2 xl:min-h-0 xl:min-w-0 xl:flex-1 xl:shrink">
<div className="h-[45vmin] min-h-[180px] w-full shrink-0 xl:min-h-0 xl:flex-1">
<WarMap />
</div>
<div className="flex shrink-0 flex-col gap-2 overflow-x-auto border-t border-military-border bg-military-panel/95 px-3 py-2 xl:flex-row xl:items-stretch xl:overflow-visible xl:px-4">
<CombatLossesPanel
usLosses={situation.usForces.combatLosses}
iranLosses={situation.iranForces.combatLosses}
conflictStats={situation.conflictStats}
civilianTotal={situation.civilianCasualtiesTotal}
className="min-w-0 flex-1 shrink-0 py-1"
/>
<BaseStatusPanel keyLocations={situation.usForces.keyLocations} className="shrink-0 xl:min-w-[200px] xl:border-r xl:border-military-border xl:pr-4" />
<IranBaseStatusPanel
keyLocations={situation.iranForces.keyLocations}
className="min-w-0 shrink-0 xl: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-b border-military-border p-3 xl:order-1 xl:min-w-[320px] xl:max-w-[340px] xl:border-b-0 xl:border-r xl:p-4">
<div className="flex h-40 shrink-0 flex-col gap-0 rounded-lg border border-military-us/30 bg-military-panel/80 p-1 xl: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>
<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 xl:order-3 xl:min-w-[320px] xl:max-w-[340px] xl:border-t-0 xl:border-l xl:p-4">
<div className="h-40 shrink-0 rounded-lg border border-military-iran/30 bg-military-panel/80 p-1 xl: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>
)
}