spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
1import type { PowerOverview } from "@dci/core";2import { HonestEmpty } from "@/components/intelligence/shared";3import { CountryFlag } from "@/components/ui/country-flag";4import { RowLink, TBody, THead, Table, Td, Th, Tr } from "@/components/ui/table";5import { fmtInt, fmtMw, fmtPct } from "@/lib/format";6import { routes } from "@/lib/routes";7import { compareBy, parseSort, sortTh, type SearchParams } from "@/lib/sort";89export const ENERGY_SORTS = ["name", "renewable", "twh", "year", "carbon", "mw", "facilities"] as const;10export type EnergySort = (typeof ENERGY_SORTS)[number];11type Row = PowerOverview["countryEnergy"][number];1213function getter(k: EnergySort): (r: Row) => number | string | null {14 switch (k) {15 case "name":16 return (r) => r.name;17 case "renewable":18 return (r) => r.energy.renewableShare;19 case "twh":20 return (r) => r.energy.electricityTwh;21 case "year":22 return (r) => r.energy.statsYear;23 case "carbon":24 return (r) => r.energy.gridCarbonIntensity;25 case "mw":26 return (r) => r.knownMw;27 case "facilities":28 return (r) => r.facilities;29 }30}3132/** National electricity context per country (World Bank vintage) next to the known DC load — sortable via ?sort=&order=. */33export function CountryEnergyTable({ rows, sp }: { rows: Row[]; sp: SearchParams }) {34 if (!rows.length) return <HonestEmpty title="No national energy statistics loaded" detail="the World Bank connector has not populated any country yet" />;35 const sort = parseSort<EnergySort>(sp, ENERGY_SORTS, { key: "facilities", order: "desc" });36 const sorted = [...rows].sort(compareBy(getter(sort.key), sort.order));37 const th = (k: EnergySort) => sortTh(routes.power(), sp, sort, k);38 const source = rows.find((r) => r.energy.sourceName)?.energy.sourceName ?? null;39 return (40 <div>41 <Table dense mobileCollapse={{ total: sorted.length, label: "countries" }}>42 <THead>43 <tr>44 <Th {...th("name")}>Country</Th>45 <Th numeric {...th("renewable")}>46 Renewable share47 </Th>48 <Th numeric className="hidden sm:table-cell" {...th("twh")}>49 Electricity50 </Th>51 <Th numeric className="hidden md:table-cell" {...th("year")}>52 Year53 </Th>54 <Th numeric className="hidden lg:table-cell" {...th("carbon")}>55 Grid carbon56 </Th>57 <Th numeric {...th("mw")}>58 Known DC MW59 </Th>60 <Th numeric className="hidden sm:table-cell" {...th("facilities")}>61 Facilities62 </Th>63 </tr>64 </THead>65 <TBody>66 {sorted.map((r) => (67 <Tr key={r.iso2}>68 <Td primary>69 <RowLink href={routes.country(r.slug)}>70 <span className="inline-flex items-center gap-1.5">71 <CountryFlag iso2={r.iso2} size={12} />72 {r.name}73 </span>74 </RowLink>75 </Td>76 <Td label="Renewable share" numeric lead>77 {r.energy.renewableShare === null ? <span className="text-ink-4">—</span> : fmtPct(r.energy.renewableShare / 100, 1)}78 </Td>79 <Td label="Electricity" numeric className="hidden sm:table-cell">80 {r.energy.electricityTwh === null ? <span className="text-ink-4">—</span> : `${fmtInt(r.energy.electricityTwh)} TWh`}81 </Td>82 <Td label="Year" numeric className="hidden text-ink-3 md:table-cell">83 {r.energy.statsYear ?? <span className="text-ink-4">—</span>}84 </Td>85 <Td label="Grid carbon" numeric className="hidden lg:table-cell">86 {r.energy.gridCarbonIntensity === null ? <span className="text-ink-4" title="No reliable public source connected">not available</span> : `${fmtInt(r.energy.gridCarbonIntensity)} gCO₂/kWh`}87 </Td>88 <Td label="Known DC MW" numeric>89 {r.knownMw === null ? <span className="text-ink-4">—</span> : fmtMw(r.knownMw)}90 </Td>91 <Td label="Facilities" numeric className="hidden sm:table-cell">92 {fmtInt(r.facilities)}93 </Td>94 </Tr>95 ))}96 </TBody>97 </Table>98 <p className="mt-2 text-[11.5px] text-ink-4">{source ? `Source: ${source} (latest available vintage per country). ` : ""}Grid carbon intensity reads “not available” until a reliable public source is connected — it is never estimated.</p>99 </div>100 );101}102