Files
T

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
05-01
src/forest/scene.ts
src/forest/reward.ts
src/app.ts
false
MWLD-05
MWLD-06
MWLD-07
truths artifacts key_links
Kind kann mit Pfeiltasten zwischen Waldseiten navigieren
Aktuelle Waldseite wird in Progress gespeichert und nach Reload wiederhergestellt
Nach Lesson-Abschluss zeigt der Wald automatisch die Seite mit dem neuen Element
Seitenwechsel hat sanfte Fade-Animation
path provides contains
src/forest/scene.ts Navigation event handlers, page persistence forest-nav-prev
path provides contains
src/forest/reward.ts Correct slot index for paginated forest SLOTS_PER_PAGE
path provides contains
src/app.ts Forest init with correct page, post-reward navigation currentForestPage
from to via pattern
src/forest/scene.ts src/storage/db.ts saveProgress for page persistence saveProgress
from to via pattern
src/forest/reward.ts src/forest/scene.ts SLOTS_PER_PAGE import for slot calculation SLOTS_PER_PAGE
from to via pattern
src/app.ts src/forest/scene.ts renderForestScene with page parameter renderForestScene.*db.*page
Wire navigation interactions, persist current page, and fix reward flow for paginated forest.

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.md

From 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
Task 1: Wire navigation handlers and page persistence in initForestScreen src/forest/scene.ts - src/forest/scene.ts (current initForestScreen — must add nav button handlers) - src/storage/db.ts (saveProgress pattern) - src/types.ts (Progress with currentForestPage) **src/forest/scene.ts** — Modify `initForestScreen` to:
  1. Import saveProgress from ../storage/db (add to existing import).

  2. 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);
  1. After the renderLevelMap call, 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);
  };
}
  1. Update all existing calls to renderForestScene within this file to pass the page parameter. The initForestScreen call becomes renderForestScene(db, page) (already done above).

  2. Add a CSS transition for the grid on page change. In renderForestScene, before clearing grid.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';
});
cd /home/dev/workspace/zauberwald && npx tsc --noEmit 2>&1 | head -20 - src/forest/scene.ts contains `saveProgress` in import statement - src/forest/scene.ts contains `currentForestPage` - src/forest/scene.ts contains `prevBtn.onclick` - src/forest/scene.ts contains `nextBtn.onclick` - src/forest/scene.ts contains `navigateToPage` - src/forest/scene.ts contains `grid.style.opacity` - TypeScript compiles without errors Arrow buttons navigate between forest pages, current page saved to Progress on every navigation, fade animation on page transitions Task 2: Fix reward flow and all renderForestScene call sites for pagination src/forest/reward.ts, src/app.ts - src/forest/reward.ts (slotIndex calculation at line 179 — must account for pagination) - src/app.ts (all renderForestScene calls — must pass page parameter; handleLessonComplete "Zurueck zum Wald" callback) - src/forest/scene.ts (new renderForestScene signature with page parameter) **src/forest/reward.ts** — Per D-01, fix the slotIndex calculation to work with pagination:
  1. Import SLOTS_PER_PAGE from ./scene:
import { SLOTS_PER_PAGE } from "./scene";
  1. 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:

  1. In handleLessonComplete, the "Zurueck zum Wald" callback (the onBackToForest lambda 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");
}
  1. Import SLOTS_PER_PAGE from ./forest/scene and getForestElements from ./storage/db (add to existing imports if not already there).

  2. In the "Weiter ueben" callback from reward (the onContinue lambda), no forest rendering happens so no change needed.

  3. In handleLessonCancel (line 129-132), initForestScreen already reads currentForestPage from progress internally, so no change needed here.

  4. In initApp returning user flow (line 208), initForestScreen already handles page from progress, but the subsequent renderForestScene call does not exist separately — initForestScreen calls it. No change needed.

  5. In the "Zurueck zum Wald" from parent area (line 182-183), same — initForestScreen handles it.

  6. BUT: There is an explicit renderForestScene(db, elementId) call on line 123. This must become renderForestScene(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_PAGE import
    • 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
Task 3: Verify multi-forest navigation works end-to-end n/a Human verification checkpoint for the multi-forest pagination system.

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:

  1. Open http://localhost:5173 in browser
  2. If fresh install: complete onboarding, play through at least 1 lesson to get forest elements
  3. On the forest screen: if you have fewer than 13 elements, the navigation arrows should be HIDDEN
  4. 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
  5. With 13+ elements: navigation arrows ("Wald 1 von 2") should appear between the forest scene and level map
  6. Click right arrow — should fade to page 2 showing element 13+
  7. Click left arrow — should fade back to page 1
  8. Left arrow should be disabled on page 1, right arrow disabled on last page
  9. Reload browser — same page should be shown (persistence)
  10. 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>
After completion, create `.planning/phases/05-multi-wald-system-wald-pagination-und-navigation-zwischen-w-ldern/05-02-SUMMARY.md`