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.lastPlayedLevels) progress.lastPlayedLevels = [];
|
||||||
if (progress.totalCorrect === undefined) progress.totalCorrect = 0;
|
if (progress.totalCorrect === undefined) progress.totalCorrect = 0;
|
||||||
if (progress.totalErrors === undefined) progress.totalErrors = 0;
|
if (progress.totalErrors === undefined) progress.totalErrors = 0;
|
||||||
|
if (progress.currentForestPage === undefined) progress.currentForestPage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleLessonComplete(
|
async function handleLessonComplete(
|
||||||
@@ -120,7 +121,9 @@ async function handleLessonComplete(
|
|||||||
async () => {
|
async () => {
|
||||||
// "Zurück zum Wald" -- show forest with new element animated
|
// "Zurück zum Wald" -- show forest with new element animated
|
||||||
await initForestScreen(db, startLessonFromForest);
|
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");
|
showScreen("forest");
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
+31
-4
@@ -5,8 +5,11 @@ import { playForestElementSound } from "../audio/sounds";
|
|||||||
|
|
||||||
let activeObjectUrls: string[] = [];
|
let activeObjectUrls: string[] = [];
|
||||||
|
|
||||||
|
export const SLOTS_PER_PAGE = 12;
|
||||||
|
|
||||||
export async function renderForestScene(
|
export async function renderForestScene(
|
||||||
db: IDBDatabase,
|
db: IDBDatabase,
|
||||||
|
page: number,
|
||||||
newElementId?: number,
|
newElementId?: number,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const grid = document.getElementById("forest-grid");
|
const grid = document.getElementById("forest-grid");
|
||||||
@@ -21,9 +24,10 @@ export async function renderForestScene(
|
|||||||
const elements = await getForestElements(db);
|
const elements = await getForestElements(db);
|
||||||
grid.innerHTML = "";
|
grid.innerHTML = "";
|
||||||
|
|
||||||
// Render up to 12 elements (4x3 grid)
|
// Render elements for the given page (4x3 grid per page)
|
||||||
const maxSlots = 12;
|
const start = page * SLOTS_PER_PAGE;
|
||||||
const toRender = elements.slice(0, maxSlots);
|
const end = start + SLOTS_PER_PAGE;
|
||||||
|
const toRender = elements.slice(start, end);
|
||||||
|
|
||||||
for (const element of toRender) {
|
for (const element of toRender) {
|
||||||
const slot = document.createElement("div");
|
const slot = document.createElement("div");
|
||||||
@@ -51,6 +55,28 @@ export async function renderForestScene(
|
|||||||
slot.appendChild(img);
|
slot.appendChild(img);
|
||||||
grid.appendChild(slot);
|
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(
|
export function getLevelStatus(
|
||||||
@@ -113,7 +139,8 @@ export async function initForestScreen(
|
|||||||
if (!progress) return;
|
if (!progress) return;
|
||||||
|
|
||||||
renderLevelMap(mapContainer, progress, onStartLesson);
|
renderLevelMap(mapContainer, progress, onStartLesson);
|
||||||
await renderForestScene(db);
|
const currentPage = progress.currentForestPage ?? 0;
|
||||||
|
await renderForestScene(db, currentPage);
|
||||||
|
|
||||||
const allComplete = levels.every((l) =>
|
const allComplete = levels.every((l) =>
|
||||||
progress.completedLevels.includes(l.level),
|
progress.completedLevels.includes(l.level),
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ describe("IndexedDB wrapper", () => {
|
|||||||
totalErrors: 0,
|
totalErrors: 0,
|
||||||
errorKeyCounts: {},
|
errorKeyCounts: {},
|
||||||
lastPlayedLevels: [],
|
lastPlayedLevels: [],
|
||||||
|
currentForestPage: 0,
|
||||||
};
|
};
|
||||||
await saveProgress(db, progress);
|
await saveProgress(db, progress);
|
||||||
const result = await getProgress(db);
|
const result = await getProgress(db);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export interface Progress {
|
|||||||
totalErrors: number;
|
totalErrors: number;
|
||||||
errorKeyCounts: Record<string, number>;
|
errorKeyCounts: Record<string, number>;
|
||||||
lastPlayedLevels: number[]; // last 3 played levels for review mechanic
|
lastPlayedLevels: number[]; // last 3 played levels for review mechanic
|
||||||
|
currentForestPage: number; // 0-indexed, default 0
|
||||||
}
|
}
|
||||||
|
|
||||||
export type LessonPhase = "discover" | "practice" | "words";
|
export type LessonPhase = "discover" | "practice" | "words";
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ export function initWelcomeScreen(
|
|||||||
totalErrors: 0,
|
totalErrors: 0,
|
||||||
errorKeyCounts: {},
|
errorKeyCounts: {},
|
||||||
lastPlayedLevels: [],
|
lastPlayedLevels: [],
|
||||||
|
currentForestPage: 0,
|
||||||
};
|
};
|
||||||
await saveProgress(db, progress);
|
await saveProgress(db, progress);
|
||||||
navigateTo("forest");
|
navigateTo("forest");
|
||||||
|
|||||||
Reference in New Issue
Block a user