feat(tradein-ui): Yandex admin scraper page — mirror Avito + global delay control #488
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#488
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/tradein-yandex-admin-frontend"
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?
Motivation
User request: "сделай страничку аналогичную авито только нужно добавить глобальный делэй для запросов что бы настройка работала на все запросы". Frontend follow-up to PR #484 (backend
scraper_settings+ Yandex admin trigger endpoints, mergedb21d7c7).Replaces the 5-line "В разработке" stub at
/scrapers/yandexwith a full admin page mirroring the Avito layout, adapted for the 4 Yandex scrapers that landed in PRs #453/#456/#462/#466/#467/#468.Sections
GET/PUT /api/v1/admin/scraper-settingsyandexkey. Settings refetch every 30s; PUT invalidates query on success.POST /api/v1/admin/scrape(sources=[yandex])multi_room_yandex/deep_yandextogglesPOST /api/v1/admin/scrape/yandex-detail?offer_url=POST /api/v1/admin/scrape/yandex-newbuilding?slug=&id=&city=POST /api/v1/admin/scrape/yandex-valuation?address=&offer_category=&offer_type=&page=Skipped vs Avito: city-sweep + schedule sections — no Yandex cron/sweep job exists yet (potential follow-up).
Implementation notes
any@/components/trade-in/trade-in.cssclasses (scraper-page,scraper-section,scraper-section--highlight,scraper-form,scraper-result, etc.) — no new CSSuseScraperSettings(refetch 30s),useUpdateScraperSetting+useScrape*mutationsResultPanel<TData>inlined (no shared component extraction — keeps PR small)Topbar active="yandex"already supports this pageVerification
npx tsc --noEmitagainst main repo: 0 errors (worktree-level errors are missing node_modules cascade — unrelated)npm run lintskipped: project has no ESLint config (interactive prompt, pre-existing state). Prettier pre-commit hook passed.Files
tradein-mvp/frontend/src/app/scrapers/yandex/page.tsx— replaced 5-line stub with 557-line full page (+548 / -9)Reviewer note
Reviewer: deep-code-reviewer — only merge after APPROVE.
Manual smoke after deploy: visit
https://gendsgn.ru/trade-in/scrapers/yandex, change global delay 5→6, save, refresh — value should persist. Then trigger one Valuation for Учителей 18 — should returnyear_built=1981-ish + N history items.Deep Code Review — BLOCK (HIGH × 2)
Endpoints all exist on main (
admin.py:561/576/721/757/796), CSS classes wired, slider min reasonable. But headline feature ("Глобальная задержка запросов") is non-functional because frontend contract mismatches backend in two places. Same bugs already shipped incian/page.tsx(PR #486) — should not be replicated.Critical 1 —
useScraperSettingstypes response wrong → runtime TypeError or silent no-oppage.tsx:73-79:Backend (
admin.py:561-573) returns dict, not array:Confirmed by test
test_scraper_settings.py:312:assert "settings" in data.Result:
settingsQ.dataat runtime is{settings: [...]}. Code atpage.tsx:151, 184:→
.findis not a function on the response object → page throws on render after fetch resolves, ORyandexSettingis always undefined → settings panel never shows, slider input never auto-populates from DB (form always shows hardcoded "5.0").Fix (either):
Critical 2 — PUT body missing required
source→ 422 on every savepage.tsx:38-40+:85-90:Backend
admin.py:555-558:Plus
admin.py:592-596validatespayload.source == path source→ 400 if mismatched.Result: clicking "Сохранить" → 422 "field required: source" → error panel shows red. User cannot save delay.
Fix:
Both bugs already in prod via #486
cian/page.tsx:67-74and:80-91, :141have identical bugs. Recommend same fixup PR (or immediate follow-up) patches Cian too. Also: zero PUT coverage intest_scraper_settings.py→ add a smoke test to prevent regression.Medium (post-merge OK)
useEffectat:96-99reruns every 30s (refetchInterval) → clobbers user mid-edit. Guard with first-load-only flag.Verified OK
scraper-section--highlight,schedule-status*) wired; Topbaractive="yandex"supported;apiFetchroutes viaAPI_BASE_URL=/trade-in→ Caddy strip; no auth header needed; slidermin={1}tighter than backendge=0.0(no 422 risk on lower bound); rebase clean fromb21d7c7.Awaiting fixup commit on
feat/tradein-yandex-admin-frontend. Will re-review when head SHA changes.Fix-up applied (commit
271b5da). All 2 critical + M1 fixed inyandex/page.tsx:useScraperSettingsunwraps.settings—queryFnreturnsapiFetch<{settings: ScraperSetting[]}>("/api/v1/admin/scraper-settings").then((r) => r.settings). Consumer code (settingsQ.data?.find(...)) works unchanged.source— both interface (ScraperSettingUpdatenow hassource: string) and submit payload ({ source: "yandex", request_delay_sec }). Resolves backend Pydantic 422 + path-vs-body source mismatch.initializedRef = useRef(false)guard prevents 30s refetch from clobbering user input mid-edit.Deviation from review recommendation:
cian/page.tsxwas NOT modified — current state on main is a 5-line stub (nouseScraperSettings, no settings UI, no PUT mutation). Bugs 1-3 don't exist there. PR #486 must have shipped only the stub, OR the bugs were already fixed in a later PR. Verify via:expects 0 lines. If Cian admin gets a real settings UI in a future PR, the same fix pattern applies.
Verification:
271b5daRe-review please.
Merged via deep-code-reviewer — verdict ✅ APPROVE (after fixup).
Fix verification (commit
271b5dae)Bug 1 — response wrapper unwrap ✅
Hook now correctly unwraps
{settings:[...]}envelope; consumer.find()operates on real array.Bug 2 — PUT body includes
source✅Matches backend Pydantic
ScraperSettingPayloadrequired field; path source == body source validation passes.Bonus — useEffect race fix (M) ✅
delayInitializedRefguards first-load init so the 30srefetchIntervaldoesn't clobber user's in-progress slider edit.Follow-up needed — Cian sibling hotfix 🟡
tradein-mvp/frontend/src/app/scrapers/cian/page.tsx(merged in PR #486) still has BOTH bugs:useScraperSettings: types asapiFetch<ScraperSetting[]>(unwrapped) — wrong, real response is{settings:[...]}..find(...)will throwTypeError: data.find is not a function.body: JSON.stringify(payload): missingsourcefield — every save will 422.Cian admin page settings panel is currently shipping broken on prod. Recommend hotfix PR
fix/tradein-cian-scraper-settings-shapeapplying identical pattern.Post-merge smoke checklist
https://gendsgn.ru/trade-in/scrapers/yandex→ Global delay panel renders current value (not blank)year_built≈ 1981, history items list populated