diff --git a/web/src/components/dashboard/CrewSection.tsx b/web/src/components/dashboard/CrewSection.tsx deleted file mode 100644 index 2a443ff..0000000 --- a/web/src/components/dashboard/CrewSection.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import NumericStepper from '../ui/NumericStepper'; -import type { Ship } from '../../types/ship'; - -interface Props { - ship: Ship; - onUpdate: (patch: Partial) => void; - editing: boolean; -} - -export default function CrewSection({ ship, onUpdate, editing }: Props) { - return ( -
-

Crew & Cargo

- {editing ? ( -
- onUpdate({ crew_req: v })} - /> - onUpdate({ hardpoints: v })} - /> - onUpdate({ cargo: v })} - /> -
- ) : ( -
-
- Crew - {ship.crew_req} -
-
- Hardpoints - {ship.hardpoints} -
-
- Cargo - {ship.cargo}t -
-
- )} -
- ); -} diff --git a/web/src/components/dashboard/MobilitySection.tsx b/web/src/components/dashboard/MobilitySection.tsx deleted file mode 100644 index cf4697f..0000000 --- a/web/src/components/dashboard/MobilitySection.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import NumericStepper from '../ui/NumericStepper'; -import EnumDropdown from '../ui/EnumDropdown'; -import type { Ship } from '../../types/ship'; - -const MANEUVER_CLASSES = ['S', 'A', 'B', 'C', 'D', 'E', 'F']; -const SIZE_CATEGORIES = ['Tiny', 'Small', 'Medium', 'Large', 'Huge', 'Gargantuan']; - -interface Props { - ship: Ship; - onUpdate: (patch: Partial) => void; - editing: boolean; -} - -export default function MobilitySection({ ship, onUpdate, editing }: Props) { - return ( -
-

Mobility

- {editing ? ( -
- onUpdate({ speed: v })} - /> - onUpdate({ maneuver_class: v })} - /> - onUpdate({ size_category: v })} - /> -
- ) : ( -
-
- Speed - {ship.speed ?? 0}ft -
-
- Class - {ship.maneuver_class ?? '—'} -
-
- Size - {ship.size_category ?? '—'} -
-
- )} -
- ); -} diff --git a/web/src/components/dashboard/ShipStatsSection.tsx b/web/src/components/dashboard/ShipStatsSection.tsx new file mode 100644 index 0000000..2da9785 --- /dev/null +++ b/web/src/components/dashboard/ShipStatsSection.tsx @@ -0,0 +1,89 @@ +import { useState } from 'react'; +import NumericStepper from '../ui/NumericStepper'; +import EnumDropdown from '../ui/EnumDropdown'; +import type { Ship } from '../../types/ship'; + +const MANEUVER_CLASSES = ['S', 'A', 'B', 'C', 'D', 'E', 'F']; +const SIZE_CATEGORIES = ['Tiny', 'Small', 'Medium', 'Large', 'Huge', 'Gargantuan']; + +interface Props { + ship: Ship; + onUpdate: (patch: Partial) => void; +} + +export default function ShipStatsSection({ ship, onUpdate }: Props) { + const [editing, setEditing] = useState(false); + + return ( +
+
+

Ship Stats

+ +
+ + {editing ? ( +
+ onUpdate({ hull_max: v })} /> + onUpdate({ armor_max: v })} /> + onUpdate({ ac: v })} /> + onUpdate({ con_save: v })} /> + onUpdate({ speed: v })} /> + onUpdate({ maneuver_class: v })} /> + onUpdate({ size_category: v })} /> + onUpdate({ crew_req: v })} /> + onUpdate({ hardpoints: v })} /> + onUpdate({ cargo: v })} /> +
+ ) : ( +
+
+ AC + {ship.ac} +
+
+ Con + {ship.con_save != null ? `+${ship.con_save}` : '—'} +
+
+ Hull Max + {ship.hull_max} +
+
+ Armor Max + {ship.armor_max} +
+
+ Speed + {ship.speed ?? 0}ft +
+
+ Class + {ship.maneuver_class ?? '—'} +
+
+ Size + {ship.size_category ?? '—'} +
+
+ Crew + {ship.crew_req} +
+
+ Hardpoints + {ship.hardpoints} +
+
+ Cargo + {ship.cargo}t +
+
+ )} +
+ ); +} diff --git a/web/src/components/dashboard/VitalsSection.tsx b/web/src/components/dashboard/VitalsSection.tsx index 8b0806f..346a253 100644 --- a/web/src/components/dashboard/VitalsSection.tsx +++ b/web/src/components/dashboard/VitalsSection.tsx @@ -4,70 +4,29 @@ import type { Ship } from '../../types/ship'; interface Props { ship: Ship; onUpdate: (patch: Partial) => void; - editing: boolean; } -export default function VitalsSection({ ship, onUpdate, editing }: Props) { +export default function VitalsSection({ ship, onUpdate }: Props) { return (
-

Vitals

- {editing ? ( -
+
+
onUpdate({ hull_current: v })} /> +
+
onUpdate({ hull_max: v })} - /> - onUpdate({ armor_current: v })} /> - onUpdate({ armor_max: v })} - /> - onUpdate({ ac: v })} - /> - onUpdate({ con_save: v })} - />
- ) : ( -
-
- Hull - {ship.hull_current}/{ship.hull_max} -
-
- AC - {ship.ac} -
-
- Armor - {ship.armor_current}/{ship.armor_max} -
-
- Con - {ship.con_save != null ? `+${ship.con_save}` : '—'} -
-
- )} +
); } diff --git a/web/src/index.css b/web/src/index.css index 5c8f204..342b25b 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -321,10 +321,17 @@ button:disabled { padding-bottom: var(--spacing-xs); } -.dashboard-toolbar { - display: flex; - justify-content: flex-end; - margin-bottom: var(--spacing-md); +.combat-stats { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--spacing-md); +} + +.combat-stat { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius); + padding: var(--spacing-sm); } .stat-grid { diff --git a/web/src/pages/ShipDashboardPage.tsx b/web/src/pages/ShipDashboardPage.tsx index c93ab64..078e06e 100644 --- a/web/src/pages/ShipDashboardPage.tsx +++ b/web/src/pages/ShipDashboardPage.tsx @@ -1,10 +1,9 @@ -import { useEffect, useState } from 'react'; +import { useEffect } 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 ShipStatsSection from '../components/dashboard/ShipStatsSection'; import WeaponsSection from '../components/dashboard/WeaponsSection'; import NotesSection from '../components/dashboard/NotesSection'; import { useShipStore } from '../store/use-ship-store'; @@ -12,7 +11,6 @@ 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); @@ -34,18 +32,8 @@ export default function ShipDashboardPage() { <> -
- -
- - - + +