import type { OperatorKind } from "@dci/core"; import { OPERATOR_KINDS } from "@dci/core"; import type { Metadata } from "next"; import { Search } from "lucide-react"; import { Badge, EstimateMark } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Page, PageHeader } from "@/components/ui/card"; import { CountryFlag } from "@/components/ui/country-flag"; import { FilterChips, type Chip } from "@/components/ui/filter-chips"; import { Pagination } from "@/components/ui/pagination"; import { EmptyState, OfflineNotice } from "@/components/ui/states"; import { RowLink, TBody, THead, Table, Td, Th, Tr } from "@/components/ui/table"; import { api } from "@/lib/api"; import { countryName, fmtInt, fmtMw } from "@/lib/format"; import { OPERATOR_KIND_LABEL } from "@/lib/labels"; import { routes } from "@/lib/routes"; import { hrefWith, parseSort, sortTh, spGet, spInt, type SearchParams } from "@/lib/sort"; export const revalidate = 120; export const metadata: Metadata = { title: "Operators", description: "Data center operators, hyperscalers, carriers and developers indexed worldwide: facilities, country footprint, known and pipeline capacity.", alternates: { canonical: "/operators" }, }; const PER_PAGE = 50; const SORTS = ["facilities", "name", "mw"] as const; const KIND_SET = new Set(OPERATOR_KINDS); const selectCls = "h-9 min-w-0 rounded-sm border border-hair-2 bg-surface px-2 text-[13px] text-ink focus:outline-none focus-visible:ring-2 focus-visible:ring-accent"; export default async function OperatorsPage({ searchParams }: { searchParams: Promise }) { const sp = await searchParams; const base = routes.operators(); const q = spGet(sp, "q"); const kindRaw = spGet(sp, "kind"); const kind = kindRaw && KIND_SET.has(kindRaw) ? (kindRaw as OperatorKind) : undefined; const country = spGet(sp, "country")?.toUpperCase(); const page = spInt(sp, "page", 1); const sort = parseSort(sp, SORTS, { key: "facilities", order: "desc" }); const [res, countriesRes] = await Promise.all([ api.operators({ q, kind, country, sort: sort.key, order: sort.order, page, per_page: PER_PAGE }), api.countries(), ]); const ok = res.total > 0 || res.items.length > 0 || (await api.health()).ok; const countries = countriesRes.items.filter((c) => c.facilityCount > 0).sort((a, b) => a.name.localeCompare(b.name)); const chips: Chip[] = []; if (q) chips.push({ key: "q", label: "Search", value: q, removeHref: hrefWith(base, sp, { q: undefined }) }); if (kind) chips.push({ key: "kind", label: "Kind", value: OPERATOR_KIND_LABEL[kind], removeHref: hrefWith(base, sp, { kind: undefined }) }); if (country) chips.push({ key: "country", label: "HQ", value: countryName(country), removeHref: hrefWith(base, sp, { country: undefined }) }); const th = (key: (typeof SORTS)[number]) => sortTh(base, sp, sort, key); return ( {!ok && }
{sort.key !== "facilities" && } {sort.key !== "facilities" && }
{res.items.length === 0 ? ( ) : ( {res.items.map((o) => ( ))}
Operator Kind HQ Facilities Countries Metros Known MW Pipeline Projects
{o.name} {o.kind && ( {OPERATOR_KIND_LABEL[o.kind]} )}
{o.kind ? {OPERATOR_KIND_LABEL[o.kind]} : —} {fmtInt(o.facilityCount)} {fmtInt(o.countryCount)} {o.metroCount === undefined ? — : fmtInt(o.metroCount)} {o.knownMw === null || o.knownMw === undefined ? — : fmtMw(o.knownMw)} {o.plannedMw === null || o.plannedMw === undefined ? ( — ) : ( {fmtMw(o.plannedMw)} )} {o.projectCount === undefined ? — : fmtInt(o.projectCount)}
)} hrefWith(base, sp, { page: p > 1 ? p : undefined })} label="operators" />
); }