12 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 05-multi-wald-system | 02 | execute | 2 |
|
|
false |
|
|
Purpose: Plan 01 added the data model and rendering. This plan makes it interactive: clicking arrows changes pages, the page persists across sessions, and completing a lesson navigates to the correct page.
Output: Working multi-forest navigation, persisted page state, correct reward-to-forest flow.
<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/05-multi-wald-system-wald-pagination-und-navigation-zwischen-w-ldern/05-CONTEXT.md @.planning/phases/05-multi-wald-system-wald-pagination-und-navigation-zwischen-w-ldern/05-01-SUMMARY.mdFrom src/types.ts (after Plan 01):
export interface Progress {
// ... existing fields ...
currentForestPage: number; // 0-indexed, default 0
}
From src/forest/scene.ts (after Plan 01):
export const SLOTS_PER_PAGE = 12;
export async function renderForestScene(db: IDBDatabase, page: number, newElementId?: number): Promise<void>;
export async function initForestScreen(db: IDBDatabase, onStartLesson: (level: number) => void): Promise<void>;
From src/storage/db.ts (unchanged):
export function getProgress(db: IDBDatabase): Promise<Progress | null>;
export function saveProgress(db: IDBDatabase, progress: Progress): Promise<void>;
export function getForestElements(db: IDBDatabase): Promise<ForestElement[]>;
From src/app.ts:
function migrateProgress(progress): void; // adds currentForestPage if missing
async function handleLessonComplete(completedLevel, stats): Promise<void>;
// calls initRewardScreen which returns elementId
// "Zurueck zum Wald" callback: initForestScreen + renderForestScene + showScreen
-
Import
saveProgressfrom../storage/db(add to existing import). -
Read
progress.currentForestPage(with fallback to 0) and use it as the initial page for rendering:
const page = progress.currentForestPage ?? 0;
await renderForestScene(db, page);
- After the
renderLevelMapcall, wire up navigation buttons per D-05:
const prevBtn = document.getElementById('forest-nav-prev') as HTMLButtonElement;
const nextBtn = document.getElementById('forest-nav-next') as HTMLButtonElement;
let currentPage = progress.currentForestPage ?? 0;
const navigateToPage = async (newPage: number) => {
currentPage = newPage;
await renderForestScene(db, currentPage);
// Persist page in progress per D-05
const freshProgress = await getProgress(db);
if (freshProgress) {
freshProgress.currentForestPage = currentPage;
await saveProgress(db, freshProgress);
}
};
if (prevBtn) {
prevBtn.onclick = () => {
if (currentPage > 0) navigateToPage(currentPage - 1);
};
}
if (nextBtn) {
nextBtn.onclick = async () => {
const elements = await getForestElements(db);
const totalPages = Math.max(1, Math.ceil(elements.length / SLOTS_PER_PAGE));
if (currentPage < totalPages - 1) navigateToPage(currentPage + 1);
};
}
-
Update all existing calls to
renderForestScenewithin this file to pass the page parameter. TheinitForestScreencall becomesrenderForestScene(db, page)(already done above). -
Add a CSS transition for the grid on page change. In
renderForestScene, before clearinggrid.innerHTML, add:
grid.style.opacity = '0';
grid.style.transition = 'opacity 0.3s ease';
And after the rendering loop completes:
// Trigger fade-in after a frame
requestAnimationFrame(() => {
grid.style.opacity = '1';
});
- Import
SLOTS_PER_PAGEfrom./scene:
import { SLOTS_PER_PAGE } from "./scene";
- Replace the slotIndex calculation (currently
const slotIndex = existing.length % 12):
const slotIndex = existing.length % SLOTS_PER_PAGE;
This ensures the element is placed in the correct grid position on its page.
src/app.ts — Update ALL renderForestScene and initForestScreen call sites per D-06:
- In
handleLessonComplete, the "Zurueck zum Wald" callback (theonBackToForestlambda around line 122-125):
async () => {
// Per D-06: navigate to page containing the new element
const elements = await getForestElements(db);
const newPage = Math.max(0, Math.ceil(elements.length / SLOTS_PER_PAGE) - 1);
// Update progress with new page
const latestProgress = await getProgress(db);
if (latestProgress) {
latestProgress.currentForestPage = newPage;
await saveProgress(db, latestProgress);
}
await initForestScreen(db, startLessonFromForest);
await renderForestScene(db, newPage, elementId);
showScreen("forest");
}
-
Import
SLOTS_PER_PAGEfrom./forest/sceneandgetForestElementsfrom./storage/db(add to existing imports if not already there). -
In the "Weiter ueben" callback from reward (the
onContinuelambda), no forest rendering happens so no change needed. -
In
handleLessonCancel(line 129-132),initForestScreenalready readscurrentForestPagefrom progress internally, so no change needed here. -
In
initAppreturning user flow (line 208),initForestScreenalready handles page from progress, but the subsequentrenderForestScenecall does not exist separately —initForestScreencalls it. No change needed. -
In the "Zurueck zum Wald" from parent area (line 182-183), same —
initForestScreenhandles it. -
BUT: There is an explicit
renderForestScene(db, elementId)call on line 123. This must becomerenderForestScene(db, newPage, elementId)as described in step 1 above. cd /home/dev/workspace/zauberwald && npx tsc --noEmit 2>&1 | head -20 && grep -n "SLOTS_PER_PAGE" src/forest/reward.ts src/app.ts <acceptance_criteria>- src/forest/reward.ts contains
import { SLOTS_PER_PAGE } from "./scene" - src/forest/reward.ts contains
existing.length % SLOTS_PER_PAGE - src/app.ts contains
SLOTS_PER_PAGEimport - src/app.ts contains
currentForestPage = newPage - src/app.ts does NOT contain
renderForestScene(db, elementId)(old 2-arg call with elementId) - TypeScript compiles without errors </acceptance_criteria> Reward flow correctly calculates slot position for paginated grid, "Zurueck zum Wald" navigates to the page containing the new element, all renderForestScene calls pass page parameter
- src/forest/reward.ts contains
What was built: Arrow navigation between forest pages, page persistence in Progress, correct page navigation after lesson completion, fade animation on page transitions.
How to verify:
- Open http://localhost:5173 in browser
- If fresh install: complete onboarding, play through at least 1 lesson to get forest elements
- On the forest screen: if you have fewer than 13 elements, the navigation arrows should be HIDDEN
- To test pagination with many elements: Use browser DevTools console to add fake elements to IndexedDB, OR play through enough lessons to fill 12+ slots
- With 13+ elements: navigation arrows ("Wald 1 von 2") should appear between the forest scene and level map
- Click right arrow — should fade to page 2 showing element 13+
- Click left arrow — should fade back to page 1
- Left arrow should be disabled on page 1, right arrow disabled on last page
- Reload browser — same page should be shown (persistence)
- Complete a lesson — after clicking "Zurueck zum Wald", should show the page with the new element (last page)
Resume signal: Type "approved" or describe issues. User confirms visual and functional correctness of multi-forest navigation User approves that forest pagination, navigation arrows, page persistence, and post-lesson page selection all work correctly
- `npx tsc --noEmit` passes - `npm run dev` starts without errors - Navigation arrows hidden when <= 12 elements - Navigation arrows visible when > 12 elements - Page persists in IndexedDB across reloads - New element after lesson appears on correct page<success_criteria>
- Clicking prev/next arrows changes forest page with fade animation
- "Wald X von Y" text updates correctly
- Arrows disabled at boundaries (prev on page 1, next on last page)
- currentForestPage persisted in Progress and restored on reload
- After lesson completion, forest shows the page containing the new element
- No console errors during normal navigation </success_criteria>