/** * Overview — the landing view. * * Leads with margin and idle capacity rather than deal counts, because those * are the numbers this business actually turns on. A CRM that opens on * "23 open opportunities" tells you nothing about whether you are making money. * * The one thing that outranks the money is the licence to operate. An export * authorisation nobody renewed converts lawful business into unlawful business, * and the Calendar — where every other dated risk lives — can only ever report * the quarter being read. So a lapse is reported here, in the first screenful, * however long ago it happened. */ import { useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { AlertTriangle, ArrowRight, Plus, Server, ShieldAlert } from 'lucide-react'; import { Link } from 'react-router-dom'; import { compactNumber, get, money, percent, relativeTime, shortDate, unitPrice, } from '@/lib/api'; import { Badge, Button, Card, CardContent, CardHeader, CardTitle, EmptyState, Skeleton, Stat, cn, } from '@/components/ui'; import { withoutDemoPrefix } from '@/lib/utils'; import { CommitmentSheet } from '@/components/RecordSheets'; import { usePageTitle } from '@/lib/title'; import { usePiggyContext } from '@/lib/piggy-context'; import { useIdentity } from '@/lib/identity'; import { can } from '@/lib/permissions'; interface ComplianceItem { id: string; kind: 'authorization' | 'artifact'; /** The specific instrument — "Export licence", "SOC 2" — not the table it came from. */ label: string; reference: string | null; accountId: string | null; accountName: string | null; expiresAt: string; lapsed: boolean; volatile: boolean; href: string; } interface Dashboard { me: { name: string; teams: { team: string; role: string }[] }; margin: { revenueCents: number; costCents: number; grossMarginCents: number; grossMarginPct: number | null; marginPerAllocatedGpuHourCents: number | null; utilisation: number; idleGpuHours: number; committedGpuHours: number; allocatedGpuHours: number; }; blocks: number; openDemandDeals: number; openDemandAcvCents: number; openSupplyDeals: number; compliance: { horizonDays: number; lapsedCount: number; expiringCount: number; items: ComplianceItem[]; }; idleAlerts: { commitmentId: string; name: string; gpuType: string; gpuCount: number; idleCostCents: number; utilisation: number; breakEvenPriceCents: number | null; }[]; recentActivity: { id: string; type: string; subject: string | null; accountName: string | null; occurredAt: string; }[]; } export function Overview() { usePageTitle('Overview'); const me = useIdentity(); const [recordingCommitment, setRecordingCommitment] = useState(false); const { data, isLoading, error, refetch } = useQuery({ queryKey: ['dashboard'], queryFn: () => get('/api/dashboard'), // The book does not change second to second, but it does change while // someone is looking at it during a pipeline review. refetchInterval: 60_000, }); /* * Published unconditionally — hooks cannot hide behind the loading return * below — and labelled from the figures once they arrive, so the dock names * the book the reader is looking at rather than repeating the route. */ usePiggyContext({ type: 'page', route: '/', ...(data ? { label: `Overview — ${percent(data.margin.grossMarginPct, 1)} margin, ${percent( data.margin.utilisation, )} of committed capacity sold`, } : {}), }); if (isLoading) { return (
{Array.from({ length: 4 }).map((_, i) => ( ))}
); } if (error || !data) { return ( ); } const m = data.margin; const marginTone = m.grossMarginCents >= 0 ? 'positive' : 'danger'; // The seeded book prefixes every name with its demonstration marker, and a // positional read of that took the label for the person: "Good evening, // DEMO" was the first line of the screen everyone opens. const firstName = withoutDemoPrefix(data.me.name).split(' ')[0]; const idleExposureCents = data.idleAlerts.reduce((sum, alert) => sum + alert.idleCostCents, 0); /* * Recording what capacity was bought is a supply lead's authority, not * everyone's. Offering the button to someone the server will refuse turns an * empty screen into a 403, which is a worse dead end than the one it fixes. */ const canRecordCommitment = can(me, 'commitment:write', 'supply'); return (

{greeting()}, {firstName}

{data.blocks === 0 ? 'No capacity commitments yet — margin appears once you record what you have bought.' : `${data.blocks} capacity commitment${data.blocks === 1 ? '' : 's'} on the book.`}

0 && m.utilisation < 0.6 ? 'warning' : 'default'} /> 0 ? 'warning' : 'default'} /> {/* The value of what is open rather than a count of it — a count is the one figure on this page nobody can act on. The money is demand ACV alone, because a supply deal carries GPUs and a target cost and never a contract value; both counts stay in the hint, where they now agree with the two pipeline boards. */}
{data.idleAlerts.length > 0 ? (
Capacity you are paying for and not selling

Prioritized by idle cost exposure.

{money(idleExposureCents)}
{data.idleAlerts.map((alert) => (

{alert.name}

{alert.gpuCount}× {alert.gpuType} · {percent(alert.utilisation)} sold {/* A zero break-even means the block's cost is already covered, so any further sale is upside. Printing "break even above $0.00" is technically true and reads like a bug, so it is said in words instead. */} {alert.breakEvenPriceCents == null ? null : alert.breakEvenPriceCents > 0 ? ( <> {' · '}break even above{' '} {unitPrice(alert.breakEvenPriceCents)}/GPU-hr ) : ( <>{' · '}cost already covered — further sales are upside )}

{money(alert.idleCostCents)} Match
))}
) : null} {/* `items-start` so a short book does not stretch to the height of a busy activity feed and open a hole under its last row. */}
The book
{/* The blended rate, which is what a block is actually judged on: a book can clear millions and still be selling GPU-hours for pennies over what they cost. */}

