'use client' import { useEffect, useState } from 'react' import { Badge } from '@/components/ui/badge' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import type { CrewDto, CrewState } from '@/lib/game/save' // CREW tab — the ship's roster: starting crew plus members found while exploring. Fetches // /api/crew on mount; Radix unmounts inactive tabs, so opening this tab always refetches // (no polling needed — turn-based game). Display-only for now: no dismiss/assign actions yet. interface CrewPanelProps { narrow?: boolean } export function CrewPanel({ narrow }: CrewPanelProps) { const [roster, setRoster] = useState(null) const [error, setError] = useState(null) useEffect(() => { let cancelled = false fetch('/api/crew') .then(async (res) => { if (!res.ok) throw new Error(`HTTP ${res.status}`) return (await res.json()) as CrewState // { crew, tasks } — the endpoint wraps the roster (JC-7) }) .then((r) => { if (!cancelled) setRoster(r.crew) }) .catch((err: unknown) => { if (!cancelled) setError(err instanceof Error ? err.message : String(err)) }) return () => { cancelled = true } }, []) if (error && !roster) { return (
CREW MANIFEST OFFLINE // {error.toUpperCase()}
) } if (!roster) { return (
LOADING CREW MANIFEST…
) } return (
{roster.map((member) => (
{member.name} ACTIVE

{member.role}

+ {member.traitGood}
- {member.traitBad}

ORIGIN // {member.origin.toUpperCase()}

))}
) }