"use client";
import { useState } from "react";
import {
BarChart3,
Building2,
Check,
ChevronDown,
ChevronUp,
Database,
MapPin,
Minus,
RefreshCw,
} from "lucide-react";
import { UserMenu } from "@/components/auth/UserMenu";
import { PilotRequestModal } from "@/components/landing/PilotRequestModal";
import { TopNav } from "@/components/landing/TopNav";
import { HeadlineBar } from "@/components/ui/HeadlineBar";
import { useLandingStats } from "@/lib/api/landing";
// ── FAQ data ───────────────────────────────────────────────────────────────
const FAQ: { q: string; a: string }[] = [
{
q: "Откуда берутся данные?",
a: "Три источника: Росреестр (ДДУ-сделки, >7 млн записей), DOM.РФ (портфель новостроек, ПЗЗ), Objective (цены предложения). Обновление еженедельное для DOM.РФ и цен, ежеквартальное для Росреестра.",
},
{
q: "Насколько точны цены?",
a: "Цены предложения актуальны на дату последнего обновления. Цена сделки из ДДУ — реальная стоимость на момент регистрации в Росреестре. Расхождение с рыночной ценой в пике может составлять 5–15%.",
},
{
q: "Какие районы и регионы охвачены?",
a: "Сейчас — Екатеринбург и Свердловская область (ПЗЗ ЕКБ, МСК-66). Расширение на другие регионы УрФО в роудмапе.",
},
{
q: "Что входит в пилотный доступ?",
a: "Полный доступ к Site Finder (анализ участков по кадастровому номеру), аналитике рынка Свердловской области и рекомендатору квартирографии. Срок пилота — 30 дней. Поддержка по email.",
},
{
q: "Как устроен маппинг Objective → DOM.РФ?",
a: "Объекты Objective сопоставляются с портфелем DOM.РФ по нечёткому совпадению названия и геокоординатам. Текущее покрытие — около 11% (один DOM.РФ-объект может объединять несколько Objective-лотов).",
},
];
// ── GenDesign vs НСПД — value-prop differentiation (#100) ────────────────────
// НСПД (nspd.gov.ru) — бесплатная госкарта пространственных данных. GenDesign
// не заменяет её, а считает поверх: рынок, прогноз, инвест-вердикт. Таблица
// объясняет, за что девелопер платит сверх бесплатного источника.
interface ComparisonRow {
feature: string;
/** null = нет совсем; string = есть, но в каком виде. */
nspd: string | null;
gendesign: string;
}
const COMPARISON_ROWS: ComparisonRow[] = [
{
feature: "Кадастр, ПЗЗ, ЗОУИТ, границы участка",
nspd: "Карта и атрибуты",
gendesign: "То же + сверка одним кликом",
},
{
feature: "Цены сделок ДДУ (Росреестр)",
nspd: null,
gendesign: "Медиана по району и классу",
},
{
feature: "Остатки и скорость продаж новостроек",
nspd: null,
gendesign: "DOM.РФ + Objective, еженедельно",
},
{
feature: "POI-скор участка и объяснение",
nspd: null,
gendesign: "POI-скор 0–40 с разбором факторов",
},
{
feature: "Прогноз цены и горизонты выхода",
nspd: null,
gendesign: "Прогноз с доверительным интервалом",
},
{
feature: "Рекомендация квартирографии",
nspd: null,
gendesign: "Mix планировок под спрос района",
},
{
feature: "Экспорт в PDF / Excel / DXF",
nspd: null,
gendesign: "Отчёт по участку в один клик",
},
];
// ── Sub-components ─────────────────────────────────────────────────────────
function ComparisonCell({ value }: { value: string | null }) {
if (value === null) {
return (
нет
);
}
return (
{value}
);
}
function FaqItem({ q, a }: { q: string; a: string }) {
const [open, setOpen] = useState(false);
return (
{open ? (
{a}
) : null}
);
}
// ── KPI formatting ─────────────────────────────────────────────────────────
function formatNumber(n: number | undefined, decimals = 0): string {
if (n === undefined) return "—";
return n.toLocaleString("ru", {
minimumFractionDigits: decimals,
maximumFractionDigits: decimals,
});
}
/** Skeleton placeholder shown when stale=true (no fake data) */
function KpiSkeleton() {
return (
);
}
// ── Main component ─────────────────────────────────────────────────────────
export default function HomePage() {
const [modalOpen, setModalOpen] = useState(false);
const { data: stats, isLoading } = useLandingStats();
const isStale = stats?.stale === true;
const showSkeleton = isLoading || isStale;
return (
{/* ── Nav ────────────────────────────────────────────────────────── */}
{/* UserMenu — личный кабинет (avatar + dropdown) для залогиненного юзера.
В dev (401) или до загрузки /me — UserMenu сам рендерит null. */}
} />
{/* ── Hero ───────────────────────────────────────────────────────── */}
Цифры рынка перед фундаментом
Аналитика новостроек Свердловской области — Росреестр, DOM.РФ,
Objective — в одном инструменте для девелоперов.
DOM.РФ фиксирует строящиеся ЖК, но цены предложения Objective
покрывают лишь часть из них. Из тех, где цены есть, публично доступны
единицы — остальное требует прямого запроса или данных, агрегированных
GenDesign.
{/* ── GenDesign vs НСПД (#100) ───────────────────────────────────── */}
GenDesign и НСПД
НСПД (nspd.gov.ru) — бесплатная государственная карта: кадастр, ПЗЗ,
границы. GenDesign не заменяет её, а считает поверх — добавляет рынок,
прогноз и инвест-вердикт. Любую цифру можно сверить с первоисточником
из карточки участка.
{/* Header row */}
Возможность
НСПД (бесплатно)
GenDesign
{/* Data rows */}
{COMPARISON_ROWS.map((row, i) => (
{[
"Site Finder — анализ участков по кадастру",
"Аналитика рынка Свердловской области",
"Рекомендатор квартирографии",
"Данные DOM.РФ, Росреестр, Objective",
"Email-поддержка в рабочие дни",
].map((item) => (