--- phase: 01-grundger-st-tippmechanik plan: 02 type: execute wave: 2 depends_on: ["01-01"] files_modified: - src/app.ts - src/ui/screens.ts - src/companion/characters.ts - index.html autonomous: true requirements: - FNDN-05 - ONBD-01 - ONBD-02 - ONBD-03 - ONBD-04 must_haves: truths: - "App startet und zeigt den Willkommens-Screen" - "4 Begleitfigur-Karten sind klickbar und zeigen Emoji + Name" - "DE/CH Layout-Toggle ist waehlbar" - "Nach Auswahl + Los gehts wechselt die App zur Wald-Uebersicht" - "Nach Browser-Reload bleibt die Auswahl erhalten und Willkommens-Screen wird uebersprungen" artifacts: - path: "src/app.ts" provides: "Screen management and routing" exports: ["showScreen", "initApp"] - path: "src/ui/screens.ts" provides: "Welcome screen logic and companion selection" exports: ["initWelcomeScreen"] - path: "src/companion/characters.ts" provides: "Companion definitions (name, emoji, personality)" exports: ["companions", "CompanionDefinition"] key_links: - from: "src/app.ts" to: "src/storage/db.ts" via: "checks progress on init to skip welcome" pattern: "getProgress" - from: "src/ui/screens.ts" to: "src/storage/db.ts" via: "saves companion + layout choice" pattern: "saveProgress" - from: "src/main.ts" to: "src/app.ts" via: "calls initApp() on DOMContentLoaded" pattern: "initApp" --- Implement screen management (CSS fade transitions between 5 screens) and the complete onboarding flow: companion selection, layout selection, persistence, and navigation to forest. Purpose: The user must be able to start the app, choose a companion and layout, and reach the forest overview. This is the entry point for all subsequent gameplay. Output: Working welcome-to-forest flow with IndexedDB persistence. @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/01-grundger-st-tippmechanik/01-CONTEXT.md @.planning/phases/01-grundger-st-tippmechanik/01-01-SUMMARY.md @SPEC.md (sections 5.2, 7.1, 7.2) From src/types.ts: ```typescript export type CompanionType = 'fee' | 'einhorn' | 'fuchs' | 'eule'; export type KeyboardLayout = 'de' | 'ch'; 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/storage/db.ts: ```typescript export function openDB(): Promise; export async function getProgress(db: IDBDatabase): Promise; export async function saveProgress(db: IDBDatabase, progress: Progress): Promise; ``` Task 1: Screen management + companion definitions src/app.ts, src/companion/characters.ts src/types.ts src/storage/db.ts src/styles/main.css index.html SPEC.md (section 5.2 for companion definitions, section 7.1 for screen list) 1. Create src/companion/characters.ts with companion definitions (per D-05, emoji placeholders): ```typescript import type { CompanionType } from '../types'; export interface CompanionDefinition { type: CompanionType; name: string; emoji: string; personality: string; } export const companions: CompanionDefinition[] = [ { type: 'fee', name: 'Lila', emoji: '🧚', personality: 'Sanft, ermutigend, ein bisschen vertraeumt' }, { type: 'einhorn', name: 'Stella', emoji: '🦄', personality: 'Froehlich, enthusiastisch, feiert jeden kleinen Erfolg' }, { type: 'fuchs', name: 'Finn', emoji: '🦊', personality: 'Ruhig, weise, humorvoll' }, { type: 'eule', name: 'Elsa', emoji: '🦉', personality: 'Geduldig, warm, grossmuetterlich' }, ]; ``` 2. Create src/app.ts with screen management (per D-01): ```typescript import type { ScreenName } from './types'; import { openDB, getProgress } from './storage/db'; import { initWelcomeScreen } from './ui/screens'; let db: IDBDatabase; export function showScreen(name: ScreenName): void { document.querySelectorAll('.screen').forEach(el => { el.classList.remove('screen--active'); }); const target = document.getElementById(`screen-${name}`); if (target) { target.classList.add('screen--active'); } } export function getDB(): IDBDatabase { return db; } export async function initApp(): Promise { db = await openDB(); const progress = await getProgress(db); if (progress && progress.selectedCharacter) { // Returning user — skip welcome, go to forest showScreen('forest'); } else { // First time — show welcome initWelcomeScreen(db, showScreen); showScreen('welcome'); } } ``` 3. Update src/main.ts to call initApp: ```typescript import './styles/main.css'; import { initApp } from './app'; document.addEventListener('DOMContentLoaded', initApp); ``` cd /home/dev/workspace/zauberwald && npx tsc --noEmit - src/companion/characters.ts exports `companions` array with 4 entries (fee, einhorn, fuchs, eule) - src/companion/characters.ts contains emoji strings: '🧚', '🦄', '🦊', '🦉' - src/app.ts exports `showScreen` and `initApp` - src/app.ts imports from `./storage/db` and `./ui/screens` - src/app.ts contains logic: if progress exists -> showScreen('forest'), else showScreen('welcome') - src/main.ts contains `import { initApp } from './app'` and `initApp` - `npx tsc --noEmit` exits 0 Screen transitions work via CSS class toggling, companion data defined, app routes to welcome or forest based on saved progress Task 2: Welcome screen UI + onboarding flow src/ui/screens.ts, index.html, src/styles/main.css src/app.ts src/companion/characters.ts src/types.ts src/storage/db.ts src/styles/main.css index.html 1. Update index.html — populate the welcome screen section with: ```html Willkommen im Zauberwald! Waehle deine Begleitfigur: Tastatur-Layout: DE CH Los geht's! ``` Keep the other 4 screen sections empty (just the section tag). 2. Create src/ui/screens.ts: ```typescript import type { CompanionType, KeyboardLayout, ScreenName, Progress } from '../types'; import { companions } from '../companion/characters'; import { saveProgress } from '../storage/db'; export function initWelcomeScreen( db: IDBDatabase, navigateTo: (screen: ScreenName) => void ): void { let selectedCompanion: CompanionType | null = null; let selectedLayout: KeyboardLayout = 'de'; const grid = document.getElementById('companion-grid')!; const startBtn = document.getElementById('start-btn') as HTMLButtonElement; const layoutToggle = document.getElementById('layout-toggle')!; // Render companion cards companions.forEach(c => { const card = document.createElement('button'); card.className = 'companion-card'; card.dataset.companion = c.type; card.innerHTML = ` ${c.emoji} ${c.name} `; card.addEventListener('click', () => { grid.querySelectorAll('.companion-card').forEach(el => el.classList.remove('companion-card--selected') ); card.classList.add('companion-card--selected'); selectedCompanion = c.type; startBtn.disabled = false; }); grid.appendChild(card); }); // Layout toggle layoutToggle.addEventListener('click', (e) => { const btn = (e.target as HTMLElement).closest('.layout-btn') as HTMLButtonElement | null; if (!btn) return; layoutToggle.querySelectorAll('.layout-btn').forEach(el => el.classList.remove('layout-btn--active') ); btn.classList.add('layout-btn--active'); selectedLayout = btn.dataset.layout as KeyboardLayout; }); // Start button startBtn.addEventListener('click', async () => { if (!selectedCompanion) return; const progress: Progress = { id: 1, currentLevel: 1, completedLevels: [], totalSessions: 0, sessionDates: [], selectedCharacter: selectedCompanion, selectedLayout: selectedLayout, }; await saveProgress(db, progress); navigateTo('forest'); }); } ``` 3. Add CSS for welcome screen in src/styles/main.css: - `.welcome` — centered flex column, padding 2rem, max-width 600px, margin auto - `.welcome h1` — font-family Quicksand, font-size 2rem, color var(--text-dark) - `.welcome__companions` / `#companion-grid` — display grid, grid-template-columns repeat(2, 1fr), gap 1rem - `.companion-card` — background white, border 3px solid transparent, border-radius 16px, padding 1.5rem, cursor pointer, transition border-color 0.2s, text-align center, display flex, flex-direction column, align-items center, gap 0.5rem - `.companion-card:hover` — border-color var(--accent-gold) - `.companion-card--selected` — border-color var(--accent-green), background var(--bg-forest) - `.companion-card__emoji` — font-size 3rem - `.companion-card__name` — font-family Quicksand, font-weight 600, font-size 1.2rem, color var(--text-dark) - `.layout-btn` — padding 0.5rem 1.5rem, border-radius 8px, border 2px solid var(--text-light), background white, cursor pointer, font-family Nunito, font-size 1rem - `.layout-btn--active` — background var(--accent-green), color white, border-color var(--accent-green) - `.welcome__start-btn` — margin-top 1.5rem, padding 1rem 3rem, border-radius 12px, background var(--accent-green), color white, border none, font-family Quicksand, font-weight 700, font-size 1.3rem, cursor pointer, opacity 1, transition opacity 0.2s - `.welcome__start-btn:disabled` — opacity 0.4, cursor not-allowed - `.welcome__layout-toggle` — display flex, gap 0.5rem, margin-top 0.5rem cd /home/dev/workspace/zauberwald && npx tsc --noEmit && npm run dev -- --strictPort 2>&1 & sleep 3 && curl -s http://localhost:5173 | grep -q "companion-grid" && kill %1 && echo "PASS" - index.html contains `id="companion-grid"` and `id="start-btn"` and `id="layout-toggle"` - index.html contains `data-layout="de"` and `data-layout="ch"` - src/ui/screens.ts exports `initWelcomeScreen` - src/ui/screens.ts contains `saveProgress(db, progress)` call - src/ui/screens.ts contains `navigateTo('forest')` after save - src/ui/screens.ts creates 4 companion cards with `.companion-card` class - src/styles/main.css contains `.companion-card`, `.companion-card--selected`, `.welcome__start-btn` - src/styles/main.css contains `.layout-btn--active` - `npx tsc --noEmit` exits 0 - Welcome screen renders 4 companion cards and DE/CH toggle in browser Welcome screen shows 4 emoji companion cards, DE/CH layout toggle, and "Los geht's" button. Selecting companion enables start. Clicking start saves to IndexedDB and navigates to forest screen. On reload, app skips welcome and shows forest directly. - App loads and shows welcome screen with 4 companion cards - Clicking a companion highlights it and enables "Los geht's" - DE/CH toggle switches active state - Clicking "Los geht's" transitions to forest screen (empty for now) - Refreshing the page skips welcome and shows forest directly - Clearing IndexedDB and refreshing shows welcome again - Complete onboarding flow: select companion + layout, start, persist, skip on return - Screen transitions use CSS fade (opacity transition) - All companion data matches spec section 5.2 names After completion, create `.planning/phases/01-grundger-st-tippmechanik/01-02-SUMMARY.md`
Waehle deine Begleitfigur:
Tastatur-Layout: