spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
1import type { Metadata } from "next";2import { Suspense } from "react";3import { Map as MapIcon } from "lucide-react";4import { FacilityFilterBar } from "@/components/facility-filters";5import { FacilityTable } from "@/components/facility-table";6import { Button } from "@/components/ui/button";7import { Page, PageHeader } from "@/components/ui/card";8import { Pagination } from "@/components/ui/pagination";9import { OfflineNotice } from "@/components/ui/states";10import { api } from "@/lib/api";11import { fmtInt } from "@/lib/format";12import { filtersToQuery, parseFilters } from "@/lib/query";13import { routes } from "@/lib/routes";1415export const revalidate = 120;1617export const metadata: Metadata = {18 title: "Data centers",19 description: "Filterable index of data center facilities worldwide: operator, market, country, status, capacity, type and confidence.",20 alternates: { canonical: "/datacenters" },21};2223const PER_PAGE = 50;2425export default async function DatacentersPage({ searchParams }: { searchParams: Promise<Record<string, string | string[] | undefined>> }) {26 const sp = await searchParams;27 const filters = parseFilters(sp);28 const page = filters.page ?? 1;29 const query = { ...filters, page, per_page: filters.per_page ?? PER_PAGE, sort: filters.sort ?? "mw", order: filters.order ?? (filters.sort === "name" ? "asc" : "desc") };30 const res = await api.facilities(query);31 const hrefFor = (p: number) => routes.datacenters(filtersToQuery({ ...filters, page: p }));32 const mapQs = filtersToQuery({ ...filters, page: undefined, per_page: undefined, sort: undefined, order: undefined });3334 return (35 <Page>36 <PageHeader37 eyebrow="Index"38 title="Data centers"39 description={res.ok ? `${fmtInt(res.total)} facilities indexed. Figures are sourced; capacity shows the best known figure (IT, total or ≈ planned).` : "Every indexed facility with operator, market, status, capacity and confidence."}40 aside={41 <Button href={routes.map(mapQs)} size="sm">42 <MapIcon className="size-4" strokeWidth={1.75} /> Open in map43 </Button>44 }45 />46 {!res.ok && <OfflineNotice detail={res.error} className="mb-3" />}47 <div className="sticky top-12 z-[20] -mx-3 border-b border-hair bg-paper/95 px-3 py-2 backdrop-blur sm:top-14 sm:mx-0 sm:px-0">48 <Suspense>49 <FacilityFilterBar basePath={routes.datacenters()} total={res.ok ? res.total : null} />50 </Suspense>51 </div>52 <div className="pt-1">53 <FacilityTable items={res.items} filters={query} basePath={routes.datacenters()} emptyTitle={res.ok ? "No facilities match these filters" : "Facilities unavailable"} emptyDescription={res.ok ? "Loosen a filter or clear them all." : "The index API is not reachable right now."} />54 </div>55 <Pagination page={page} perPage={query.per_page} total={res.total} hrefFor={hrefFor} label="facilities" />56 </Page>57 );58}59