fix(sf-fe): decode cad param (B5 400) + hide entry sidebar when drawer open #350

Closed
lekss361 wants to merge 2 commits from fix/sf-cad-decode-drawer-overlay into main
Owner

Summary

2 prod регрессии (user screenshot):

Bug A — /parcels/{cad}/analyze всегда 400

API error 400: Неверный формат кадастрового номера.
Ожидается NN:NN:NNNNNN или NN:NN:NNNNNN:NN

Next.js dynamic route доставляет params.cad URL-encoded (:%3A). Хуки потом делали encodeURIComponent на уже-encoded строке, получая /api/v1/parcels/66%253A41%253A0204016%253A10/analyze. FastAPI decoded one layer → 66%3A41%3A0204016%3A10, regex rejected → 400. Section 1 вечный error state.

Fix: decodeURIComponent(cadRaw) один раз на границе page → downstream хуки/breadcrumb/Section1 видят canonical 66:41:0204016:10 и encode ровно один раз при build URL. Заодно закрывает breadcrumb double-encode bug из QA PR #346.

Bug B — sidebar и drawer наложены

При click на парцель <ParcelDrawer/> slide-in из правого края наезжал на правый sidebar (CadInput + RecentParcels + ParcelLegend), который тоже anchored right. Видно на screenshot: «Кадастровый номер» проступает через панель парцеля.

Fix: conditional render — sidebar mounts только когда selectedParcel == null. Открытие парцеля даёт drawer чистую правую колонку. Закрытие восстанавливает sidebar.

Verify post-deploy

  • /site-finder/analysis/66:41:0204016:10 — Section 1 НЕ показывает «не удалось загрузить»; KPI + EGRN + POI рендерятся.
  • Network: GET /api/v1/parcels/66%3A41%3A0204016%3A10/analyze → 200 (single-encode).
  • /site-finder → click на marker → drawer открывается, sidebar исчезает; close → sidebar возвращается.
  • Breadcrumb на analysis page — 66:41:0204016:10, не 66%3A41%3A0204016%3A10.

