"use client"; import type { ExploreQuery, ExploreResponse } from "@dci/core"; import { CONFIDENCE_LEVELS, FACILITY_STATUSES, FACILITY_TYPES, GEO_PRECISIONS, PIPELINE_STATUSES, PROJECT_CLASSES } from "@dci/core"; import { SlidersHorizontal } from "lucide-react"; import { useRouter } from "next/navigation"; import { useState, type ReactNode } from "react"; import { Button } from "@/components/ui/button"; import { cn } from "@/components/ui/cn"; import { ToggleChip } from "@/components/ui/filter-chips"; import { SegmentedControl } from "@/components/ui/segmented"; import { Sheet } from "@/components/ui/sheet"; import { AI_FILTERS, countExploreFilters, exploreHref, toggleCsv } from "@/lib/explore-query"; import { fmtInt } from "@/lib/format"; import { CONFIDENCE_SHORT, PRECISION_SHORT, STATUS_LABEL, TYPE_LABEL } from "@/lib/labels"; const PROJECT_STATUSES = [...PIPELINE_STATUSES, "operational", "expansion", "cancelled"] as const; const CLASS_LABEL: Record = { NEW_BUILD: "New build", EXPANSION: "Expansion", CONSTRUCTION_START: "Construction start", PERMIT: "Permit", LAND_ACQUISITION: "Land acquisition", GRID_CONNECTION: "Grid connection", POWER_AGREEMENT: "Power agreement", FINANCING: "Financing", ACQUISITION: "Acquisition", PARTNERSHIP: "Partnership", CUSTOMER_AGREEMENT: "Customer agreement", EXECUTIVE_APPOINTMENT: "Executive appointment", SUSTAINABILITY: "Sustainability", PRODUCT_NEWS: "Product news", GENERAL_COMPANY_NEWS: "Company news", UNKNOWN: "Unknown", }; const AI_LABEL: Record<(typeof AI_FILTERS)[number], string> = { any: "Any", confirmed: "Confirmed", likely: "≥ Likely", associated: "≥ Associated" }; const inputCls = "h-10 w-full min-w-0 rounded-sm border border-hair-2 bg-surface px-2.5 text-[13px] text-ink outline-none focus:border-ink sm:h-9"; function Field({ label, hint, children }: { label: string; hint?: string; children: ReactNode }) { return ( ); } function Group({ legend, children }: { legend: string; children: ReactNode }) { return (
{legend} {children}
); } interface Props { query: ExploreQuery; facets: ExploreResponse["facets"] | null; } /** * Structured query builder (URL-as-state). Desktop: inline left column; mobile: a Filters button opening a sheet. * Chips apply immediately; text/number inputs apply on blur / Enter (and via the sheet's Apply). */ export function QueryBuilder({ query, facets }: Props) { return ( <>
); } function MobileFilters({ query, facets }: Props) { const [open, setOpen] = useState(false); const active = countExploreFilters(query); return (
setOpen(false)} title="Build a query" description="Every field maps to a URL parameter — the address bar is the saved view." heightVh={86}> setOpen(false)} />
); } function Form({ query, facets, onNavigate }: Props & { onNavigate?: () => void }) { const router = useRouter(); const isProjects = query.entity === "projects"; const [draft, setDraft] = useState(query); const [synced, setSynced] = useState(query); if (synced !== query) { setSynced(query); setDraft(query); } const go = (patch: Partial & Record) => { router.replace(exploreHref(query, { ...patch, page: undefined }), { scroll: false }); onNavigate?.(); }; const commit = () => go({ ...draft }); const csvOn = (key: keyof ExploreQuery, member: string) => ((draft[key] as string | undefined) ?? "").split(",").includes(member); const flip = (key: keyof ExploreQuery, member: string) => go({ [key]: toggleCsv(query[key] as string | undefined, member) }); const onKey = (e: React.KeyboardEvent) => { if (e.key === "Enter") { e.preventDefault(); commit(); } }; const setNum = (key: keyof ExploreQuery) => (e: React.ChangeEvent) => { const v = e.target.value; setDraft({ ...draft, [key]: v === "" ? undefined : Number(v) }); }; const statuses = isProjects ? PROJECT_STATUSES : FACILITY_STATUSES; const countryFacet = (facets?.country ?? []).slice(0, 12); const operatorFacet = (facets?.operator ?? []).slice(0, 8); return ( { e.preventDefault(); commit(); }} > { router.replace(exploreHref({ entity: v as ExploreQuery["entity"], view: query.view, q: query.q, country: query.country, operator: query.operator, metro: query.metro }), { scroll: false }); onNavigate?.(); }} options={[ { value: "facilities", label: "Facilities" }, { value: "projects", label: "Projects" }, ]} className="w-full [&>*]:flex-1" /> setDraft({ ...draft, q: e.target.value || undefined })} onBlur={commit} onKeyDown={onKey} placeholder={isProjects ? "Project, operator or city" : "Facility, operator or city"} className={inputCls} aria-label="Free text" />
{statuses.map((s) => ( flip("status", s)} className="h-9 text-[12px] sm:h-7"> {STATUS_LABEL[s]} ))}
setDraft({ ...draft, country: e.target.value.toUpperCase().replace(/[^A-Z,]/g, "") || undefined })} onBlur={commit} onKeyDown={onKey} placeholder="US,CA" className={cn(inputCls, "figure")} /> setDraft({ ...draft, metro: e.target.value.trim() || undefined })} onBlur={commit} onKeyDown={onKey} placeholder="northern-virginia" className={cn(inputCls, "figure")} />
{countryFacet.length > 0 && (
{countryFacet.map((c) => ( flip("country", c.key)} className="h-9 text-[12px] sm:h-7"> {c.name} {fmtInt(c.count)} ))}
)}
setDraft({ ...draft, operator: e.target.value.trim() || undefined })} onBlur={commit} onKeyDown={onKey} placeholder="equinix" className={cn(inputCls, "figure")} aria-label="Operator slug" /> {operatorFacet.length > 0 && (
{operatorFacet.map((o) => ( go({ operator: query.operator === o.key ? undefined : o.key })} className="h-9 text-[12px] sm:h-7"> {o.name} {fmtInt(o.count)} ))}
)}
{!isProjects && (
{FACILITY_TYPES.map((t) => ( flip("type", t)} className="h-9 text-[12px] sm:h-7"> {TYPE_LABEL[t]} ))}
)}
go({ has_mw: query.has_mw ? undefined : true })} className="h-9 text-[12px] sm:h-7"> Known MW only {!isProjects && ( go({ hyperscale: query.hyperscale ? undefined : true })} className="h-9 text-[12px] sm:h-7"> Hyperscale )}
go({ ai: v === "any" ? undefined : (v as ExploreQuery["ai"]) })} options={AI_FILTERS.map((a) => ({ value: a, label: AI_LABEL[a] }))} className="w-full [&>*]:flex-1" size="xs" />

Confirmed ⊂ likely ⊂ associated; “associated” alone is a tenant / customer mention, not AI infrastructure.

{isProjects ? ( <>
setDraft({ ...draft, announced_since: e.target.value || undefined })} onBlur={commit} className={cn(inputCls, "figure")} />
{PROJECT_CLASSES.map((c) => ( flip("project_class", c)} className="h-9 text-[12px] sm:h-7"> {CLASS_LABEL[c] ?? c} ))}
) : ( <>

Facilities without a published opening date never match a year range.

{GEO_PRECISIONS.map((p) => ( flip("location_precision", p)} className="h-9 text-[12px] sm:h-7"> {PRECISION_SHORT[p]} ))}
)}
{CONFIDENCE_LEVELS.map((c) => ( flip("confidence", c)} className="h-9 text-[12px] sm:h-7"> {CONFIDENCE_SHORT[c]} ))}
); }