chore(plan): lab-split 5-phase plan

PLAN.md + 5 subplans + CONTEXT.md

Strategy: Incremental | Mode: Automated | Execution: Direct

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-05-22 22:33:41 +03:00
parent 58cff2285e
commit 77ebe9e3e4
7 changed files with 429 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
# Phase 4: Hash-router для sim deep-links
**Status:** ⬜ Not Started
**Parent plan:** [PLAN.md](./PLAN.md)
**Domain:** frontend
## Objective
Сделать `#sim/projectile`, `#sim/newton`, `#sim/chemsandbox` etc. → открывают конкретный sim в lab. F5 на любом deep-link восстанавливает sim. Browser back/forward переключают между симуляциями. По образцу admin-redesign Phase 1 router.
## Tasks
- [ ] В `frontend/js/labs/lab-glue.js` (или новый `frontend/js/labs/lab-router.js`):
- На load: прочитать `location.hash`, parsr `#sim/<name>`, активировать соответствующий sim
- Listen `hashchange`: при изменении hash → переключить sim
- При программном переключении sim (через sim-switcher UI) → обновить hash без recursion (флаг `_routerNavigating`)
- [ ] Map sim-name → sim-id:
- `#sim/projectile` → activate `<div id="sim-proj">`
- `#sim/newton` → activate `<div id="sim-dynamics">` (или какой-там)
- Полный mapping из существующих sim-ID
- [ ] Fallback: unknown hash → ignore (показать default sim)
- [ ] Verify: F5 на `/lab#sim/projectile` восстанавливает projectile sim
## Files to Modify
- `frontend/js/labs/lab-glue.js` — добавить router code (~50-100L)
- `frontend/lab.html` — без изменений (или + 1 script tag если делаем отдельный lab-router.js)
## Acceptance Criteria
- F5 на `/lab#sim/X` восстанавливает соответствующий sim
- Browser back/forward переключают между sims
- Click на sim-switcher обновляет URL (`#sim/X` в адресной строке)
- Unknown hash (`#sim/nonexistent`) → console.warn + fallback на default
- 5 deep-link проверены вручную (projectile, newton, chemsandbox, gas, mirror)
## Notes
### Recursion guard pattern (из admin-redesign Phase 1)
```js
let _navigating = false;
function navigateTo(simId) {
_navigating = true;
location.hash = '#sim/' + simId;
setTimeout(() => { _navigating = false; }, 0);
activateSim(simId);
}
window.addEventListener('hashchange', () => {
if (_navigating) return;
const m = location.hash.match(/^#sim\/([\w-]+)/);
if (m) activateSim(m[1]);
});
```
### Reference
`frontend/js/admin/router.js` (admin-redesign Phase 1) — read for inspiration. Adapt to lab context.
## Review Checklist
- [ ] Hash deep-link работает для 5 проверенных симов
- [ ] Browser back/forward работают
- [ ] No console errors
- [ ] No infinite-loop при программной активации
- [ ] Pre-commit hook passes
## Handoff to Next Phase
<!-- Implementer: full mapping #sim/X → sim-ID для Phase 5 (template lazy). -->