fix(sf-legacy): фильтр стейл competitors (>1 года Сданные → не конкурент)

User: 'плюс проверь какие данн чтобы было то что хочет макс хотя бы похожи
что не старше года иначе жк не конкурент'.

Анализ /analyze для 66:41:0204016:10:
  Total competitors: 20
  Строящиеся: 6
  Сданные: 14 (12 из них ready_dt >1y → стейл)

Maxim spec: ЖК старше года не конкурент. Активные = строящиеся
ИЛИ ready_dt в будущем ИЛИ сданы ≤1 года назад.

MarketTab фильтрует data.competitors в relevantCompetitors:
  - site_status === 'Строящиеся' → активен
  - ready_dt в будущем → активен
  - ready_dt в пределах последнего года → активен
  - иначе скрыт

activeCount + CompetitorTable теперь используют отфильтрованный список.
Section label показывает 'N из M — фильтр' для прозрачности.

После deploy для тестового cad: activeCount упадёт с 20 → 9
(6 строящихся + 1 future ≤1y + 2 past ≤1y).
This commit is contained in:
lekss361 2026-05-18 07:29:26 +03:00
parent b605f213c9
commit 12030c4e76

View file

@ -56,9 +56,21 @@ export function MarketTab({ data }: Props) {
data.competitors.length > 0;
// ── Above-the-fold values ────────────────────────────────────────────────
// Note: site_status field pending fix #2/#3 (backend PR). Using total
// competitors count as proxy for active (строящихся) count for now.
const activeCount = data.competitors.length;
// Maxim's spec: «ЖК старше года → не конкурент». Filter active competitors:
// - site_status === 'Строящиеся' → активен
// - либо ready_dt в будущем → активен (готовность ещё не наступила)
// - либо ready_dt в пределах последнего года → активен (свежие продажи)
// - иначе (Сданные >1y назад) → не конкурент, скрыт
const REL_MS = 365 * 24 * 60 * 60 * 1000;
const yearAgoTs = Date.now() - REL_MS;
const relevantCompetitors = data.competitors.filter((c) => {
if (c.site_status === "Строящиеся") return true;
if (!c.ready_dt) return false;
const ts = new Date(c.ready_dt).getTime();
if (Number.isNaN(ts)) return false;
return ts >= yearAgoTs;
});
const activeCount = relevantCompetitors.length;
const radiusKm = getRadiusKm(data);
// Treat zero velocity as "no data" — backend returns 0 when competitors
// are unmapped to Objective ground truth (OBJ-3). Showing "0.0 м²/мес"
@ -241,11 +253,15 @@ export function MarketTab({ data }: Props) {
{/* ── Main content blocks ───────────────────────────────────────────── */}
{/* Competitors */}
{data.competitors.length > 0 && (
{relevantCompetitors.length > 0 && (
<div>
<SectionLabel style={{ marginBottom: 12 }}>Конкуренты</SectionLabel>
<SectionLabel style={{ marginBottom: 12 }}>
Конкуренты ({relevantCompetitors.length} из{" "}
{data.competitors.length}
{" — фильтр: строящиеся или сданы ≤1 года)"}
</SectionLabel>
<CompetitorTable
competitors={data.competitors}
competitors={relevantCompetitors}
districtName={data.district?.district_name}
/>
</div>