Files
suaveplan/openspec/changes/enterprise-react-port-tracking/tasks.md
2026-05-27 23:29:53 +01:00

5.6 KiB
Raw Blame History

Tasks: enterprise-react-port-tracking

Change ID: enterprise-react-port-tracking Package: @suaveplan/react-port-tracking Target path: react/platform/react-port-tracking Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/events, @suaveplan/ports, @suaveplan/react-map, @suaveplan/react-translate


0. Pre-flight (non-negotiable)

  • 0.1 Confirm clean working tree (git status reports nothing) and no in-flight worktrees with uncommitted work (git worktree list then git status in each)
  • 0.2 If any worktrees exist under .claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
  • 0.3 Confirm the package set in MANIFEST.md matches find packages -maxdepth 3 -name package.json count. Drift here means a prior change archived without regenerating the manifest.

1. Scaffold

  • Create directory tree. Write package.json at 0.1.0, tsconfig.json, vitest.config.ts, scripts.
  • Dependencies: @suaveplan/error workspace:^, @suaveplan/events workspace:^, @suaveplan/ports workspace:^, @suaveplan/react-map workspace:^, @suaveplan/react-translate workspace:^, @opentelemetry/api catalog:observability, zod catalog:forms, tslib catalog:build.

2. Error codes and types

  • Define PortTrackingError; codes: PORT_SEARCH_FAILED, VESSEL_TRACK_FAILED, ETA_ESTIMATE_FAILED.
  • Define all types: ETAPanelProps, PortInfoCardProps, PortMapProps, PortMarkerProps, ShippingLaneOverlayProps, VesselPosition, VesselTrackerProps, UseETAEstimateOptions, UseETAEstimateReturn, UsePortSearchOptions, UsePortSearchReturn, ShippingLaneWithDistance, UseShippingLanesReturn, UseVesselTrackingOptions, UseVesselTrackingReturn, PortIconType.

3. Utils

port-icons.ts

  • portIconPaths: Record<PortIconType, string> — SVG path strings for sea/air/rail/multimodal port icon types.
  • Write port-icons.test.ts (≤500 lines): all icon types present, paths are valid non-empty strings. { timeout: 5000 }.
  • Write port-icons.md.

4. Hooks

usePortSearch

  • Searches ports via @suaveplan/ports. Returns { results, loading, error, search }. OTel port.search span. Throws PortTrackingError(PORT_SEARCH_FAILED) on engine error.
  • Write test + md.

useShippingLanes

  • Loads shipping lanes with distance from a reference point. Returns { lanes, loading, error }.
  • Write test + md.

useETAEstimate

  • Computes ETA from current position + route via @suaveplan/ports. Returns { eta, distance, speed, loading, error }. OTel vessel.eta.estimate span.
  • Write test + md.

useVesselTracking

  • Subscribes to vessel position updates via @suaveplan/events. Returns { position, history, loading, error }. OTel vessel.position.update counter. Throws PortTrackingError(VESSEL_TRACK_FAILED) on connection failure.
  • Write use-vessel-tracking.test.ts (≤500 lines): initial position, position update event, history accumulates, unsubscribe on unmount. { timeout: 10000 }.
  • Write use-vessel-tracking.md.

5. Components

PortMarker

  • SVG marker using portIconPaths for port type. Accepts port, onClick, ARIA label via useTranslation.
  • Write test, stories (all-types, selected, playground), md.

ETAPanel

  • Displays ETA, distance, speed. Labels "Arriving" / "Delayed" via useTranslation. Handles null ETA with "–".
  • Write test, stories (arriving, delayed, unknown, playground), md.

PortInfoCard

  • Port card with facilities, name, type, coordinates. All labels via useTranslation.
  • Write test, stories (default, with-facilities, no-facilities, playground), md.

ShippingLaneOverlay

  • Renders shipping lanes as Polygon / polylines on @suaveplan/react-map canvas.
  • Write shipping-lane-overlay.test.tsx (≤500 lines): renders lanes on map, no-lanes empty state. { timeout: 5000 }.
  • Write stories (default, multi-lane, highlighted, playground), md.

VesselTracker

  • Renders vessel icon at current position using @suaveplan/react-map Marker. Shows course line. Updates smoothly on position change.
  • Write vessel-tracker.test.tsx (≤500 lines): renders at position, updates on new position event, shows course. { timeout: 5000 }.
  • Write stories (default, in-motion, anchored, playground), md.

PortMap

  • Composite: MapView from @suaveplan/react-map + PortMarker[] + ShippingLaneOverlay + VesselTracker[]. Accepts adapter prop forwarded to MapView.
  • Write port-map.test.tsx (≤500 lines): renders map + markers + overlays, vessel positions updated, empty markers state. { timeout: 10000 }.
  • Write stories (default, with-vessels, with-lanes, loading, playground), md.

6. E2E

  • e2e/port-tracking.spec.ts — Playwright:
    • Render PortMap with test data; verify port markers present.
    • Simulate vessel position update event; verify VesselTracker moves.
    • Verify ETAPanel shows "Arriving" label for an in-bound vessel.
    • Test search for a port; verify PortInfoCard renders for the result.

7. Verify and publish

  • bunx turbo lint typecheck test --filter=@suaveplan/react-port-tracking — green.
  • bunx turbo test:coverage --filter=@suaveplan/react-port-tracking — 100%.
  • bun scripts/publish.ts --package @suaveplan/react-port-tracking.
  • Archive change folder.