Commit graph

9 commits

Author SHA1 Message Date
6a46585e8c feat(tradein): StreetDealsCard с paired listings (PR L / #564 Phase 2)
Switch StreetDealsCard от /street-deals к /sales-vs-listings. В каждой
строке ДКП-сделки теперь показан linked исторический ASK с источником
(Avito/Cian/Yandex/N1), ценой listing, сроком до сделки и discount_pct
в цвете (зелёный = торг, красный = overshoot). В шапке секции —
linkage_rate % сделок имеют match + медианный торг по pairs с listing.

Changes:
- types/trade-in.ts: SalesListingPair + SalesVsListingsResponse
- lib/trade-in-api.ts: useSalesVsListings hook (TanStack, staleTime 10m)
- components/StreetDealsCard.tsx: rewrite — switch endpoint, add listing
  column, compute aggregates client-side (count/median/range), extract
  <ListingBadge> subcomponent
- components/trade-in.css: token-based styles (.linkage-hint, .discount-pos/neg,
  .listing-cell, .listing-link, .listing-source-badge) + mobile breakpoint

Decisions:
- Endpoint replacement (не parallel fetch) — /sales-vs-listings суперсет
- Period default 24 мес (от endpoint default) — больше data для pairing
- Discount sign: var(--success) при <0 (торг), var(--danger) при >0
- safeUrl() guard для listing URLs (XSS) + target="_blank" rel="noopener"
- Mobile <720px — listing column stacks vertically
- linkage_rate=0 → listing column скрыт целиком (`hasAnyListing` flag)

Tests: tsc --noEmit clean. No new deps.

Out of scope: useStreetDeals hook deprecated, можно убрать в cleanup PR.

Closes #564 Phase 2.
2026-05-27 17:28:38 +05:00
5bfacd51b0 feat(tradein): «Росреестр» button — copy address + open EGRN request form (#550)
Some checks failed
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Has been cancelled
2026-05-24 19:42:09 +00:00
08cf615ad7 feat(tradein/cian): surface valuation chart + rent + change-pct on /trade-in (#530)
Some checks failed
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Successful in 48s
Deploy Trade-In / build-frontend (push) Has been cancelled
2026-05-24 14:32:54 +00:00
fd3cb4e6ed feat(tradein): /scrapers/avito — 6-я секция Расписание (in-app scheduler UI) (#483)
All checks were successful
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-frontend (push) Successful in 1m22s
Deploy Trade-In / deploy (push) Successful in 23s
Deploy Trade-In / build-backend (push) Has been skipped
2026-05-23 14:55:31 +00:00
dd24bd8136 feat(tradein): /scrapers/avito — 5-я секция City sweep (auto + cancel + runs list) (#478)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m22s
Deploy Trade-In / deploy (push) Successful in 23s
2026-05-23 14:40:11 +00:00
649034479f feat(tradein): Stage 4c — scrapers admin pages (Avito real + Cian/Yandex stubs) (#472)
All checks were successful
Deploy Trade-In / build-frontend (push) Successful in 1m23s
Deploy Trade-In / deploy (push) Successful in 22s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
2026-05-23 14:05:56 +00:00
72d2b97ee0 feat(tradein): Stage 4b — IMV benchmark badge + house info card on estimate result (#461)
All checks were successful
Deploy Trade-In / deploy (push) Successful in 21s
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m21s
2026-05-23 13:28:23 +00:00
6041ac8464 fix(tradein): фото аналога в Сводке больше не скрыто плейсхолдером
В .hero-photo псевдоэлементы ::before/::after рисуют декоративный
скелет-плейсхолдер «фасада дома». Они position:absolute, а <img> с
фото аналога — position:static, поэтому абсолютные псевдоэлементы
рисовались ПОВЕРХ картинки: реальное фото загружалось (naturalWidth
есть), но визуально всегда был серый плейсхолдер.

Фото (z-index 1) и подпись .photo-meta (z-index 2) теперь над
скелетом. Скелет остаётся виден, когда фото нет или оно не
загрузилось (onError → display:none).
2026-05-22 15:35:01 +05:00
lekss361
02267d0306 feat: add tradein-mvp subproject (Trade-In Estimator под /trade-in)
- FastAPI backend: PostGIS estimator + 3 scrapers (Avito/Cian/Yandex)
- Next.js 15 frontend: tradein.html mockup design, basePath=/trade-in
- WeasyPrint PDF (Брусника-style 4-page report)
- Address autocomplete с typo-tolerance + 6 EKB presets
- Изолированный docker stack gendesign-tradein (отдельная postgres БД)
- Caddy inline routes: gendsgn.ru/trade-in/* и /trade-in/api/v1/*
- Forgejo Actions: .forgejo/workflows/deploy-tradein.yml (shell-based GHCR login)
- Триггер только по paths: tradein-mvp/** (не пересекается с deploy.yml)
- Образы: ghcr.io/lekss361/gendesign-tradein-{backend,frontend}:latest

Первый запуск на сервере (вручную, один раз):
  - создать /opt/gendesign/tradein-mvp/.env.runtime (postgres pwd, contact email)
  - docker network create gendesign_shared (если нет)
  - docker compose -p gendesign-tradein up -d
  - docker compose -p gendesign exec caddy caddy reload
2026-05-21 00:25:39 +03:00