Files
Zauberwald/.planning/phases/01-grundger-st-tippmechanik/01-05-PLAN.md
T

13 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
01-grundger-st-tippmechanik 05 execute 4
01-02
01-04
src/ui/screens.ts
src/forest/scene.ts
index.html
src/styles/main.css
src/app.ts
false
FRST-04
FRST-05
truths artifacts key_links
Wald-Uebersicht zeigt Stufenkarte mit Status locked/current/completed
Weiter-ueben-Button startet die naechste offene Stufe
Nach Lesson-Abschluss kehrt die App zur Wald-Uebersicht zurueck und zeigt aktualisierten Status
Gesamter Flow funktioniert: Welcome -> Forest -> Lesson -> Forest (mit Fortschritt)
path provides exports
src/forest/scene.ts Forest overview with level map
initForestScreen
renderLevelMap
from to via pattern
src/forest/scene.ts src/storage/db.ts loads progress to determine level statuses getProgress
from to via pattern
src/forest/scene.ts src/game/levels.ts reads level definitions for the map import.*levels
from to via pattern
src/forest/scene.ts src/app.ts calls startLesson when user clicks a level or continue button startLesson|navigateTo
Build the forest overview screen with the level map (Stufenkarte) showing locked/current/completed states, and wire together the complete app flow: welcome -> forest -> lesson -> forest.

Purpose: This is the final integration plan that connects all pieces into a playable app. The user can see their progress and start lessons from the forest screen. Output: Complete playable Phase 1 app with the core loop working end-to-end.

<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/phases/01-grundger-st-tippmechanik/01-CONTEXT.md @.planning/phases/01-grundger-st-tippmechanik/01-01-SUMMARY.md @.planning/phases/01-grundger-st-tippmechanik/01-02-SUMMARY.md @.planning/phases/01-grundger-st-tippmechanik/01-03-SUMMARY.md @.planning/phases/01-grundger-st-tippmechanik/01-04-SUMMARY.md @SPEC.md (section 7.1 for screen structure) From src/types.ts: ```typescript export type LevelStatus = 'locked' | 'current' | 'completed'; export type ScreenName = 'welcome' | 'forest' | 'lesson' | 'reward' | 'parent'; export interface Progress { id: 1; currentLevel: number; completedLevels: number[]; totalSessions: number; sessionDates: string[]; selectedCharacter: CompanionType; selectedLayout: KeyboardLayout; } ```

From src/game/levels.ts:

export const levels: Level[];

From src/app.ts:

export function showScreen(name: ScreenName): void;
export function getDB(): IDBDatabase;

From src/storage/db.ts:

export async function getProgress(db: IDBDatabase): Promise<Progress | null>;
Task 1: Forest screen with level map and continue button src/forest/scene.ts, index.html, src/styles/main.css src/types.ts src/game/levels.ts src/storage/db.ts src/app.ts src/ui/screens.ts index.html src/styles/main.css 1. Update index.html — populate forest screen: ```html

Dein Zauberwald

Weiter ueben
```
2. Create src/forest/scene.ts:
```typescript
import type { Progress, LevelStatus, ScreenName } 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 statusEmoji = status === 'completed' ? '✓' : status === 'current' ? '→' : '🔒';
    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">${statusEmoji}</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);
}
```

