13 KiB
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 | 02 | execute | 2 |
|
|
true |
|
|
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.
<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/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:
export function openDB(): Promise<IDBDatabase>;
export async function getProgress(db: IDBDatabase): Promise<Progress | null>;
export async function saveProgress(db: IDBDatabase, progress: Progress): Promise<void>;
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<void> {
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);
```
Willkommen im Zauberwald!
Waehle deine Begleitfigur:
Tastatur-Layout:
DE
CH
Los geht's!
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 = `
<span class="companion-card__emoji">${c.emoji}</span>
<span class="companion-card__name">${c.name}</span>
`;
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
<success_criteria>
- 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 </success_criteria>