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:
43
web/src/components/ships/ShipCard.tsx
Normal file
43
web/src/components/ships/ShipCard.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import type { ShipListItem } from '../../types/ship';
|
||||
|
||||
interface Props {
|
||||
ship: ShipListItem;
|
||||
onDelete: (id: string) => void;
|
||||
}
|
||||
|
||||
export default function ShipCard({ ship, onDelete }: Props) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const timeAgo = formatTimeAgo(ship.updated_at);
|
||||
|
||||
return (
|
||||
<div className="ship-card" onClick={() => navigate(`/ship/${ship.id}`)}>
|
||||
<div className="ship-card-info">
|
||||
<span className="ship-card-name">{ship.name}</span>
|
||||
<span className="ship-card-updated">{timeAgo}</span>
|
||||
</div>
|
||||
<button
|
||||
className="btn-icon ship-card-delete"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onDelete(ship.id);
|
||||
}}
|
||||
title="Delete ship"
|
||||
>
|
||||
🗑
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function formatTimeAgo(timestamp: number): string {
|
||||
const seconds = Math.floor((Date.now() - timestamp) / 1000);
|
||||
if (seconds < 60) return 'just now';
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
if (minutes < 60) return `${minutes}m ago`;
|
||||
const hours = Math.floor(minutes / 60);
|
||||
if (hours < 24) return `${hours}h ago`;
|
||||
const days = Math.floor(hours / 24);
|
||||
return `${days}d ago`;
|
||||
}
|
||||
Reference in New Issue
Block a user