gendesign/frontend/src
lekss361 990c109756 fix(#234): NSPD harvest ETA badge + SETNX dedupe (Sub-PR C)
Backend (quarter_dump_lookup.py):
- _acquire_harvest_lock: Redis SETNX TTL=120s на quarter, защищает от burst
  N concurrent analyze, ставящих N одинаковых harvest task в очередь
- _trigger_harvest: использует lock перед apply_async, возвращает False если
  lock уже взят (другой запрос триггернул раньше)
- make_empty_result/EMPTY_DUMP_RESULT: новое поле harvest_eta_seconds в
  nspd_dump dict, типичный harvest_quarter = 60с
- /analyze: пробрасывает поле через nspd_dump dict (нет typed schema —
  response_model=None для /analyze endpoint, dict уходит как есть)

Frontend (NspdFreshnessBadge, NspdZoningBlock):
- Countdown «НСПД: загрузка ~Nс» вместо бесконечного спиннера
- После остановки countdown (remaining=0) NspdZoningBlock показывает
  «загрузка дольше обычного» + ссылку на ПКК вместо infinite skeleton

Tests: 5 новых unit + 2 для empty_result schema (всего +7, pass)

Closes #234 (UX-side; data-side resolves когда Sub-PR B + D merged).
2026-05-17 09:13:06 +03:00
..
app feat(#115): Leaflet layer toggle для connection points (Макс KILLER) 2026-05-16 22:51:12 +03:00
components fix(#234): NSPD harvest ETA badge + SETNX dedupe (Sub-PR C) 2026-05-17 09:13:06 +03:00
hooks feat(site-finder): debounce weight re-analyze (#201 Phase 2) (#215) 2026-05-16 12:54:51 +00:00
lib fix(frontend): apiFetchWithStatus body stream double-read crash (#149) 2026-05-15 07:39:21 +03:00
types fix(#234): NSPD harvest ETA badge + SETNX dedupe (Sub-PR C) 2026-05-17 09:13:06 +03:00
instrumentation.ts feat(frontend): @sentry/nextjs init для GlitchTip (#204 frontend) (#208) 2026-05-16 15:09:38 +00:00