← back to Homesonspec

apps/web/src/app/[state]/[city]/page.tsx

46 lines

import Link from "next/link";
import { notFound } from "next/navigation";
import { prisma } from "@homesonspec/database";
import { fmtPrice } from "@homesonspec/shared-ui";

export const dynamic = "force-dynamic";

/** Minimal city/metro SEO landing — full editorial treatment deferred. */
export default async function CityLandingPage({
  params,
}: {
  params: Promise<{ state: string; city: string }>;
}) {
  const { state, city } = await params;
  const stateUpper = state.toUpperCase();
  if (!/^[a-z]{2}$/i.test(state)) notFound();
  const cityName = decodeURIComponent(city).replace(/-/g, " ");

  const homes = await prisma.inventoryHome.findMany({
    where: { state: stateUpper, city: { equals: cityName, mode: "insensitive" }, status: "PUBLISHED", isDemo: false },
    include: { community: { select: { slug: true, name: true } }, builder: { select: { name: true } } },
    orderBy: { publishedAt: "desc" },
    take: 24,
  });
  if (homes.length === 0) notFound();

  return (
    <div className="mx-auto max-w-6xl px-4 py-8">
      <h1 className="text-3xl font-bold">
        New construction homes in {homes[0]!.city}, {stateUpper}
      </h1>
      <p className="mt-1 text-sm text-neutral-500">{homes.length} available demonstration homes</p>
      <div className="mt-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
        {homes.map((home) => (
          <Link key={home.id} href={`/homes/${home.id}`}
            className="rounded-xl border border-neutral-200 p-4 shadow-sm hover:border-teal-400">
            <div className="font-semibold">{fmtPrice(home.price === null ? null : Number(home.price))}</div>
            <div className="text-sm text-neutral-600">{home.street}</div>
            <div className="text-sm text-neutral-500">{home.community.name} · {home.builder.name}</div>
          </Link>
        ))}
      </div>
    </div>
  );
}