feat(web): implement Ship List page with create and delete modals

Adds ship cards with navigation, create ship modal with initial stats,
inline delete confirmation, and supporting CSS for modals and cards.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Bas van Rossem
2026-02-19 16:23:00 +01:00
parent 06428f79cd
commit 130cffd3c1
5 changed files with 360 additions and 1 deletions

View File

@@ -1,12 +1,74 @@
import { useEffect, useState } from 'react';
import TopBar from '../components/layout/TopBar';
import PageContainer from '../components/layout/PageContainer';
import ShipCard from '../components/ships/ShipCard';
import CreateShipModal from '../components/ships/CreateShipModal';
import { useShipsList } from '../store/use-ships-list';
export default function ShipListPage() {
const { ships, loading, fetchShips, deleteShip } = useShipsList();
const [showCreate, setShowCreate] = useState(false);
const [pendingDelete, setPendingDelete] = useState<string | null>(null);
useEffect(() => {
fetchShips();
}, [fetchShips]);
const handleDelete = async (id: string) => {
setPendingDelete(id);
};
const confirmDelete = async () => {
if (!pendingDelete) return;
await deleteShip(pendingDelete);
setPendingDelete(null);
};
return (
<>
<TopBar title="Ships" />
<PageContainer>
<p style={{ color: 'var(--color-text-muted)' }}>Ship list coming soon...</p>
<div className="ship-list-header">
<button className="btn-primary" onClick={() => setShowCreate(true)}>
+ Create Ship
</button>
</div>
{loading && <p className="loading-text">Loading ships...</p>}
{!loading && ships.length === 0 && (
<p className="empty-text">No ships yet. Create one to get started!</p>
)}
<div className="ship-list">
{ships.map((ship) => (
<ShipCard key={ship.id} ship={ship} onDelete={handleDelete} />
))}
</div>
<CreateShipModal open={showCreate} onClose={() => setShowCreate(false)} />
{/* Simple delete confirmation */}
{pendingDelete && (
<div className="modal-overlay" onClick={() => setPendingDelete(null)}>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
<div className="modal-header">
<h2 className="modal-title">Delete Ship?</h2>
</div>
<p style={{ margin: 'var(--spacing-md) 0' }}>
This will permanently delete this ship and all its weapons.
</p>
<div className="modal-actions">
<button className="btn-secondary" onClick={() => setPendingDelete(null)}>
Cancel
</button>
<button className="btn-danger" onClick={confirmDelete}>
Delete
</button>
</div>
</div>
</div>
)}
</PageContainer>
</>
);