"use client"; import * as React from "react"; import { gateLabelForStatus } from "@tasks/shared/convoy-lifecycle"; import type { ConvoyStatus } from "@tasks/shared/convoy-lifecycle"; import { Loader2, Radar } from "lucide-react"; import { ConvoyDetailPanel } from "@/components/mission-control/convoy-detail-panel"; import { FleetActivityFeed } from "@/components/fleet/fleet-activity-feed"; import { cn } from "@/lib/utils"; import { api } from "@/lib/trpc"; function formatAge(date: Date | string): string { const d = new Date(date); const diff = Date.now() - d.getTime(); const days = Math.floor(diff / (1000 * 60 * 60 * 24)); if (days > 0) return `${days}d`; const hours = Math.floor(diff / (1000 * 60 * 60)); if (hours > 0) return `${hours}h`; const mins = Math.floor(diff / (1000 * 60)); return `${mins}m`; } export default function FleetPage() { const fleetQuery = api.convoys.fleet.useQuery(); const [selected, setSelected] = React.useState<{ convoyId: string; workspaceSlug: string } | null>(null); if (fleetQuery.isLoading) { return (
Loading fleet…
); } if (fleetQuery.error) { return

{fleetQuery.error.message}

; } const data = fleetQuery.data; const byWorkspace = data?.byWorkspace ?? []; const gateInboxAcross = data?.gateInboxAcross ?? []; // Group gate inbox by status for "× pr_review 2d" count display const gateByStatus = new Map(); for (const c of gateInboxAcross) { const arr = gateByStatus.get(c.status) ?? []; arr.push(c); gateByStatus.set(c.status, arr); } return (

Fleet

All workspaces · gates needing you · live convoy events

{/* Needs you */}

Needs you

Gate inbox across all workspaces

{gateInboxAcross.length > 0 && (
{[...gateByStatus.entries()].map(([status, list]) => ( × {status} {list.length} · {formatAge(list[0]?.updatedAt ?? new Date())} ))}
)}
{gateInboxAcross.length === 0 ? (

No pending gates.

) : (
    {gateInboxAcross.map((convoy) => (
  • ))}
)}
{/* byWorkspace cards grid */}
{byWorkspace.length === 0 ? (

No workspaces or no convoys yet.

) : (
{byWorkspace.map(({ workspace, convoys }) => { const workspaceGateCount = gateInboxAcross.filter((c) => c.workspaceId === workspace.id).length; return (

{workspace.name}

{workspace.slug} · {convoys.length} convoys {workspaceGateCount > 0 ? ` · ${workspaceGateCount} needing you` : ""}

    {convoys.length === 0 ? (
  • No convoys.
  • ) : ( convoys.slice(0, 8).map((convoy) => (
  • )) )} {convoys.length > 8 && (
  • +{convoys.length - 8} more
  • )}
); })}
)} {/* byStatus summary */} {data?.byStatus && Object.keys(data.byStatus).length > 0 && (

By status

{Object.entries(data.byStatus).map(([status, list]) => ( {status}: {(list as unknown[]).length} ))}
)}
{/* Detail panel workspace-agnostic */}
); }