feat(site-finder): per-room bucket breakdown в VelocityBlock #166

Merged
lekss361 merged 1 commit from feat/velocity-block-per-room-frontend into main 2026-05-15 07:12:42 +00:00
lekss361 commented 2026-05-15 07:05:46 +00:00 (Migrated from github.com)

Frontend для backend PR #163. Aggregate table 'По комнатности' + per-competitor mini-row. Backward compat via optional fields. tsc 0 errors. Closes #161 frontend.

Frontend для backend PR #163. Aggregate table 'По комнатности' + per-competitor mini-row. Backward compat via optional fields. tsc 0 errors. Closes #161 frontend.
lekss361 commented 2026-05-15 07:12:21 +00:00 (Migrated from github.com)

Final review (SHA 8c41a66, CI )

Cross-checked агентом — TS contract gap из PR #163 закрыт корректно.

TS contract exact alignment:

interface VelocityBucketStat { units: number; sqm: number; complexes_count: number; }
Velocity.by_room_bucket?: Record<string, VelocityBucketStat>;
VelocityCompetitor.by_room_bucket?: Record<string, number>;

Field names и shapes 1:1 с backend as_dict(). Нет drift'а как в PR #147 (где был obj_class vs class, total_sqm_period vs total_sqm).

Rendering safety: optional chaining velocity.by_room_bucket && ... и velocity.by_room_bucket?.[b] guard backend-без-field. Empty {} объект → header без rows (acceptable).

Backward compat: оба ?: optional — старый backend response не крашит UI.

Deterministic ordering: hardcoded BUCKET_ORDER = ["студия", "1", "2", "3", "4+"] — стабильный порядок. Unknown buckets silently dropped (reasonable trade-off).

Type-safety: Record<string, ...> matches backend str keys, не too strict.

tsc 0 errors, CI green.

Минор (pre-existing patterns, не блокеры)

  • Hardcoded hex colors без dark-mode — consistent с existing VelocityBlock style, не регрессия

approve merge

## Final review (SHA `8c41a66`, CI ✅) Cross-checked агентом — TS contract gap из PR #163 закрыт корректно. ✅ **TS contract exact alignment**: ```ts interface VelocityBucketStat { units: number; sqm: number; complexes_count: number; } Velocity.by_room_bucket?: Record<string, VelocityBucketStat>; VelocityCompetitor.by_room_bucket?: Record<string, number>; ``` Field names и shapes 1:1 с backend `as_dict()`. **Нет drift'а как в PR #147** (где был `obj_class` vs `class`, `total_sqm_period` vs `total_sqm`). ✅ **Rendering safety**: optional chaining `velocity.by_room_bucket && ...` и `velocity.by_room_bucket?.[b]` guard backend-без-field. Empty `{}` объект → header без rows (acceptable). ✅ **Backward compat**: оба `?:` optional — старый backend response не крашит UI. ✅ **Deterministic ordering**: hardcoded `BUCKET_ORDER = ["студия", "1", "2", "3", "4+"]` — стабильный порядок. Unknown buckets silently dropped (reasonable trade-off). ✅ **Type-safety**: `Record<string, ...>` matches backend `str` keys, не too strict. ✅ tsc 0 errors, CI green. ### Минор (pre-existing patterns, не блокеры) - Hardcoded hex colors без dark-mode — consistent с existing VelocityBlock style, не регрессия approve merge
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#166
No description provided.