feat(01-05): forest screen with level map and complete app flow

- Add forest overview screen with 6-level map showing locked/current/completed states
- Create src/forest/scene.ts with getLevelStatus, renderLevelMap, initForestScreen
- Wire complete flow: welcome -> forest -> lesson -> forest with progress updates
- Add forest CSS with level card styles and continue button

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-29 11:15:18 +02:00
co-authored by Claude Opus 4.6
parent d04e09a5a3
commit 5bac8501bf
4 changed files with 225 additions and 37 deletions
+66
View File
@@ -0,0 +1,66 @@
import type { Progress, LevelStatus } from "../types";
import { levels } from "../game/levels";
import { getProgress } from "../storage/db";
export function getLevelStatus(
levelNum: number,
progress: Progress,
): LevelStatus {
if (progress.completedLevels.includes(levelNum)) return "completed";
if (levelNum === progress.currentLevel) return "current";
return "locked";
}
export function renderLevelMap(
container: HTMLElement,
progress: Progress,
onLevelClick: (level: number) => void,
): void {
container.innerHTML = "";
levels.forEach((level) => {
const status = getLevelStatus(level.level, progress);
const card = document.createElement("button");
card.className = `level-card level-card--${status}`;
card.dataset.level = String(level.level);
const statusIcon =
status === "completed" ? "\u2713" : status === "current" ? "\u2192" : "\uD83D\uDD12";
const keysDisplay = level.newKeys
.filter((k) => k !== " ")
.map((k) => k.toUpperCase())
.join(" ");
card.innerHTML = `
<span class="level-card__number">Stufe ${level.level}</span>
<span class="level-card__keys">${keysDisplay}${level.newKeys.includes(" ") ? " + Leertaste" : ""}</span>
<span class="level-card__status">${statusIcon}</span>
`;
// Only current and completed levels are clickable
if (status !== "locked") {
card.addEventListener("click", () => onLevelClick(level.level));
} else {
card.disabled = true;
}
container.appendChild(card);
});
}
export async function initForestScreen(
db: IDBDatabase,
onStartLesson: (level: number) => void,
): Promise<void> {
const mapContainer = document.getElementById("level-map")!;
const continueBtn = document.getElementById(
"continue-btn",
) as HTMLButtonElement;
const progress = await getProgress(db);
if (!progress) return;
renderLevelMap(mapContainer, progress, onStartLesson);
// Continue button starts the current level
continueBtn.onclick = () => onStartLesson(progress.currentLevel);
}