- Restructure flat static prototype into pnpm workspace monorepo - apps/game: playable shell with R3F 3D scene, HUD, SpacetimeDB connection - apps/docs: design docs and prototypes - apps/site: landing page - packages/ui: shared Button and Panel primitives - services/spacetimedb: backend module (9 tables, 11 reducers) - Archive legacy static files to archive/legacy-static/ - Game loop: connect, undock, target, approach, dock, mine, sell - Add pnpm-workspace.yaml, tsconfig.base.json, spacetime.json
60 lines
2.1 KiB
TypeScript
60 lines
2.1 KiB
TypeScript
import { Button, Panel } from "@void-nav/ui";
|
|
import type { PointOfInterest, Ship } from "../module_bindings/types";
|
|
|
|
export function TargetPanel({
|
|
ship,
|
|
pois,
|
|
selected,
|
|
onSelect,
|
|
}: {
|
|
ship?: Ship;
|
|
pois: PointOfInterest[];
|
|
selected?: PointOfInterest;
|
|
onSelect: (poiId: string) => void;
|
|
}) {
|
|
const current = pois.find((poi) => poi.poiId === ship?.currentPoiId);
|
|
|
|
return (
|
|
<Panel className="p-4">
|
|
<div className="flex items-start justify-between gap-3">
|
|
<div>
|
|
<p className="m-0 font-mono text-xs uppercase tracking-[0.1em] text-muted">Selected Target</p>
|
|
<h2 className="m-0 mt-1 text-lg leading-tight text-fg-bright">{selected?.name ?? "No target selected"}</h2>
|
|
</div>
|
|
<span className="rounded-md border border-border bg-bg-subtle px-2 py-1 font-mono text-xs uppercase tracking-[0.08em] text-fg-dim">
|
|
{ship?.flightMode ?? "offline"}
|
|
</span>
|
|
</div>
|
|
|
|
<dl className="mt-3 grid gap-2 text-sm">
|
|
<InfoRow label="Current" value={current?.name ?? "Unknown"} />
|
|
<InfoRow label="Target type" value={selected?.poiType.replace("_", " ") ?? "Select in scene or list"} />
|
|
</dl>
|
|
|
|
<div className="mt-4 grid gap-2">
|
|
{pois.map((poi) => (
|
|
<Button
|
|
key={poi.poiId}
|
|
tone={selected?.poiId === poi.poiId ? "primary" : "secondary"}
|
|
className="min-h-9 w-full justify-between px-3 text-left"
|
|
onClick={() => onSelect(poi.poiId)}
|
|
disabled={!ship}
|
|
>
|
|
<span className="flex-1 text-left">{poi.name}</span>
|
|
<span className="shrink-0 pl-3 font-mono text-xs opacity-75">{poi.poiType === "asteroid_belt" ? "Belt" : "Station"}</span>
|
|
</Button>
|
|
))}
|
|
</div>
|
|
</Panel>
|
|
);
|
|
}
|
|
|
|
function InfoRow({ label, value }: { label: string; value: string }) {
|
|
return (
|
|
<div className="grid grid-cols-[5.5rem_1fr] gap-2 border-t border-border pt-2">
|
|
<dt className="font-mono text-xs uppercase tracking-[0.08em] text-muted">{label}</dt>
|
|
<dd className="m-0 text-fg">{value}</dd>
|
|
</div>
|
|
);
|
|
}
|