spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
1import type { FacilitySummary } from "@dci/core";2import Link from "next/link";3import { AiMark, EstimateMark, StatusBadge } from "@/components/ui/badge";4import { CountryFlag } from "@/components/ui/country-flag";5import { RowLink, TBody, THead, Table, Td, Th, Tr } from "@/components/ui/table";6import { HonestEmpty } from "@/components/intelligence/shared";7import { bestMw, fmtMw } from "@/lib/format";8import { AI_EVIDENCE_LABEL } from "@/lib/labels";9import { routes } from "@/lib/routes";1011/** AI / HPC facilities with the evidence level per row (confirmed / likely / associated / unknown). */12export function AiFacilitiesTable({ items }: { items: FacilitySummary[] }) {13 if (!items.length) return <HonestEmpty title="No facility with AI evidence yet" detail="a site is listed only when a source describes it as AI / HPC / GPU infrastructure (confirmed or likely)" />;14 return (15 <Table dense mobileCollapse={{ total: items.length, label: "facilities" }}>16 <THead>17 <tr>18 <Th>Facility</Th>19 <Th className="hidden sm:table-cell">Operator</Th>20 <Th className="hidden md:table-cell">Market</Th>21 <Th>Country</Th>22 <Th>Status</Th>23 <Th numeric>Capacity</Th>24 <Th>Evidence</Th>25 </tr>26 </THead>27 <TBody>28 {items.map((f) => {29 const { mw, kind } = bestMw(f);30 const ev = f.aiEvidence ?? "unknown";31 return (32 <Tr key={f.id}>33 <Td primary>34 <RowLink href={routes.facility(f.slug)}>{f.name}</RowLink>35 <div className="text-[11.5px] text-ink-3 sm:hidden">{f.operator?.name ?? "Operator unknown"}</div>36 </Td>37 <Td label="Operator" className="hidden sm:table-cell">38 {f.operator ? (39 <Link href={routes.operator(f.operator.slug)} className="text-ink-2 hover:text-ink hover:underline">40 {f.operator.name}41 </Link>42 ) : (43 <span className="text-ink-4">—</span>44 )}45 </Td>46 <Td label="Market" className="hidden md:table-cell" muted>47 {f.metro ? (48 <Link href={routes.market(f.metro.slug)} className="hover:text-ink hover:underline">49 {f.metro.name}50 </Link>51 ) : (52 (f.city ?? "—")53 )}54 </Td>55 <Td label="Country">56 <CountryFlag iso2={f.countryIso2} withName className="max-w-[140px] text-ink-2" />57 </Td>58 <Td label="Status">59 <StatusBadge status={f.status} short size="xs" />60 </Td>61 <Td label="Capacity" numeric lead>62 {mw === null ? (63 <span className="text-ink-4">—</span>64 ) : (65 <span title={kind === "it" ? "IT capacity" : kind === "total" ? "Total power" : "Planned power"}>66 {(f.mwIsEstimate || kind === "planned") && <EstimateMark className="mr-0.5" />}67 {fmtMw(mw)}68 </span>69 )}70 </Td>71 <Td label="Evidence">72 {ev === "unknown" ? (73 <span className="text-[11.5px] text-ink-4" title={AI_EVIDENCE_LABEL.unknown}>74 flagged AI · evidence level unknown75 </span>76 ) : (77 <AiMark evidence={ev} />78 )}79 </Td>80 </Tr>81 );82 })}83 </TBody>84 </Table>85 );86}87