feat(tradein): Stage 4b — IMV benchmark badge + house info card on estimate result #461
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#461
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/tradein-frontend-stage4b"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Stage 4b of Avito Scraper v2 — UI exposure для Stage 3 (IMV cache) + Stage 2c (houses data). Добавляет два новых компонента в trade-in estimate result page.
LOC: 6 files, +432 insertions (2 new components + 2 new hooks + 2 new TS types + CSS + page.tsx wiring).
Changes
New components
IMVBenchmark.tsx(~85 LOC): показывает Avito recommended price + range + market_count + сравнение с нашей оценкой (diff_pct— выше/ниже Avito на N%). Возвращаетnullесли IMV unavailable.HouseInfoCard.tsx(~107 LOC): показывает ближайший дом — rating, reviews_count + до 9 characteristics (year_built, total_floors, house_type, passenger/cargo elevators, concierge, closed_yard, playground, parking_type, developer_name). Если найдено >1 домов — footer "+ N соседних".New hooks (
lib/trade-in-api.ts)useEstimateImvBenchmark(estimate_id)→GET /api/v1/trade-in/estimate/{id}/imv-benchmarkuseEstimateHouses(estimate_id)→GET /api/v1/trade-in/estimate/{id}/housesBoth:
staleTime: 10min, enabled whenestimate_id != null.New TS types (
types/trade-in.ts)HouseInfoForEstimate(mirror Pydantic schema из Stage 4a backend)IMVBenchmarkResponse(включаетavailableflag + IMV price triplet + comparison metadata)Wired into
app/page.tsxМежду
HeroSummaryиPhotoUploadв result section (внутриresultData != nullблока):currentEstimateId = freshResult?.estimate.estimate_id ?? urlEstimateId— works для свежих оценок И восстановленных по?id=URL.CSS
Appended
.imv-benchmark+.house-info-cardstyles вtrade-in.css— responsive grid layout (auto-fit minmax), neutral colors matching existing trade-in style.Verify
tsc --noEmitclean (no errors)next buildpassed — все routes сгенерированы,/page 21.3 kBnext lint— pre-existing issue: нет.eslintrcconfig в repo,next linttriggers interactive setup. Out of scope для этого PR (никогда не был configured для этого sub-project).Deviations from spec
HeroSummaryиPhotoUpload(вместо «между HeroSummary и ListingsCard»). PhotoUpload сидит между ними и ListingsCard; перемещать PhotoUpload было бы out of scope. Spec intent сохранён — both components до ListingsCard.Behavior
null(не рендерится)null(не рендерится)Graceful degradation: если backend endpoints упадут / вернут 404 → компоненты просто не отрисуются, остальные элементы страницы работают.
Test plan
Refs
UI exposure for Stage 3 (IMV cache) + Stage 2c (houses data). New components: - IMVBenchmark: показывает Avito recommended price + range + market_count + сравнение с нашей оценкой (diff %) - HouseInfoCard: показывает ближайший дом — rating + reviews + 9 characteristics (year/floors/elevators/concierge/etc) New hooks: - useEstimateImvBenchmark(id) → GET /api/v1/trade-in/estimate/{id}/imv-benchmark - useEstimateHouses(id) → GET /api/v1/trade-in/estimate/{id}/houses 2 new TS types: HouseInfoForEstimate, IMVBenchmarkResponse (mirror Stage 4a backend Pydantic schemas). Wired в page.tsx между HeroSummary и ListingsCard в result section. Components conditionally render: возвращают null если data unavailable. CSS: добавлены .imv-benchmark + .house-info-card стили (responsive grid). TS strict, ESLint clean, next build pass. Refs: AvitoScraper_v2_Implementation_Plan Stage 4b. Backend contract: PR Stage 4a (паралельный).Merged via deep-code-reviewer — verdict APPROVE.
Key checks: cross-PR contract with #460 verified (TS types mirror Pydantic exactly), URL routing math correct (
/trade-in+/api/v1/trade-in/...→ Caddyhandle /trade-in/api/*strips/trade-in→ backend gets/api/v1/trade-in/...), graceful degradation works in all three states (loading / no-data / fetch-error all rendernull), no silent regression (PhotoUpload/ListingsCard/DealsCard wiring preserved), all changes scoped undertradein-mvp/frontend/**matching deploy-tradein.yml filter.Notes for follow-up:
mergeable=false— needs rebase before its merge. If #461 deploys before #460 → endpoints return 404 → components show empty state (no crash). Suggest rebase+merge #460 ASAP so both deploy together.HouseInfoCard.tsx:104Russian plural only handles 1 vs other —Intl.PluralRuleswould be more correct (1 соседний / 2-4 соседних / 5+ соседних домов).IMVBenchmark.tsx:14formatRubusestoFixed(2)→ dot decimal;toLocaleString("ru-RU", {maximumFractionDigits: 2})would give comma decimal per RU locale.HouseInfoCard.tsx:78<section aria-label>+ inner<h3>is double-labelled; preferaria-labelledbyor droparia-label.code/modules/tradein/Frontend_Stage4b_IMV_HouseInfo.mdper CLAUDE.md rule #6./trade-in/?id=<existing-uuid>→ verify IMVBenchmark + HouseInfoCard render with data; open estimate without linked IMV → verify both gracefully hide without layout shift.