Files
spelljammer-ships/web/src/pages/ShipDashboardPage.tsx
Bas van Rossem 88e9bf7f05 feat(web): implement Ship Dashboard with vitals and mobility sections
Adds NumericStepper and EnumDropdown UI components, VitalsSection (hull/armor/AC/con),
MobilitySection (speed/maneuver class/size), with debounced real-time updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:24:53 +01:00

53 lines
1.6 KiB
TypeScript

import { useEffect, useRef, useCallback } from 'react';
import { useParams } from 'react-router-dom';
import TopBar from '../components/layout/TopBar';
import PageContainer from '../components/layout/PageContainer';
import VitalsSection from '../components/dashboard/VitalsSection';
import MobilitySection from '../components/dashboard/MobilitySection';
import { useShipStore } from '../store/use-ship-store';
import type { Ship } from '../types/ship';
export default function ShipDashboardPage() {
const { id } = useParams<{ id: string }>();
const { ship, loading, joinShip, leaveShip, updateShip } = useShipStore();
const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
useEffect(() => {
if (id) joinShip(id);
return () => leaveShip();
}, [id, joinShip, leaveShip]);
const handleUpdate = useCallback(
(patch: Partial<Ship>) => {
// Debounce rapid changes (e.g. stepper clicks)
if (debounceRef.current) clearTimeout(debounceRef.current);
debounceRef.current = setTimeout(() => {
updateShip(patch);
}, 300);
},
[updateShip],
);
if (loading || !ship) {
return (
<>
<TopBar title="Loading..." />
<PageContainer>
<p className="loading-text">Loading ship data...</p>
</PageContainer>
</>
);
}
return (
<>
<TopBar title={ship.name} />
<PageContainer>
<VitalsSection ship={ship} onUpdate={handleUpdate} />
<MobilitySection ship={ship} onUpdate={handleUpdate} />
{/* Weapons and Notes sections will be added next */}
</PageContainer>
</>
);
}