Cost is charged against the full commitment, not only the hours that sold — unsold hours are already paid for.

Recent activity {data.recentActivity.length === 0 ? (

Nothing logged yet.

) : (
    {data.recentActivity.slice(0, 6).map((activity) => (
  • {activity.type.replace('_', ' ')} {activity.subject ?? '—'} {activity.accountName ? ( {activity.accountName} ) : null} {relativeTime(activity.occurredAt)}
  • ))}
)}
{data.blocks === 0 ? ( } title="No capacity on the book yet" description={ canRecordCommitment ? 'Record a capacity commitment — what you bought, at what cost, over what term — and margin, utilisation and idle alerts all follow from it.' : 'Margin, utilisation and idle alerts all follow from a recorded capacity commitment. Recording one needs supply-lead authority — ask a supply lead to add the first block.' } action={ canRecordCommitment ? ( ) : null } /> ) : null} {/* Mounted outside the empty state it is opened from: recording the first block makes `blocks` non-zero, and a sheet that unmounts underneath its own success toast closes with a jump. */}
); } /** * The compliance tile. * * Always rendered, never collapsed to nothing when the news is good: a card * that appears only in trouble teaches the reader that its absence means * nothing was checked. The tone escalates instead — quiet when clear, warning * inside the horizon, and danger the moment anything has lapsed. */ function LicenceToOperate({ compliance }: { compliance: Dashboard['compliance'] }) { const lapsed = compliance.lapsedCount > 0; const expiring = compliance.expiringCount > 0; /* * Three rows, however many are dated. The server sorts lapsed first, so the * rows that survive the cut are never the ones this card exists for; the * remainder is a queue, and a queue belongs on the Calendar's compliance * lane rather than on the screen everyone opens first. */ const shown = compliance.items.slice(0, COMPLIANCE_ROWS); const remaining = compliance.lapsedCount + compliance.expiringCount - shown.length; const hiddenLapsed = compliance.lapsedCount - shown.filter((item) => item.lapsed).length; return (
Licence to operate

{lapsed ? 'An expired export authorisation converts lawful business into unlawful business.' : `Export authorisations and attestations expiring within ${compliance.horizonDays} days.`}

{lapsed ? `${compliance.lapsedCount} lapsed` : expiring ? `${compliance.expiringCount} expiring` : 'Clear'}
{shown.length === 0 ? (

Nothing on file has lapsed, and nothing expires in the next {compliance.horizonDays} days. A counterparty with no authorisation recorded at all is not covered by this check.

) : ( shown.map((item) => ) )} {remaining > 0 ? ( {hiddenLapsed > 0 ? `${remaining} more, ${hiddenLapsed} of them lapsed` : `${remaining} more expiring within ${compliance.horizonDays} days`} ) : null}
); } function ComplianceRow({ item }: { item: ComplianceItem }) { const days = daysUntil(item.expiresAt); const detail = [ item.kind === 'authorization' ? 'Export authorisation' : 'Compliance artefact', item.reference, // The date on file cannot be trusted for this counterparty; say so where // the deadline is read, not on a screen nobody opens. item.volatile ? 'rules in flux, re-verify' : null, ].filter((part): part is string => Boolean(part)); return (

{item.label} {item.accountName ? — {item.accountName} : null}

{detail.join(' · ')}

{item.lapsed ? `Lapsed ${shortDate(item.expiresAt)} · ${Math.abs(days)}d ago` : `Expires ${shortDate(item.expiresAt)} · ${days}d`} Review
); } const COMPLIANCE_ROWS = 3; const DAY_MS = 86_400_000; /** Whole days, negative once the date has passed. Rounded, as the Calendar rounds. */ function daysUntil(value: string): number { return Math.round((new Date(value).getTime() - Date.now()) / DAY_MS); } function Row({ label, value, emphasis, tone, }: { label: string; value: string; emphasis?: boolean; tone?: 'positive' | 'danger'; }) { return (
{label} {value}
); } function greeting(): string { const hour = new Date().getHours(); if (hour < 12) return 'Good morning'; if (hour < 18) return 'Good afternoon'; return 'Good evening'; }