);
}
// ── Derived: filter competitors client-side ───────────────────────────────────
function applyFilters(
data: ParcelAnalysis,
filters: FilterState,
): ParcelAnalysis["competitors"] {
// Guard: a 202 on-demand-fetch stub (#1001) or older backend may omit the
// array entirely — fall back to empty so we render an empty state, not throw.
let result = [...(data.competitors ?? [])];
// Radius filter — distance_m is in metres from the parcel centroid
result = result.filter((c) => c.distance_m <= filters.radiusKm * 1000);
// Note: the competitor type doesn't carry status/date fields yet (B6 extension).
// The chips are wired to state but can't filter until backend enriches data.
// They're kept in state so backend pass-through (Wave 4) can use them.
return result;
}
// ── Section 3 wrapper ─────────────────────────────────────────────────────────
export function Section3SettingsAndCompetitors({ cad, data }: Props) {
const [filters, setFilters] = useState({
radiusKm: 2,
onlyUnderConstruction: false,
minDeadline3mo: false,
maxAge6mo: false,
onlyApartments: false,
});
const [selectedCompetitor, setSelectedCompetitor] =
useState(null);
const filteredCompetitors = applyFilters(data, filters);
// Normalise once — a 202 stub / older backend may omit `competitors` (#1001).
const competitorCount = (data.competitors ?? []).length;
const districtName = data.district?.district_name ?? null;
return (
{/* Section headline bar */}
3. Продажи конкурентов
{competitorCount > 0
? `${filteredCompetitors.length} из ${competitorCount} объектов в радиусе ${filters.radiusKm} км`
: "Конкуренты не найдены в радиусе анализа"}
{/* Sub-sections */}
{/* Competitor table — moved before 3.2/3.3 for context */}
{filteredCompetitors.length > 0 && (
)}