feat(05-01): extend Progress type with currentForestPage, add paginated renderForestScene
- Add currentForestPage: number field to Progress interface in types.ts - Export SLOTS_PER_PAGE = 12 constant from scene.ts - Change renderForestScene signature to accept page: number parameter - Slice elements by page (start/end = page * SLOTS_PER_PAGE) - Update navigation UI (forest-nav) after rendering - Add migrateProgress entry for currentForestPage in app.ts - Fix Progress object literals in db.test.ts and screens.ts to include new field
This commit is contained in:
+4
-1
@@ -38,6 +38,7 @@ function migrateProgress(
|
||||
if (!progress.lastPlayedLevels) progress.lastPlayedLevels = [];
|
||||
if (progress.totalCorrect === undefined) progress.totalCorrect = 0;
|
||||
if (progress.totalErrors === undefined) progress.totalErrors = 0;
|
||||
if (progress.currentForestPage === undefined) progress.currentForestPage = 0;
|
||||
}
|
||||
|
||||
async function handleLessonComplete(
|
||||
@@ -120,7 +121,9 @@ async function handleLessonComplete(
|
||||
async () => {
|
||||
// "Zurück zum Wald" -- show forest with new element animated
|
||||
await initForestScreen(db, startLessonFromForest);
|
||||
await renderForestScene(db, elementId);
|
||||
const prog = await getProgress(db);
|
||||
const page = prog?.currentForestPage ?? 0;
|
||||
await renderForestScene(db, page, elementId);
|
||||
showScreen("forest");
|
||||
},
|
||||
);
|
||||
|
||||
+31
-4
@@ -5,8 +5,11 @@ import { playForestElementSound } from "../audio/sounds";
|
||||
|
||||
let activeObjectUrls: string[] = [];
|
||||
|
||||
export const SLOTS_PER_PAGE = 12;
|
||||
|
||||
export async function renderForestScene(
|
||||
db: IDBDatabase,
|
||||
page: number,
|
||||
newElementId?: number,
|
||||
): Promise<void> {
|
||||
const grid = document.getElementById("forest-grid");
|
||||
@@ -21,9 +24,10 @@ export async function renderForestScene(
|
||||
const elements = await getForestElements(db);
|
||||
grid.innerHTML = "";
|
||||
|
||||
// Render up to 12 elements (4x3 grid)
|
||||
const maxSlots = 12;
|
||||
const toRender = elements.slice(0, maxSlots);
|
||||
// Render elements for the given page (4x3 grid per page)
|
||||
const start = page * SLOTS_PER_PAGE;
|
||||
const end = start + SLOTS_PER_PAGE;
|
||||
const toRender = elements.slice(start, end);
|
||||
|
||||
for (const element of toRender) {
|
||||
const slot = document.createElement("div");
|
||||
@@ -51,6 +55,28 @@ export async function renderForestScene(
|
||||
slot.appendChild(img);
|
||||
grid.appendChild(slot);
|
||||
}
|
||||
|
||||
// Update 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 function getLevelStatus(
|
||||
@@ -113,7 +139,8 @@ export async function initForestScreen(
|
||||
if (!progress) return;
|
||||
|
||||
renderLevelMap(mapContainer, progress, onStartLesson);
|
||||
await renderForestScene(db);
|
||||
const currentPage = progress.currentForestPage ?? 0;
|
||||
await renderForestScene(db, currentPage);
|
||||
|
||||
const allComplete = levels.every((l) =>
|
||||
progress.completedLevels.includes(l.level),
|
||||
|
||||
@@ -37,6 +37,7 @@ describe("IndexedDB wrapper", () => {
|
||||
totalErrors: 0,
|
||||
errorKeyCounts: {},
|
||||
lastPlayedLevels: [],
|
||||
currentForestPage: 0,
|
||||
};
|
||||
await saveProgress(db, progress);
|
||||
const result = await getProgress(db);
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface Progress {
|
||||
totalErrors: number;
|
||||
errorKeyCounts: Record<string, number>;
|
||||
lastPlayedLevels: number[]; // last 3 played levels for review mechanic
|
||||
currentForestPage: number; // 0-indexed, default 0
|
||||
}
|
||||
|
||||
export type LessonPhase = "discover" | "practice" | "words";
|
||||
|
||||
@@ -83,6 +83,7 @@ export function initWelcomeScreen(
|
||||
totalErrors: 0,
|
||||
errorKeyCounts: {},
|
||||
lastPlayedLevels: [],
|
||||
currentForestPage: 0,
|
||||
};
|
||||
await saveProgress(db, progress);
|
||||
navigateTo("forest");
|
||||
|
||||
Reference in New Issue
Block a user