import Link from "next/link"; import type { Metadata } from "next"; import { Badge, Chip, Empty, Flag, PageHeader, Panel, Table, Td, TierBadge } from "@/components/ui"; import { api } from "@/lib/api"; import { fmtInt, relTime } from "@/lib/format"; export const dynamic = "force-dynamic"; export const metadata: Metadata = { title: "Sources", description: "Every organization monitored by WebSensor, with its sensors and recent activity. Filter by country, tier, category and provenance." }; const CATS = ["ai", "cloud", "developer", "cyber", "consumer-tech", "semiconductors", "finance", "government", "statistics", "health", "pharma", "science", "space", "automotive", "commerce", "payments", "crypto", "enterprise", "internet", "standards", "news", "media", "sports", "transport", "energy"]; const TIERS = ["S", "A", "B", "C", "D"]; type Params = { q?: string; category?: string; country?: string; tier?: string; first_party?: string }; function href(p: Params, patch: Partial): string { const n: Record = { ...p, ...patch }; const sp = new URLSearchParams(); for (const k of ["q", "category", "country", "tier", "first_party"]) if (n[k]) sp.set(k, n[k]!); const s = sp.toString(); return s ? `/sources?${s}` : "/sources"; } export default async function SourcesPage({ searchParams }: { searchParams: Promise }) { const raw = await searchParams; const sp: Params = { q: raw.q?.trim() || undefined, category: raw.category || undefined, country: raw.country?.toUpperCase() || undefined, tier: TIERS.includes((raw.tier ?? "").toUpperCase()) ? raw.tier!.toUpperCase() : undefined, first_party: raw.first_party === "true" || raw.first_party === "false" ? raw.first_party : undefined }; const [{ items }, countries] = await Promise.all([api.sources({ q: sp.q, category: sp.category, country: sp.country, tier: sp.tier, first_party: sp.first_party }), api.countries()]); const active = [sp.q, sp.category, sp.country, sp.tier, sp.first_party].filter(Boolean).length; const firstParty = items.filter((s) => s.first_party !== false).length; return ( <>
{sp.category && } {sp.tier && } {sp.first_party && } {active > 0 && clear {active} filter{active === 1 ? "" : "s"}}
tier all {TIERS.map((t) => ( {t} ))} · all kinds first-party media / external
category all {CATS.map((c) => ( {c} ))} {sp.category && !CATS.includes(sp.category) && {sp.category}}
{items.length === 0 ? ( No source matches these filters. ) : ( {items.map((s) => ( ))}
{s.name} {s.domain} {s.country ? {s.country} : —} {s.first_party === false ? : }
{s.categories.slice(0, 3).map((c) => {c})}{s.categories.length > 3 && +{s.categories.length - 3}}
{s.sensor_count ?? 0} {fmtInt(s.events_24h ?? 0)} {fmtInt(s.event_count)} {s.last_event_at ? relTime(s.last_event_at) : "—"} {(s.sensors_degraded ?? 0) > 0 ? {s.sensors_degraded} DEGRADED : UP}
)}
); }