[tradein][frontend] Error/not-found UI при восстановлении оценки по ?id= #822

Closed
opened 2026-05-30 19:40:14 +00:00 by lekss361 · 2 comments
Owner

Worker: auto-frontend. Ветка от forgejo/main, код+PR. Backend не трогать. Тест: npm run build + (опц) playwright на /trade-in/?id=<несуществующий-uuid>.

Задача

/trade-in/?id=<uuid> вызывает useEstimate(urlEstimateId), но читается только .data.isError/.isPending НЕ читаются. Backend теперь отдаёт 404 на missing/owner-mismatch (_assert_estimate_access). При 404 resultData=null → страница молча показывает empty-state «🏠 Введите параметры» — маскирует «отчёт не найден/нет доступа/устарел». При загрузке — то же (нет скелетона).

Файлы

  • frontend/src/app/page.tsx:91-94restoredEstimate = useEstimate(...)
  • frontend/src/app/page.tsx:115-128 — resultData только из .data
  • frontend/src/app/page.tsx:226-291 — развилка resultData ? : empty-state
  • useEstimate — grep export function useEstimate (lib/*)

Definition of Done

  • urlEstimateId && restoredEstimate.isError → not-found/error card («Отчёт не найден или недоступен» + кнопка «Новая оценка» → router.replace("/")), НЕ дефолтный empty-state.
  • urlEstimateId && isPending && !freshResult → loading (skeleton/спиннер), НЕ empty-state.
  • 404 (из HTTPError) → not-found текст; прочее → generic error.
  • npm run build + npx tsc --noEmit зелёные.

Не делать

  • Backend/эндпоинты не трогать. Путь свежей оценки (freshResult) не ломать. Без suspense-рефактора.
> Worker: auto-frontend. Ветка от forgejo/main, код+PR. Backend не трогать. Тест: npm run build + (опц) playwright на /trade-in/?id=<несуществующий-uuid>. ## Задача `/trade-in/?id=<uuid>` вызывает `useEstimate(urlEstimateId)`, но читается только `.data` — `.isError`/`.isPending` НЕ читаются. Backend теперь отдаёт **404** на missing/owner-mismatch (`_assert_estimate_access`). При 404 `resultData=null` → страница молча показывает empty-state «🏠 Введите параметры» — маскирует «отчёт не найден/нет доступа/устарел». При загрузке — то же (нет скелетона). ## Файлы - `frontend/src/app/page.tsx:91-94` — `restoredEstimate = useEstimate(...)` - `frontend/src/app/page.tsx:115-128` — resultData только из `.data` - `frontend/src/app/page.tsx:226-291` — развилка resultData ? : empty-state - `useEstimate` — grep `export function useEstimate` (lib/*) ## Definition of Done - [ ] `urlEstimateId && restoredEstimate.isError` → not-found/error card («Отчёт не найден или недоступен» + кнопка «Новая оценка» → router.replace("/")), НЕ дефолтный empty-state. - [ ] `urlEstimateId && isPending && !freshResult` → loading (skeleton/спиннер), НЕ empty-state. - [ ] 404 (из HTTPError) → not-found текст; прочее → generic error. - [ ] `npm run build` + `npx tsc --noEmit` зелёные. ## Не делать - Backend/эндпоинты не трогать. Путь свежей оценки (freshResult) не ломать. Без suspense-рефактора.
lekss361 added this to the Night batch — 2026-05-31 milestone 2026-05-30 19:40:14 +00:00
lekss361 added the
bug
scope/frontend
priority/p2
tradein
status/ready
labels 2026-05-30 19:40:15 +00:00
bot-frontend self-assigned this 2026-05-30 19:41:27 +00:00
bot-frontend added
status/wip
and removed
status/ready
labels 2026-05-30 19:41:29 +00:00
bot-frontend added
status/review
and removed
status/wip
labels 2026-05-30 19:46:19 +00:00
Collaborator

Working on this in PR #825.

Working on this in PR #825.
bot-reviewer added
status/qa
and removed
status/review
labels 2026-05-30 19:49:52 +00:00
Collaborator

QA PASS — error/not-found UI на ?id=-restore (PR #825, merged 19:49). Live-смоук на gendsgn.ru/trade-in (pilot user7):

  • Битый id (?id=00000000-0000-0000-0000-000000000000) → карточка «Отчёт не найден или недоступен» + подпись «Ссылка устарела, отчёт удалён или у вас нет к нему доступа» + кнопка «Новая оценка». Форма НЕ рендерится (hasAddressInput=false) → молчаливого empty-state БОЛЬШЕ НЕТ.
  • 404-specific текст (не generic) — DoD #3 .
  • «Новая оценка» → URL очищается ?id=https://gendsgn.ru/trade-in (router.replace), форма возвращается (hasAddressInput=true).
  • Свежий load /trade-in/ (без id) → только форма, без карточки.
  • npm run build 11/11 + tsc — per PR .

(Примечание: «Введите параметры» в правом рейле — это idle-плейсхолдер виджета агрегации «0/7 источников», отдельный от main-empty-state; не маскирует ошибку.)

status/done, closing. Закрывает deferred-часть #25 из #770.


ℹ️ Minor non-blocking (не фейлю, не регрессия — старое поведение было строго хуже): после клика «Новая оценка» в SPA-переходе стаут-карточка «Отчёт не найден» НЕ размонтируется сразу — висит ниже формы (y≈889) до любой следующей навигации/перезагрузки. Свежий load чист. Вероятно useEstimate.isError кэшируется по старому id-ключу, а ветка ошибки не сбрасывается в том же client-transition после router.replace. Косметика, не демо-блокер — кандидат на мелкий polish-follow-up (сбросить error-стейт / reset query при clear-id), отдельный issue не завожу.

✅ **QA PASS** — error/not-found UI на `?id=`-restore (PR #825, merged 19:49). Live-смоук на `gendsgn.ru/trade-in` (pilot `user7`): - **Битый id** (`?id=00000000-0000-0000-0000-000000000000`) → карточка **«Отчёт не найден или недоступен»** + подпись «Ссылка устарела, отчёт удалён или у вас нет к нему доступа» + кнопка **«Новая оценка»**. Форма НЕ рендерится (`hasAddressInput=false`) → молчаливого empty-state БОЛЬШЕ НЕТ. ✅ - **404-specific текст** (не generic) — DoD #3 ✅. - **«Новая оценка»** → URL очищается `?id=` → `https://gendsgn.ru/trade-in` (router.replace), форма возвращается (`hasAddressInput=true`). ✅ - Свежий load `/trade-in/` (без id) → только форма, без карточки. ✅ - `npm run build` 11/11 + tsc — per PR ✅. (Примечание: «Введите параметры» в правом рейле — это idle-плейсхолдер виджета агрегации «0/7 источников», отдельный от main-empty-state; не маскирует ошибку.) → `status/done`, closing. Закрывает deferred-часть #25 из #770. --- ℹ️ **Minor non-blocking** (не фейлю, не регрессия — старое поведение было строго хуже): после клика «Новая оценка» в SPA-переходе стаут-карточка «Отчёт не найден» НЕ размонтируется сразу — висит ниже формы (y≈889) до любой следующей навигации/перезагрузки. Свежий load чист. Вероятно `useEstimate.isError` кэшируется по старому id-ключу, а ветка ошибки не сбрасывается в том же client-transition после `router.replace`. Косметика, не демо-блокер — кандидат на мелкий polish-follow-up (сбросить error-стейт / reset query при clear-id), отдельный issue не завожу.
bot-qa added
status/done
and removed
status/qa
labels 2026-05-30 19:57:36 +00:00
Sign in to join this conversation.
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#822
No description provided.