Some checks failed
Co-authored-by: bot-backend <bot-backend@gendsgn.local> Co-committed-by: bot-backend <bot-backend@gendsgn.local>
413 lines
12 KiB
TypeScript
413 lines
12 KiB
TypeScript
// #801: статичная фикстура результата оценки для preview-маршрута (a11y/lighthouse).
|
||
// Полностью оффлайн — никакой сети. Значения правдоподобны (ЕКБ, 2-к вторичка),
|
||
// заполнены ВСЕ surface'ы «денежного экрана»: asking + expected-sold + Avito IMV +
|
||
// ДКП-коридор + cian valuation + price_trend + аналоги/сделки.
|
||
// photo_url=null у всех лотов — намеренно, чтобы не тянуть внешние картинки
|
||
// (чистый оффлайн-рендер для lighthouse/axe).
|
||
|
||
import type {
|
||
AggregatedEstimate,
|
||
AnalogLot,
|
||
HouseAnalyticsResponse,
|
||
HouseInfoForEstimate,
|
||
IMVBenchmarkResponse,
|
||
PlacementHistoryItem,
|
||
SalesVsListingsResponse,
|
||
SellTimeSensitivityResponse,
|
||
TradeInEstimateInput,
|
||
} from "@/types/trade-in";
|
||
|
||
const analogs: AnalogLot[] = [
|
||
{
|
||
address: "ул. Репина, 73",
|
||
area_m2: 54,
|
||
rooms: 2,
|
||
floor: 7,
|
||
total_floors: 16,
|
||
price_rub: 9_700_000,
|
||
price_per_m2: 179_629,
|
||
listing_date: "2026-05-12",
|
||
days_on_market: 18,
|
||
photo_url: null,
|
||
source: "avito",
|
||
source_url: "https://www.avito.ru/ekaterinburg/kvartiry/preview-1",
|
||
distance_m: 120,
|
||
tier: null,
|
||
lat: 56.8401,
|
||
lon: 60.5702,
|
||
},
|
||
{
|
||
address: "ул. Викулова, 33",
|
||
area_m2: 57,
|
||
rooms: 2,
|
||
floor: 4,
|
||
total_floors: 10,
|
||
price_rub: 9_950_000,
|
||
price_per_m2: 174_561,
|
||
listing_date: "2026-05-20",
|
||
days_on_market: 10,
|
||
photo_url: null,
|
||
source: "cian",
|
||
source_url: "https://www.cian.ru/sale/flat/preview-2",
|
||
distance_m: 340,
|
||
tier: null,
|
||
lat: 56.8389,
|
||
lon: 60.5681,
|
||
},
|
||
{
|
||
address: "ул. Кирова, 28",
|
||
area_m2: 53,
|
||
rooms: 2,
|
||
floor: 9,
|
||
total_floors: 12,
|
||
price_rub: 9_400_000,
|
||
price_per_m2: 177_358,
|
||
listing_date: "2026-05-04",
|
||
days_on_market: 31,
|
||
photo_url: null,
|
||
source: "avito",
|
||
source_url: "https://www.avito.ru/ekaterinburg/kvartiry/preview-3",
|
||
distance_m: 510,
|
||
tier: null,
|
||
lat: 56.8372,
|
||
lon: 60.5749,
|
||
},
|
||
];
|
||
|
||
const actualDeals: AnalogLot[] = [
|
||
{
|
||
address: "ул. Репина",
|
||
area_m2: 55,
|
||
rooms: 2,
|
||
floor: null,
|
||
total_floors: null,
|
||
price_rub: 8_800_000,
|
||
price_per_m2: 160_000,
|
||
listing_date: "2026-01-01",
|
||
days_on_market: null,
|
||
photo_url: null,
|
||
source: "rosreestr",
|
||
source_url: null,
|
||
distance_m: null,
|
||
tier: "T1_per_street",
|
||
lat: null,
|
||
lon: null,
|
||
},
|
||
{
|
||
address: "ул. Викулова",
|
||
area_m2: 58,
|
||
rooms: 2,
|
||
floor: null,
|
||
total_floors: null,
|
||
price_rub: 9_280_000,
|
||
price_per_m2: 160_000,
|
||
listing_date: "2025-10-01",
|
||
days_on_market: null,
|
||
photo_url: null,
|
||
source: "rosreestr",
|
||
source_url: null,
|
||
distance_m: null,
|
||
tier: "T1_per_street",
|
||
lat: null,
|
||
lon: null,
|
||
},
|
||
];
|
||
|
||
export const FIXTURE_ESTIMATE: AggregatedEstimate = {
|
||
estimate_id: "preview-0000-0000-0000-000000000000",
|
||
median_price_rub: 9_850_000,
|
||
range_low_rub: 9_100_000,
|
||
range_high_rub: 10_600_000,
|
||
median_price_per_m2: 178_000,
|
||
expected_sold_price_rub: 8_900_000,
|
||
expected_sold_range_low_rub: 8_300_000,
|
||
expected_sold_range_high_rub: 9_500_000,
|
||
expected_sold_per_m2: 160_800,
|
||
asking_to_sold_ratio: 0.9,
|
||
ratio_basis: "per_rooms",
|
||
confidence: "high",
|
||
confidence_explanation: "12 аналогов в радиусе 800 м, разброс цен ±9%.",
|
||
n_analogs: 12,
|
||
insufficient_data: false,
|
||
period_months: 24,
|
||
analogs,
|
||
actual_deals: actualDeals,
|
||
expires_at: "2026-06-30T00:00:00Z",
|
||
target_address: "Екатеринбург, ул. Репина, 75/2",
|
||
target_lat: 56.84,
|
||
target_lon: 60.57,
|
||
sources_used: ["avito", "cian", "rosreestr"],
|
||
data_freshness_minutes: 35,
|
||
last_scraped_at: "2026-05-30T12:00:00Z",
|
||
est_days_on_market: 48,
|
||
address_precision: "house",
|
||
area_m2: 55.3,
|
||
rooms: 2,
|
||
floor: 5,
|
||
total_floors: 11,
|
||
year_built: 2018,
|
||
house_type: "monolith",
|
||
repair_state: "good",
|
||
has_balcony: true,
|
||
cian_valuation: {
|
||
sale_price_rub: 9_700_000,
|
||
rent_price_rub: 42_000,
|
||
chart: [
|
||
{ date: "2025-11", price: 9_300_000 },
|
||
{ date: "2025-12", price: 9_420_000 },
|
||
{ date: "2026-01", price: 9_510_000 },
|
||
{ date: "2026-02", price: 9_560_000 },
|
||
{ date: "2026-03", price: 9_640_000 },
|
||
{ date: "2026-04", price: 9_700_000 },
|
||
],
|
||
chart_change_pct: 3.2,
|
||
chart_change_direction: "increase",
|
||
},
|
||
avito_imv: {
|
||
recommended_price: 10_200_000,
|
||
lower_price: 9_400_000,
|
||
higher_price: 11_000_000,
|
||
market_count: 7,
|
||
},
|
||
dkp_corridor: {
|
||
count: 9,
|
||
low_ppm2: 150_000,
|
||
median_ppm2: 162_000,
|
||
high_ppm2: 178_000,
|
||
period_months: 24,
|
||
},
|
||
price_trend: [
|
||
{ month: "2025-11", ppm2: 168_000 },
|
||
{ month: "2025-12", ppm2: 170_500 },
|
||
{ month: "2026-01", ppm2: 172_000 },
|
||
{ month: "2026-02", ppm2: 174_000 },
|
||
{ month: "2026-03", ppm2: 176_500 },
|
||
{ month: "2026-04", ppm2: 178_000 },
|
||
],
|
||
};
|
||
|
||
export const FIXTURE_INPUT: TradeInEstimateInput = {
|
||
address: "Екатеринбург, ул. Репина, 75/2",
|
||
area_m2: 55.3,
|
||
rooms: 2,
|
||
floor: 5,
|
||
total_floors: 11,
|
||
year_built: 2018,
|
||
house_type: "monolith",
|
||
repair_state: "good",
|
||
has_balcony: true,
|
||
};
|
||
|
||
// ── IMV Benchmark fixture ─────────────────────────────────────────────────────
|
||
// available:true обязательно — иначе IMVBenchmark возвращает null.
|
||
export const FIXTURE_IMV: IMVBenchmarkResponse = {
|
||
available: true,
|
||
cache_key: "ekb:preview-house:2k",
|
||
recommended_price: 10_200_000,
|
||
lower_price: 9_400_000,
|
||
higher_price: 11_000_000,
|
||
market_count: 7,
|
||
fetched_at: "2026-05-30T12:00:00Z",
|
||
our_median_price: 9_850_000,
|
||
diff_pct: -3.4,
|
||
};
|
||
|
||
// ── HouseInfo fixture ─────────────────────────────────────────────────────────
|
||
// houses.length > 0 обязательно — иначе HouseInfoCard возвращает null.
|
||
export const FIXTURE_HOUSES: HouseInfoForEstimate[] = [
|
||
{
|
||
house_id: 42001,
|
||
ext_house_id: "ekb-repin-75",
|
||
address: "Екатеринбург, ул. Репина, 75",
|
||
short_address: "Репина, 75",
|
||
lat: 56.84,
|
||
lon: 60.57,
|
||
year_built: 2018,
|
||
total_floors: 11,
|
||
house_type: "monolith",
|
||
passenger_elevators: 2,
|
||
cargo_elevators: 1,
|
||
has_concierge: false,
|
||
closed_yard: true,
|
||
has_playground: true,
|
||
parking_type: "подземная",
|
||
developer_name: "Атомстройкомплекс",
|
||
rating: 4.3,
|
||
reviews_count: 28,
|
||
raw_characteristics: [],
|
||
},
|
||
];
|
||
|
||
// ── PlacementHistory fixture ──────────────────────────────────────────────────
|
||
// items.length > 0 обязательно — иначе PlacementHistoryCard возвращает null.
|
||
export const FIXTURE_PLACEMENT: PlacementHistoryItem[] = [
|
||
{
|
||
id: 1001,
|
||
source: "avito",
|
||
house_id: 42001,
|
||
ext_item_id: "avito-preview-1001",
|
||
title: "2к, 54 м², 7/16 эт.",
|
||
rooms: 2,
|
||
area_m2: 54,
|
||
floor: 7,
|
||
total_floors: 16,
|
||
start_price: 10_200_000,
|
||
start_price_date: "2025-11-01",
|
||
last_price: 9_700_000,
|
||
last_price_date: "2026-03-15",
|
||
removed_date: "2026-04-10",
|
||
exposure_days: 160,
|
||
notes: null,
|
||
},
|
||
{
|
||
id: 1002,
|
||
source: "cian",
|
||
house_id: 42001,
|
||
ext_item_id: "cian-preview-1002",
|
||
title: "2к, 57 м², 4/10 эт.",
|
||
rooms: 2,
|
||
area_m2: 57,
|
||
floor: 4,
|
||
total_floors: 10,
|
||
start_price: 9_800_000,
|
||
start_price_date: "2025-09-10",
|
||
last_price: 9_500_000,
|
||
last_price_date: "2025-12-20",
|
||
removed_date: "2026-01-05",
|
||
exposure_days: 117,
|
||
notes: null,
|
||
},
|
||
{
|
||
id: 1003,
|
||
source: "avito",
|
||
house_id: 42001,
|
||
ext_item_id: "avito-preview-1003",
|
||
title: "2к, 55 м², 5/11 эт.",
|
||
rooms: 2,
|
||
area_m2: 55,
|
||
floor: 5,
|
||
total_floors: 11,
|
||
start_price: 9_500_000,
|
||
start_price_date: "2025-06-01",
|
||
last_price: 9_100_000,
|
||
last_price_date: "2025-08-30",
|
||
removed_date: "2025-09-05",
|
||
exposure_days: 96,
|
||
notes: null,
|
||
},
|
||
];
|
||
|
||
// ── HouseAnalytics fixture ────────────────────────────────────────────────────
|
||
// kpi.total_lots > 0 обязательно — иначе HouseAnalyticsSection возвращает null.
|
||
// price_history >= 2 точки — для рендера PriceHistoryChart.
|
||
// recent_sold > 0 — для рендера RecentSoldList.
|
||
export const FIXTURE_ANALYTICS: HouseAnalyticsResponse = {
|
||
house_ids: [42001],
|
||
radius_m: 0,
|
||
kpi: {
|
||
total_lots: 38,
|
||
sold_count: 24,
|
||
sold_rate_pct: 63.2,
|
||
median_exposure_days: 112,
|
||
median_bargain_pct: 4.8,
|
||
},
|
||
price_history: [
|
||
{ year: 2022, source: "avito_imv", median_price_per_m2: 155_000, n_lots: 6, median_price_rub: 8_525_000 },
|
||
{ year: 2023, source: "avito_imv", median_price_per_m2: 161_000, n_lots: 9, median_price_rub: 8_855_000 },
|
||
{ year: 2024, source: "avito_imv", median_price_per_m2: 170_000, n_lots: 12, median_price_rub: 9_350_000 },
|
||
{ year: 2025, source: "avito_imv", median_price_per_m2: 176_000, n_lots: 11, median_price_rub: 9_680_000 },
|
||
],
|
||
recent_sold: [
|
||
{
|
||
id: 2001,
|
||
source: "avito_imv",
|
||
rooms: 2,
|
||
area_m2: 54,
|
||
floor: 7,
|
||
start_price: 10_200_000,
|
||
last_price: 9_700_000,
|
||
removed_date: "2026-04-10",
|
||
exposure_days: 160,
|
||
discount_pct: 4.9,
|
||
},
|
||
{
|
||
id: 2002,
|
||
source: "avito_imv",
|
||
rooms: 2,
|
||
area_m2: 57,
|
||
floor: 4,
|
||
start_price: 9_800_000,
|
||
last_price: 9_500_000,
|
||
removed_date: "2026-01-05",
|
||
exposure_days: 117,
|
||
discount_pct: 3.1,
|
||
},
|
||
],
|
||
};
|
||
|
||
// ── SellTimeSensitivity fixture ───────────────────────────────────────────────
|
||
export const FIXTURE_SELLTIME: SellTimeSensitivityResponse = {
|
||
house_ids: [42001],
|
||
radius_m: 0,
|
||
target_median_price_per_m2: 178_000,
|
||
buckets: [
|
||
{ price_premium_label: "cheap", price_premium_pct: -5, median_exposure_days: 38, p25_days: 21, p75_days: 55, n_lots: 8 },
|
||
{ price_premium_label: "median", price_premium_pct: 0, median_exposure_days: 112, p25_days: 60, p75_days: 160, n_lots: 14 },
|
||
{ price_premium_label: "plus5", price_premium_pct: 5, median_exposure_days: 185, p25_days: 90, p75_days: 240, n_lots: 10 },
|
||
{ price_premium_label: "plus10", price_premium_pct: 10, median_exposure_days: 270, p25_days: 150, p75_days: 360, n_lots: 6 },
|
||
],
|
||
};
|
||
|
||
// Секция 12: StreetDealsCard — useSalesVsListings(address, area_m2, rooms).
|
||
// Guard: street != null И pairs.length > 0 — иначе return null.
|
||
export const FIXTURE_SALES: SalesVsListingsResponse = {
|
||
street: "Репина",
|
||
period_months: 24,
|
||
window_days: 180,
|
||
area_tolerance: 0.15,
|
||
total_deals: 9,
|
||
deals_with_listings: 5,
|
||
linkage_rate_pct: 55.6,
|
||
median_discount_pct: -6.2,
|
||
data_quality: "house_linked",
|
||
pairs: [
|
||
{
|
||
deal_id: 9001,
|
||
deal_date: "2026-04-18",
|
||
deal_price_rub: 8_900_000,
|
||
deal_price_per_m2: 161_818,
|
||
deal_area_m2: 55,
|
||
deal_rooms: 2,
|
||
deal_floor: 6,
|
||
deal_address: "Екатеринбург, ул. Репина, 75/2",
|
||
listing_id: 50001,
|
||
listing_source: "avito",
|
||
listing_source_url: "https://www.avito.ru/ekaterinburg/kvartiry/preview-d1",
|
||
listing_date: "2026-03-20",
|
||
listing_price_rub: 9_500_000,
|
||
listing_price_per_m2: 172_727,
|
||
listing_area_m2: 55,
|
||
days_listing_to_deal: 29,
|
||
discount_pct: -6.3,
|
||
},
|
||
{
|
||
deal_id: 9002,
|
||
deal_date: "2026-02-27",
|
||
deal_price_rub: 9_100_000,
|
||
deal_price_per_m2: 159_649,
|
||
deal_area_m2: 57,
|
||
deal_rooms: 2,
|
||
deal_floor: 9,
|
||
deal_address: "Екатеринбург, ул. Репина, 73",
|
||
listing_id: 50002,
|
||
listing_source: "cian",
|
||
listing_source_url: "https://www.cian.ru/sale/flat/preview-d2",
|
||
listing_date: "2026-01-30",
|
||
listing_price_rub: 9_700_000,
|
||
listing_price_per_m2: 170_175,
|
||
listing_area_m2: 57,
|
||
days_listing_to_deal: 28,
|
||
discount_pct: -6.2,
|
||
},
|
||
],
|
||
};
|