SPB Git forge
3commits 1branches 0releases
417.0 KBsize
maindefault branch
10 days agolast push
TypeScript 66.5% Python 30.9% JavaScript 1.4% CSS 0.7%
4.8 KB · 92 lines tsx
Raw Blame History
1import type { Metadata } from 'next';2import Link from 'next/link';3import { EXAMPLE_QUERIES, GroupedResults, Shortcuts } from '@/components/search/results';4import { SearchForm } from '@/components/search/search-form';5import { Container, PageHeader } from '@/components/ui/section';6import { Unavailable } from '@/components/ui/unavailable';7import { api, safe } from '@/lib/api';8import { fmtInt } from '@/lib/format';9import { routes, SITE_URL } from '@/lib/site';1011export const dynamic = 'force-dynamic';1213type SP = Promise<Record<string, string | string[] | undefined>>;1415function readQ(sp: Record<string, string | string[] | undefined>): string {16  const raw = Array.isArray(sp.q) ? sp.q[0] : sp.q;17  return (raw ?? '').trim().slice(0, 120);18}1920export async function generateMetadata({ searchParams }: { searchParams: SP }): Promise<Metadata> {21  const q = readQ(await searchParams);22  const title = q ? `Search results for “${q}”` : 'Search satellites, operators, constellations and launches';23  return {24    title,25    description: q ? `SatelliteIndex search results for “${q}”: satellites, constellations, operators, countries, launches and launch sites.` : 'Search the SatelliteIndex catalogue by satellite name, NORAD or COSPAR identifier, operator, constellation, country or launch.',26    alternates: { canonical: q ? routes.search(q) : '/search' },27    robots: q ? { index: false, follow: true } : { index: true, follow: true },28    openGraph: { title, url: `${SITE_URL}${routes.search(q || undefined)}`, type: 'website' },29  };30}3132export default async function SearchPage({ searchParams }: { searchParams: SP }) {33  const q = readQ(await searchParams);34  const res = q ? await safe(api.search(q, 50)) : null;35  const payload = res?.data ?? null;36  const failed = Boolean(q) && res === null;3738  return (39    <Container>40      <PageHeader eyebrow="Search" title={q ? <>Results for <span className="text-accent">“{q}”</span></> : 'Search the index'} lede={q ? undefined : 'Satellites by name, NORAD or COSPAR identifier; constellations, operators, countries, launches and launch sites. Press ⌘K anywhere for the quick search.'} />41      <SearchForm q={q} className="max-w-2xl" autoFocus={!q} />4243      <div className="py-8 md:py-10">44        {!q ? (45          <div>46            <p className="eyebrow mb-3">Try</p>47            <ul className="flex flex-wrap gap-2">48              {EXAMPLE_QUERIES.map((ex) => (49                <li key={ex}>50                  <Link href={routes.search(ex)} className="inline-flex min-h-[40px] items-center rounded-full border border-rule bg-plane-2 px-3 text-sm text-ink-2 hover:border-rule-strong hover:text-ink">51                    {ex}52                  </Link>53                </li>54              ))}55            </ul>56            <p className="mt-6 max-w-xl text-sm leading-relaxed text-ink-3">57              Launch vehicles are not indexed yet — a query such as “Falcon 9” only matches objects whose catalogue name contains those words. Browse the{' '}58              <Link href={routes.launches()} className="link">launch log</Link> or <Link href={routes.satellites()} className="link">filter the catalogue</Link> instead.59            </p>60          </div>61        ) : failed ? (62          <Unavailable what="Search" />63        ) : payload ? (64          <>65            <Shortcuts items={payload.shortcuts} />66            {payload.results.length === 0 ? (67              <div className="rounded-lg border border-dashed border-rule-strong px-5 py-10 text-center">68                <p className="text-base text-ink">No results for “{q}”.</p>69                <p className="mx-auto mt-2 max-w-md text-sm leading-relaxed text-ink-3">70                  The index covers satellite names, NORAD and COSPAR identifiers, constellations, operators, countries, launches and launch sites. Launch vehicles (e.g. “Falcon 9”) are not indexed yet.71                </p>72                <div className="mt-5 flex flex-wrap justify-center gap-2">73                  <Link href={routes.satellites(`q=${encodeURIComponent(q)}`)} className="inline-flex min-h-[44px] items-center rounded-md border border-rule-strong px-4 text-sm text-ink hover:bg-plane-2">Filter the catalogue for “{q}”</Link>74                  <Link href={routes.explore()} className="inline-flex min-h-[44px] items-center rounded-md border border-rule px-4 text-sm text-ink-2 hover:bg-plane-2">Open the live globe</Link>75                </div>76              </div>77            ) : (78              <>79                <p className="tnum mb-6 text-xs text-ink-3">80                  {fmtInt(payload.results.length)} result{payload.results.length === 1 ? '' : 's'}81                  {payload.results.length >= 50 && ' (top 50 by relevance)'}82                </p>83                <GroupedResults results={payload.results} />84              </>85            )}86          </>87        ) : null}88      </div>89    </Container>90  );91}92