3. Update src/app.ts to wire the complete flow:
- Import `initForestScreen` from `./forest/scene`
- Import `initLessonScreen` from `./ui/screens`
- In `initApp()`: after checking progress, if user exists, call `initForestScreen(db, startLesson)` before showing forest screen
- `startLesson(level)` function: show lesson screen, call initLessonScreen with onComplete callback
- `onComplete` callback: update progress (add to completedLevels, increment currentLevel if applicable, increment totalSessions, add today's date), save to DB, re-init forest screen, show forest screen
- After welcome screen's "Los geht's" navigates to forest: also call initForestScreen

The full flow is:
- First visit: Welcome -> select companion/layout -> "Los geht's" -> Forest (level 1 = current)
- Click "Weiter ueben" or level 1 card -> Lesson screen (type letters)
- Complete lesson -> Forest (level 1 = completed, level 2 = current)
- Reload -> Forest (skips welcome, shows current state)

4. Add CSS for forest and level map to src/styles/main.css:
```css
.forest {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 2rem;
  min-height: 100vh;
  background: var(--bg-forest);
}

.forest__title {
  font-family: 'Quicksand', sans-serif;
  font-size: 2rem;
  color: var(--text-dark);
  margin-bottom: 1.5rem;
}

.forest__level-map {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  max-width: 500px;
  width: 100%;
  margin-bottom: 2rem;
}

.level-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  padding: 1rem;
  border-radius: 12px;
  border: 2px solid transparent;
  font-family: 'Nunito', sans-serif;
  cursor: pointer;
  transition: transform 0.2s ease, border-color 0.2s ease;
  background: white;
}

.level-card:hover:not(:disabled) {
  transform: scale(1.05);
}

.level-card--current {
  border-color: var(--accent-gold);
  background: #FFF8E0;
  box-shadow: 0 2px 8px rgba(232, 184, 75, 0.3);
}

.level-card--completed {
  border-color: var(--accent-green);
  background: #E8F5E4;
}

.level-card--locked {
  opacity: 0.5;
  cursor: not-allowed;
  background: #f0f0f0;
}

.level-card__number {
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--text-dark);
}

.level-card__keys {
  font-family: 'Quicksand', sans-serif;
  font-weight: 600;
  font-size: 1.1rem;
  color: var(--accent-purple);
}

.level-card__status {
  font-size: 1.2rem;
}

.forest__continue-btn {
  padding: 1rem 3rem;
  border-radius: 12px;
  background: var(--accent-green);
  color: white;
  border: none;
  font-family: 'Quicksand', sans-serif;
  font-weight: 700;
  font-size: 1.3rem;
  cursor: pointer;
  transition: transform 0.2s ease;
}

.forest__continue-btn:hover {
  transform: scale(1.05);
}
```
cd /home/dev/workspace/zauberwald && npx tsc --noEmit && npx vitest run - src/forest/scene.ts exports `initForestScreen`, `renderLevelMap`, `getLevelStatus` - src/forest/scene.ts contains `getLevelStatus` returning 'completed', 'current', or 'locked' - src/forest/scene.ts creates 6 level cards with class `level-card` - src/forest/scene.ts contains `level-card--${status}` for dynamic CSS class - index.html contains `id="level-map"` and `id="continue-btn"` - src/app.ts calls `initForestScreen` and `initLessonScreen` in the correct flow - src/app.ts has lesson completion handler that calls `saveProgress` with updated `completedLevels` and `currentLevel` - src/styles/main.css contains `.level-card--current`, `.level-card--completed`, `.level-card--locked` - src/styles/main.css contains `.forest__continue-btn` - `npx tsc --noEmit` exits 0 - `npx vitest run` exits 0 Forest screen shows 6-level map with correct statuses, continue button starts current level, level cards are clickable for completed/current levels, complete app flow works end-to-end Task 2: Verify complete Phase 1 app flow no files modified (verification only) Human verifies the complete Phase 1 app flow in the browser. No code changes in this task.
Open the app at http://vps-ip:5173 and verify these 7 steps:

1. Welcome screen: 4 companion cards with emojis and DE/CH toggle visible. Select a companion, click "Los geht's".
2. Forest overview: Level map shows Stufe 1 as current (gold border), Stufen 2-6 as locked (grayed). "Weiter ueben" button visible.
3. Click "Weiter ueben": Lesson screen appears with a large letter (F, J, or space symbol) and QWERTZ keyboard below. Target key pulses on keyboard.
4. Type the shown letter: Letter dissolves, next letter appears. Type all 8-12 letters correctly.
5. After completion: Returns to forest. Stufe 1 now shows checkmark, Stufe 2 is current (gold).
6. Reload the page: Skips welcome, goes directly to forest with preserved state.
7. Wrong key test: During a lesson, press a wrong key — nothing happens to the letter, correct key continues pulsing.
cd /home/dev/workspace/zauberwald && npx tsc --noEmit && npx vitest run && echo "ALL AUTOMATED CHECKS PASS" - All 7 manual verification steps pass in browser - `npx tsc --noEmit` exits 0 - `npx vitest run` exits 0 Human confirmed all 7 verification steps pass: welcome flow, forest map, lesson typing, level progression, persistence across reload, correct error handling - Complete flow: Welcome -> Forest -> Lesson -> Forest works - Level map shows correct statuses after completing a level - Typing exercise handles correct/wrong input per spec - Progress persists across page reloads - Keyboard shows finger colors for learned keys, gray for unlearned - All tests pass: `npx vitest run` - TypeScript compiles: `npx tsc --noEmit`

<success_criteria>

  • Forest overview shows 6 levels with locked/current/completed states
  • "Weiter ueben" button starts the current level's typing exercise
  • After completing a lesson, level status updates correctly
  • Full app loop is playable from fresh start through at least level 1 completion
  • Progress survives browser reload </success_criteria>
After completion, create `.planning/phases/01-grundger-st-tippmechanik/01-05-SUMMARY.md`