← back to Stayclaim

src/app/page.tsx

102 lines

import { searchListings, getRecentPermits, yearOf } from '@/lib/db';
import { MapHero } from '@/components/MapHero';
import { Rail } from '@/components/Rail';
import { NodeCard } from '@/components/NodeCard';
import { FilmsGridServer } from '@/components/FilmsGridServer';
import { HeroCollage } from '@/components/HeroCollage';
import { StarsCtaRow } from '@/components/StarsCtaRow';
import { currentSurface } from '@/lib/site';

// Storytelling-tone copy — facts framed as scenes / chapters / pages, not as data.
const FILMS_HEADING: Record<'flagship' | 'claim' | 'community', { kicker: string; heading: string }> = {
  flagship:  { kicker: 'Open archive',           heading: 'Stories caught on film, near here' },
  claim:     { kicker: 'Filmed here',            heading: 'Scenes the cameras came for' },
  community: { kicker: 'Pages from the block',   heading: 'What the neighborhood has lived through' },
};

export default async function HomePage() {
  const [listings, permitEvents, surface] = await Promise.all([
    searchListings({ limit: 24 }),
    getRecentPermits(6),
    currentSurface(),
  ]);
  const filmCopy = FILMS_HEADING[surface.key] ?? FILMS_HEADING.flagship;

  const pins = listings
    .map(l => {
      const lat = Number(l.latitude);
      const lng = Number(l.longitude);
      return { l, lat, lng };
    })
    .filter(({ lat, lng }) => Number.isFinite(lat) && Number.isFinite(lng))
    .map(({ l, lat, lng }, i) => ({
      slug: l.slug,
      title: l.title,
      lat,
      lng,
      featured: i === 0,
    }));

  const recentlyResearched = listings.slice(0, 3);
  const recentPermits = permitEvents.slice(0, 3);
  const recentlyClaimed = listings.filter(l => l.claimed_by).slice(0, 3);

  return (
    <>
      <HeroCollage />
      <StarsCtaRow surface={surface.key} />
      <MapHero pins={pins} />

      <Rail label="Recently researched">
        {recentlyResearched.map(l => (
          <NodeCard
            key={l.id}
            kind="address"
            href={`/address/${l.slug}`}
            title={l.title}
            subtitle={l.city ? `${l.city}, ${l.state}` : undefined}
            imageUrl={l.hero_image ?? undefined}
            eyebrow={l.property_type ?? 'Address'}
          />
        ))}
      </Rail>

      <Rail label="This week in permits">
        {recentPermits.map(p => (
          <NodeCard
            key={`permit-${p.id}`}
            kind="address"
            href={`/address/${p.listing_slug}`}
            title={p.listing_title}
            subtitle={(() => { const s = p.summary ?? ''; return s.length > 80 ? `${s.slice(0, 80)}…` : s; })()}
            imageUrl={p.listing_hero ?? undefined}
            eyebrow={`Permit · ${yearOf(p.valid_from)}`}
          />
        ))}
      </Rail>

      {recentlyClaimed.length > 0 && (
        <Rail label="Recently claimed by owners">
          {recentlyClaimed.map(l => (
            <NodeCard
              key={`claim-${l.id}`}
              kind="address"
              href={`/address/${l.slug}`}
              title={l.title}
              subtitle="Claimed"
              imageUrl={l.hero_image ?? undefined}
              eyebrow="Owner-curated"
            />
          ))}
        </Rail>
      )}

      <FilmsGridServer
        heading={filmCopy.heading}
        kicker={filmCopy.kicker}
        limit={60}
      />
    </>
  );
}