SPB Git forge
38commits 1branches 0releases
338.7 MBsize
maindefault branch
6 h agolast push
HTML 53.9% TypeScript 44.5% JavaScript 0.6% SQL 0.5%
4.5 KB · 102 lines tsx
Raw Blame History
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