9.7 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 | 01 | execute | 1 |
|
true |
|
|
Purpose: The 4x3 grid (12 slots) fills up as the child completes levels. With 16+ levels, elements overflow. This plan adds the data model and rendering logic to show elements page-by-page.
Output: Progress type with currentForestPage, renderForestScene accepting page parameter and slicing elements, navigation DOM structure in HTML, navigation CSS styling.
<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.mdFrom src/types.ts:
export interface Progress {
id: 1; // singleton row
currentLevel: number;
completedLevels: number[];
totalSessions: number;
sessionDates: string[];
selectedCharacter: CompanionType;
selectedLayout: KeyboardLayout;
totalCorrect: number;
totalErrors: number;
errorKeyCounts: Record<string, number>;
lastPlayedLevels: number[];
}
From src/forest/scene.ts:
export async function renderForestScene(db: IDBDatabase, newElementId?: number): Promise<void>;
export async function initForestScreen(db: IDBDatabase, onStartLesson: (level: number) => void): Promise<void>;
From src/storage/db.ts:
export function getProgress(db: IDBDatabase): Promise<Progress | null>;
export function saveProgress(db: IDBDatabase, progress: Progress): Promise<void>;
export function getForestElements(db: IDBDatabase): Promise<ForestElement[]>;
src/app.ts — In the migrateProgress function, add migration line:
if (progress.currentForestPage === undefined) progress.currentForestPage = 0;
src/forest/scene.ts — Modify renderForestScene signature and implementation per D-01, D-02, D-07, D-08:
-
Change signature to:
renderForestScene(db: IDBDatabase, page: number, newElementId?: number): Promise<void> -
Replace the current slicing logic:
// OLD: const toRender = elements.slice(0, maxSlots);
// NEW per D-01: page index determines slice
const SLOTS_PER_PAGE = 12;
const start = page * SLOTS_PER_PAGE;
const end = start + SLOTS_PER_PAGE;
const toRender = elements.slice(start, end);
-
Keep the rest of the rendering loop unchanged (object URL management, random offset, newElementId animation).
-
After rendering elements, update the navigation UI:
const totalPages = Math.max(1, Math.ceil(elements.length / SLOTS_PER_PAGE));
const navContainer = document.getElementById('forest-nav');
if (navContainer) {
const prevBtn = document.getElementById('forest-nav-prev') as HTMLButtonElement;
const nextBtn = document.getElementById('forest-nav-next') as HTMLButtonElement;
const pageText = document.getElementById('forest-nav-text');
if (totalPages <= 1) {
navContainer.style.display = 'none';
} else {
navContainer.style.display = 'flex';
prevBtn.disabled = page <= 0;
nextBtn.disabled = page >= totalPages - 1;
if (pageText) pageText.textContent = `Wald ${page + 1} von ${totalPages}`;
}
}
Export the constant SLOTS_PER_PAGE = 12 so Plan 02 can import it.
cd /home/dev/workspace/zauberwald && npx tsc --noEmit 2>&1 | head -30
<acceptance_criteria>
- src/types.ts contains currentForestPage: number
- src/forest/scene.ts contains export const SLOTS_PER_PAGE = 12
- src/forest/scene.ts function signature contains page: number
- src/forest/scene.ts contains page * SLOTS_PER_PAGE
- src/forest/scene.ts contains forest-nav
- src/app.ts contains currentForestPage === undefined
- TypeScript compiles without errors (tsc --noEmit exits 0)
</acceptance_criteria>
Progress type extended with currentForestPage, renderForestScene accepts page parameter and slices elements accordingly, navigation UI updated from render function, migrateProgress handles missing field
<div class="forest__nav" id="forest-nav" style="display:none">
<button class="forest__nav-btn forest__nav-btn--prev" id="forest-nav-prev" aria-label="Vorheriger Wald">❮</button>
<span class="forest__nav-text" id="forest-nav-text">Wald 1 von 1</span>
<button class="forest__nav-btn forest__nav-btn--next" id="forest-nav-next" aria-label="Nächster Wald">❯</button>
</div>
src/styles/main.css — Add forest navigation styles after the .forest__element--new animation block (after the @keyframes forest-element-appear block). Per D-04, buttons must be min 44px and pastel-styled:
/* Forest navigation (multi-wald pagination) */
.forest__nav {
display: flex;
align-items: center;
justify-content: center;
gap: 1.5rem;
margin: 1rem 0;
}
.forest__nav-btn {
min-width: 44px;
min-height: 44px;
border: 2px solid var(--accent-green);
border-radius: 50%;
background: var(--bg-cream);
color: var(--accent-green);
font-size: 1.4rem;
font-family: "Quicksand", sans-serif;
font-weight: 700;
cursor: pointer;
transition: background 0.2s, transform 0.2s;
display: flex;
align-items: center;
justify-content: center;
}
.forest__nav-btn:hover:not(:disabled) {
background: var(--bg-forest);
transform: scale(1.1);
}
.forest__nav-btn:disabled {
opacity: 0.3;
cursor: default;
}
.forest__nav-text {
font-family: "Quicksand", sans-serif;
font-size: 1.1rem;
font-weight: 600;
color: var(--text-warm);
}
<success_criteria>
- Progress type has currentForestPage field
- renderForestScene accepts page parameter and renders only 12 elements for that page
- Navigation DOM exists with prev/next buttons and page text
- Navigation hidden when only 1 page of elements
- CSS styling follows existing pastel/BEM conventions with 44px touch targets </success_criteria>