← back to Stayclaim

src/app/map/page.tsx

60 lines

import type { Metadata } from 'next';
import { searchListings, getAllFilmingPins } from '@/lib/db';
import { BreadcrumbArchive } from '@/components/BreadcrumbArchive';
import { type MapPin } from '@/components/InteractiveMapMount';
import { MapWithLayers } from './MapWithLayers';

export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';

export const metadata: Metadata = {
  title: 'Map',
  description: 'Every public address in the archive on a single interactive map. Toggle the filming layer to see what was shot where.',
  alternates: { canonical: '/map' },
};

export default async function MapPage() {
  const [listings, filming] = await Promise.all([
    searchListings({ limit: 500 }),
    getAllFilmingPins(),
  ]);
  const archivePins: MapPin[] = listings
    .filter(l => l.latitude != null && l.longitude != null)
    .map(l => ({
      slug: l.slug,
      title: l.title,
      subtitle: l.city ?? undefined,
      lat: Number(l.latitude),
      lng: Number(l.longitude),
    }))
    .filter(p =>
      Number.isFinite(p.lat) &&
      Number.isFinite(p.lng) &&
      Math.abs(p.lat) <= 90 &&
      Math.abs(p.lng) <= 180 &&
      !(p.lat === 0 && p.lng === 0)
    );

  return (
    <>
      <div className="max-w-7xl mx-auto px-6 pt-6">
        <BreadcrumbArchive items={[{ label: 'Archive', href: '/' }, { label: 'Map' }]} />
      </div>

      <header className="max-w-7xl mx-auto px-6 py-8">
        <p className="text-xs uppercase tracking-[0.15em] text-ink/50 mb-2">Map</p>
        <h1 className="font-display text-5xl md:text-6xl text-ink tracking-[-0.02em] leading-[1.02]">
          Every address. Every shot.
        </h1>
        <p className="mt-3 font-mono text-[11px] text-ink/45">
          {archivePins.length} archive pins · {filming.length} filmed locations · click any pin to open its record
        </p>
      </header>

      <div className="max-w-7xl mx-auto px-6 pb-12">
        <MapWithLayers archivePins={archivePins} filmingPins={filming} />
      </div>
    </>
  );
}