← back to Stayclaim

src/components/AddressMasthead.tsx

65 lines

import type { Listing } from '@/lib/db';

/**
 * AddressMasthead — hero for address pages.
 * Right column is a LIVE Google Street View iframe of the actual property
 * when lat/lng are present. Falls back to nothing rather than to a generic
 * stock photo, so the page never lies about the building.
 */
export function AddressMasthead({ listing }: { listing: Listing }) {
  const yearsPill = listing.bedrooms ? `${listing.bedrooms} bd · ${listing.bathrooms ?? '—'} ba` : null;
  const origin = listing.property_type ?? 'Property';
  const lat = Number(listing.latitude);
  const lng = Number(listing.longitude);
  // Reject (0, 0) — common default for unresolved geocodes.
  const hasGeo = Number.isFinite(lat) && Number.isFinite(lng) && (lat !== 0 || lng !== 0);
  const svSrc = hasGeo
    ? `https://www.google.com/maps?q=&layer=c&cbll=${encodeURIComponent(lat.toFixed(6))},${encodeURIComponent(lng.toFixed(6))}&cbp=11,0,0,0,0&output=svembed`
    : null;
  const addrLine = [listing.address_line1, listing.city].filter(Boolean).join(' · ');
  const regionLine = [listing.state, listing.postal_code].filter(Boolean).join(' ');

  return (
    <header className="border-b border-ink/10">
      <div className="max-w-6xl mx-auto px-6 py-10 grid md:grid-cols-[1fr_minmax(auto,560px)] gap-8">
        <div>
          <p className="text-xs uppercase tracking-[0.15em] text-ink/50 mb-2">{origin}</p>
          <h1 className="font-display text-5xl md:text-6xl leading-[1.02] text-ink tracking-[-0.02em]">
            {listing.title}
          </h1>
          <address className="not-italic mt-3 text-base text-ink/70">
            {addrLine}
            {addrLine && regionLine ? ', ' : ''}
            {regionLine}
          </address>
          {listing.headline && (
            <p className="mt-5 font-display italic text-xl text-ink/80 max-w-prose">{listing.headline}</p>
          )}
          {yearsPill && (
            <span className="mt-5 inline-flex items-center gap-2 border border-ink/20 px-3 py-1 text-xs uppercase tracking-wider text-ink/60">
              {yearsPill} · sleeps {listing.sleeps ?? '—'}
            </span>
          )}
        </div>
        {svSrc && (
          <div className="relative aspect-[4/3] overflow-hidden border border-ink/10 bg-ink">
            <iframe
              title={`Live Google Street View of ${listing.title}`}
              src={svSrc}
              className="absolute inset-0 w-full h-full"
              style={{ border: 0, display: 'block' }}
              loading="lazy"
              referrerPolicy="no-referrer"
              sandbox="allow-scripts allow-same-origin allow-popups"
              allowFullScreen
            />
            <span className="absolute top-2 left-2 bg-ink/85 text-sand text-[10px] uppercase tracking-[0.15em] px-2 py-1 z-10">
              Live · Google Street View
            </span>
          </div>
        )}
      </div>
    </header>
  );
}