feat(tradein-ui): placement history card #529
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#529
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/tradein-ui-placement-history-card"
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?
Context
New backend endpoint
GET /estimate/{id}/placement-history(PR 11a) exposes historical lots fromhouse_placement_historylinked to target house after PR #527 bootstrap.Changes
types/trade-in.ts— addedPlacementHistoryIteminterface mirroring backend schemalib/trade-in-api.ts—useEstimatePlacementHistoryhook (TanStack Query,staleTime: 10 min,enabledguard)PlacementHistoryCard.tsx(new) — table: title / start→last price / last date / exposure_days. Slices at 20 с «показано N из M» note. Returnsnullon loading/error/empty (quiet fail — supplementary card).page.tsx— importsPlacementHistoryCard, renders afterHouseInfoCardwrapped in{currentEstimateId && …}guardHouseInfoCard.tsxalready handled non-empty arrays correctly — no changes.Dependencies
Deploys AFTER PR #527 (DB backfill) и PR 11a (backend endpoint). Card будет пустой / hidden пока зависимости не merged.
Verify
After deploy chain (527 → 11a → this):
house_placement_historyNew /estimate/{id}/placement-history endpoint surfaces historical lots from house_placement_history for the target house (linked after PR #527 bootstrap). Card hidden when no data. - PlacementHistoryItem type added to trade-in.ts - useEstimatePlacementHistory hook added to trade-in-api.ts - PlacementHistoryCard component uses TanStack Query (no raw fetch) - Wired into page.tsx after HouseInfoCardDeep Code Review #529 — placement history card
Verdict: APPROVE. Small focused UI addition (1 new component + 1 hook + 1 type + 4-line page wiring). Safe to deploy independently of PR #527 / 11a: card silently renders
nullon isError/empty per PR description.What was checked
dangerouslySetInnerHTML, no URL rendering —safeUrlnot applicable herekey={it.id}(numeric PK, unique);items.slice(0, 20)only after non-empty guard; datetry/catch; page wraps<PlacementHistoryCard estimateId={currentEstimateId} />in{currentEstimateId && ...}so thestring-typed prop is always truthy at call siteuseEstimatePlacementHistoryfollows established pattern (queryKey, staleTime 10min,enabledguard) — matchesuseEstimate/useEstimateHouses/useEstimateImvBenchmarkinlib/trade-in-api.tsPlacementHistoryIteminterface mirrorshouse_placement_historyschema from PR #527 / decisions/Schema_Avito_Houses_Listings_Historyvar(--muted, ...)/var(--border, ...)fromtrade-in.css(OKLCH palette) with hex fallbacks<article>/<header>/<h3>/<table>with proper<thead>/<tbody>/<th>/<td>Minor cosmetic notes (non-blocking)
"лот" / "лотов"only handles 1 vs not-1. Russian needs 1/2-4/5+ tier:2renders "лотов" (should be "лота");21renders "лотов" (should be "лот"). Same simplistic pattern exists in other parts of the app — acceptable.aria-labelon<article>— siblingHouseInfoCard.tsxusesaria-label="Информация о доме". Consistency nit, not a blocker.style={{ padding: "6px 8px" }}etc., whileDealsCard.tsx/ListingsCard.tsxlean on semantic CSS classes.HouseInfoCard.tsxmixes both. Mild drift; acceptable given supplementary card status./trade-in?id=...load fires a 404 GET on/api/v1/trade-in/estimate/{id}/placement-history.apiFetchthrows →isError=true→ renders null (no UI break), but log noise. Acceptable per PR description ordering.Cross-file impact
types/trade-in.ts+lib/trade-in-api.tsare additive — no breaking changes to existingAggregatedEstimate/HouseInfoForEstimateconsumerspage.tsxinsertion ordered afterHouseInfoCard, beforePhotoUpload— wrapped incurrentEstimateIdguard; no impact on form-only view (!resultDatabranch unchanged)Positive
nullrender strategy keeps the card invisible until backend is wired — clean staged rollout patterntrade-in-api.tstry/catcharoundnew Date(d).toLocaleDateStringfor malformed ISO stringsComplexity / blast radius