"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 (
{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 MapAll workspaces · gates needing you · live convoy events
Gate inbox across all workspaces
{gateInboxAcross.length > 0 && (No pending gates.
) : (No workspaces or no convoys yet.
) : ({workspace.slug} · {convoys.length} convoys {workspaceGateCount > 0 ? ` · ${workspaceGateCount} needing you` : ""}
By status