feat: ship templates, crew fields, and read/edit dashboard

- Add crew_req, hardpoints, cargo fields (DB migration + server + types)
- Add 10 ship templates from Appendix A (Caravel, Galleon, Sloop, etc.)
- Enhanced CreateShipModal with template picker that auto-fills all stats
- Dashboard defaults to compact read-only view; Edit button toggles to
  editable steppers/dropdowns
- New CrewSection showing crew required, hardpoints, and cargo
- Two-column form layout in create modal for better use of space
- Fix .gitignore data/ pattern to only match root-level data directory

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Bas van Rossem
2026-02-19 17:16:44 +01:00
parent cbda07d793
commit 642f1f70e8
12 changed files with 524 additions and 112 deletions

View File

@@ -1,9 +1,10 @@
import { useEffect } from 'react';
import { useEffect, useState } 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 CrewSection from '../components/dashboard/CrewSection';
import WeaponsSection from '../components/dashboard/WeaponsSection';
import NotesSection from '../components/dashboard/NotesSection';
import { useShipStore } from '../store/use-ship-store';
@@ -11,6 +12,7 @@ import { useShipStore } from '../store/use-ship-store';
export default function ShipDashboardPage() {
const { id } = useParams<{ id: string }>();
const { ship, weapons, loading, joinShip, leaveShip, updateShip, createWeapon, updateWeapon, deleteWeapon } = useShipStore();
const [editing, setEditing] = useState(false);
useEffect(() => {
if (id) joinShip(id);
@@ -32,8 +34,18 @@ export default function ShipDashboardPage() {
<>
<TopBar title={ship.name} />
<PageContainer>
<VitalsSection ship={ship} onUpdate={updateShip} />
<MobilitySection ship={ship} onUpdate={updateShip} />
<div className="dashboard-toolbar">
<button
type="button"
className={editing ? 'btn-primary btn-sm' : 'btn-secondary btn-sm'}
onClick={() => setEditing(!editing)}
>
{editing ? 'Done' : 'Edit'}
</button>
</div>
<VitalsSection ship={ship} onUpdate={updateShip} editing={editing} />
<MobilitySection ship={ship} onUpdate={updateShip} editing={editing} />
<CrewSection ship={ship} onUpdate={updateShip} editing={editing} />
<WeaponsSection
weapons={weapons}
onCreateWeapon={createWeapon}