Base: fix/sf-entry-parcel-adapter-cadinput (PR #349). Merge order: #349#350 (этот), либо squash оба в main.

## Summary 2 prod регрессии (user screenshot): ### Bug A — `/parcels/{cad}/analyze` всегда 400 ``` API error 400: Неверный формат кадастрового номера. Ожидается NN:NN:NNNNNN или NN:NN:NNNNNN:NN ``` Next.js dynamic route доставляет `params.cad` **URL-encoded** (`:` → `%3A`). Хуки потом делали `encodeURIComponent` на уже-encoded строке, получая `/api/v1/parcels/66%253A41%253A0204016%253A10/analyze`. FastAPI decoded one layer → `66%3A41%3A0204016%3A10`, regex rejected → 400. Section 1 вечный error state. **Fix**: `decodeURIComponent(cadRaw)` один раз на границе page → downstream хуки/breadcrumb/Section1 видят canonical `66:41:0204016:10` и encode ровно один раз при build URL. Заодно закрывает breadcrumb double-encode bug из QA PR #346. ### Bug B — sidebar и drawer наложены При click на парцель `<ParcelDrawer/>` slide-in из правого края наезжал на правый sidebar (CadInput + RecentParcels + ParcelLegend), который тоже anchored right. Видно на screenshot: «Кадастровый номер» проступает через панель парцеля. **Fix**: conditional render — sidebar mounts только когда `selectedParcel == null`. Открытие парцеля даёт drawer чистую правую колонку. Закрытие восстанавливает sidebar. ## Verify post-deploy - [ ] `/site-finder/analysis/66:41:0204016:10` — Section 1 НЕ показывает «не удалось загрузить»; KPI + EGRN + POI рендерятся. - [ ] Network: `GET /api/v1/parcels/66%3A41%3A0204016%3A10/analyze` → 200 (single-encode). - [ ] `/site-finder` → click на marker → drawer открывается, sidebar исчезает; close → sidebar возвращается. - [ ] Breadcrumb на analysis page — `66:41:0204016:10`, не `66%3A41%3A0204016%3A10`. Base: `fix/sf-entry-parcel-adapter-cadinput` (PR #349). Merge order: #349 → #350 (этот), либо squash оба в main.
lekss361 added 2 commits 2026-05-17 23:31:26 +00:00
Two prod regressions noticed by user after #347 deploy ('не видно
участков · и нельзя просто ввести'):

1. Markers invisible — backend B1 returns
   { parcels: [{cad_num, centroid_lat, centroid_lon, area_m2, status, ...}], count, limit, bbox_area_km2 }
   but useParcelsBboxQuery typed the response as a flat ParcelBboxItem[]
   with fields { lat, lon, area_ha, district, vri, address, status }.
   Result: .map() iterated over an object (no markers rendered) and
   even if iterated, every CircleMarker got center=[undefined, undefined].
   Added an adapter in queryFn: unwrap .parcels, rename
   centroid_lat/centroid_lon -> lat/lon, convert area_m2 -> area_ha,
   default status to 'free' when null, placeholder district/vri/address
   until B1 enrichment lands. applyFilters still runs client-side.

2. No manual cad entry — A2 #343 dropped the existing CadInput component
   from the entry page when replacing placeholders. Re-wired it in the
   right sidebar above RecentParcels; submit -> router.push to
   /site-finder/analysis/{cad} (matches A1 routing scheme).
Two prod issues:

1. Analysis page B5 endpoint returned HTTP 400 'Неверный формат
   кадастрового номера' for any cad. Next.js dynamic route delivers
   `params.cad` URL-encoded (':' -> '%3A'). Hooks then ran
   encodeURIComponent on the already-encoded string, producing
   /api/v1/parcels/66%253A41%253A0204016%253A10/analyze; FastAPI
   decoded one layer to '66%3A41%3A0204016%3A10', which the regex
   rejected. Fix: decodeURIComponent the param once at the page
   boundary so downstream consumers (hooks + breadcrumb + Section1)
   work with the canonical '66:41:0204016:10' and encode exactly
   once when building URLs. Also resolves the breadcrumb double-
   encode noted in PR #346 QA.

2. Entry page right-sidebar (CadInput + RecentParcels + ParcelLegend)
   visually overlapped the ParcelDrawer slide-in: both were anchored
   to the right edge with the drawer rendered above as an overlay
   without an opaque backdrop on the sidebar area. Conditional render:
   sidebar only mounts when no parcel is selected, so opening a parcel
   gives the drawer a clean right column.
Author
Owner

⚠️ Merge blocked: conflict with main after PR #349 merge.

mergeable=false — branch was cut before #349 merged (#350 base fd4eb8c6 vs current main f87a3522). Both PRs touch frontend/src/app/site-finder/page.tsx and lib/site-finder-api.ts → overlap.

update_pr_branch returned 409: merge failed because of conflict. Author resolution needed — rebase branch onto current main, resolve conflicts (keep #349's adapter + CadInput restore, layer #350's decodeURIComponent + conditional sidebar on top).

Will re-review and merge on next polling iteration once branch updated.

⚠️ **Merge blocked: conflict with main after PR #349 merge.** `mergeable=false` — branch was cut before #349 merged (#350 base `fd4eb8c6` vs current main `f87a3522`). Both PRs touch `frontend/src/app/site-finder/page.tsx` and `lib/site-finder-api.ts` → overlap. `update_pr_branch` returned `409: merge failed because of conflict`. Author resolution needed — rebase branch onto current main, resolve conflicts (keep #349's adapter + CadInput restore, layer #350's decodeURIComponent + conditional sidebar on top). Will re-review and merge on next polling iteration once branch updated.
lekss361 closed this pull request 2026-05-17 23:34:55 +00:00

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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#350
No description provided.