docs(04-polish-audio): create phase plan
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
---
|
||||
phase: 04-polish-audio
|
||||
plan: 03
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- src/ui/parent.ts
|
||||
- index.html
|
||||
- src/styles/main.css
|
||||
- src/storage/db.ts
|
||||
autonomous: true
|
||||
requirements: [PRNT-05, PRNT-06, PRNT-07]
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "Export-Button ladet JSON-Datei mit Progress und Settings herunter (keine Blobs)"
|
||||
- "Import-Button oeffnet Dateiauswahl, validiert JSON, ueberschreibt nach Bestaetigung"
|
||||
- "Reset loescht alle 5 IndexedDB Stores nach doppelter Bestaetigung und reloaded"
|
||||
artifacts:
|
||||
- path: "src/ui/parent.ts"
|
||||
provides: "Export, Import, Reset functions"
|
||||
exports: ["exportData", "importData", "resetAllData"]
|
||||
- path: "index.html"
|
||||
provides: "Daten section in parent screen with Export/Import/Reset buttons"
|
||||
contains: "export-btn"
|
||||
key_links:
|
||||
- from: "src/ui/parent.ts"
|
||||
to: "src/storage/db.ts"
|
||||
via: "getProgress, getSettings for export; saveProgress, saveSettings for import; db.clear for reset"
|
||||
pattern: "getProgress.*getSettings|clear"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Export/Import/Reset im Elternbereich: Fortschritt als JSON exportieren, JSON importieren mit Validierung, alles zuruecksetzen mit doppelter Bestaetigung.
|
||||
|
||||
Purpose: Datensicherung und Reset-Moeglichkeit per D-12 bis D-14 aus CONTEXT.md. Eltern koennen Fortschritt sichern und bei Bedarf wiederherstellen.
|
||||
Output: Daten-Sektion im Parent-Screen mit drei Buttons, Logik in parent.ts.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@$HOME/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/phases/04-polish-audio/04-CONTEXT.md
|
||||
|
||||
@src/ui/parent.ts
|
||||
@src/storage/db.ts
|
||||
@src/types.ts
|
||||
@index.html
|
||||
@src/styles/main.css
|
||||
</context>
|
||||
|
||||
<interfaces>
|
||||
<!-- Key types the executor needs from existing code -->
|
||||
|
||||
From src/types.ts:
|
||||
```typescript
|
||||
export interface Progress {
|
||||
id: 1;
|
||||
currentLevel: number;
|
||||
completedLevels: number[];
|
||||
totalSessions: number;
|
||||
sessionDates: string[];
|
||||
selectedCharacter: CompanionType;
|
||||
selectedLayout: KeyboardLayout;
|
||||
totalCorrect: number;
|
||||
totalErrors: number;
|
||||
errorKeyCounts: Record<string, number>;
|
||||
lastPlayedLevels: number[];
|
||||
}
|
||||
|
||||
export interface Settings {
|
||||
id: 1;
|
||||
audioEnabled: boolean;
|
||||
apiKey: string;
|
||||
apiCallsToday: { text: number; image: number };
|
||||
lastApiCallDate: string;
|
||||
}
|
||||
```
|
||||
|
||||
From src/storage/db.ts:
|
||||
```typescript
|
||||
export function getProgress(db: IDBDatabase): Promise<Progress | null>;
|
||||
export function saveProgress(db: IDBDatabase, progress: Progress): Promise<void>;
|
||||
export function getSettings(db: IDBDatabase): Promise<Settings | null>;
|
||||
export function saveSettings(db: IDBDatabase, settings: Settings): Promise<void>;
|
||||
```
|
||||
|
||||
From src/ui/parent.ts:
|
||||
```typescript
|
||||
export function showParentCodePrompt(): void;
|
||||
export function initParentScreen(db: IDBDatabase, onBack: () => void): void;
|
||||
```
|
||||
</interfaces>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: HTML Daten-Section + Export/Import/Reset buttons</name>
|
||||
<files>index.html, src/styles/main.css</files>
|
||||
<read_first>index.html, src/styles/main.css</read_first>
|
||||
<action>
|
||||
1. In `index.html`: Add a third `<section>` inside `#parent-content`, after the Einstellungen section (per D-12, D-13, D-14):
|
||||
```html
|
||||
<section class="parent__section">
|
||||
<h2>Daten</h2>
|
||||
<div class="parent__data-actions">
|
||||
<button class="parent__action-btn" id="export-btn">Fortschritt exportieren</button>
|
||||
<div class="parent__import-row">
|
||||
<button class="parent__action-btn" id="import-btn">Fortschritt importieren</button>
|
||||
<input type="file" id="import-file" accept=".json" style="display:none">
|
||||
</div>
|
||||
<button class="parent__action-btn parent__action-btn--danger" id="reset-btn">Alles zuruecksetzen</button>
|
||||
</div>
|
||||
<p class="parent__data-info" id="data-feedback" style="display:none"></p>
|
||||
</section>
|
||||
```
|
||||
|
||||
2. In `src/styles/main.css`: Add styles for data section:
|
||||
```css
|
||||
.parent__data-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
max-width: 300px;
|
||||
}
|
||||
.parent__action-btn {
|
||||
font-family: 'Quicksand', sans-serif;
|
||||
font-size: 1rem;
|
||||
padding: 0.6rem 1.2rem;
|
||||
border: 2px solid var(--accent-green);
|
||||
background: var(--bg-cream);
|
||||
color: var(--text-dark);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
.parent__action-btn:hover {
|
||||
background: var(--bg-forest);
|
||||
}
|
||||
.parent__action-btn--danger {
|
||||
border-color: #D46A6A;
|
||||
color: #D46A6A;
|
||||
}
|
||||
.parent__action-btn--danger:hover {
|
||||
background: #FDE8E8;
|
||||
}
|
||||
.parent__data-info {
|
||||
font-size: 0.9rem;
|
||||
color: var(--accent-green);
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
```
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/dev/workspace/zauberwald && grep -c "export-btn\|import-btn\|reset-btn\|import-file\|parent__action-btn" index.html src/styles/main.css</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- index.html contains section with h2 "Daten" inside parent-content
|
||||
- index.html contains buttons with ids export-btn, import-btn, reset-btn
|
||||
- index.html contains hidden input#import-file with accept=".json"
|
||||
- main.css contains .parent__action-btn and .parent__action-btn--danger styles
|
||||
</acceptance_criteria>
|
||||
<done>Daten section visible in parent area with Export, Import, Reset buttons properly styled</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Export/Import/Reset logic in parent.ts</name>
|
||||
<files>src/ui/parent.ts, src/storage/db.ts</files>
|
||||
<read_first>src/ui/parent.ts, src/storage/db.ts, src/types.ts</read_first>
|
||||
<action>
|
||||
1. In `src/ui/parent.ts`, add Export function (per D-12):
|
||||
- `async function exportData(db: IDBDatabase)`: Get progress + settings via existing functions. Build JSON object `{ version: 1, exportedAt: new Date().toISOString(), progress, settings }`. Create Blob, create object URL, create temporary `<a>` link with download="zauberwald-backup.json", click it, revoke URL. Show feedback "Exportiert!" in `#data-feedback`.
|
||||
|
||||
2. Add Import function (per D-13):
|
||||
- `async function importData(db: IDBDatabase, file: File)`: Read file as text. Parse JSON. Validate structure:
|
||||
- Must have `progress` object with required fields (currentLevel: number, completedLevels: array, totalSessions: number, selectedCharacter: string, selectedLayout: string)
|
||||
- Must have `settings` object with required fields (audioEnabled: boolean)
|
||||
- If validation fails, show error in `#data-feedback` ("Ungueltige Datei") and return
|
||||
- Show confirm dialog: `confirm("Fortschritt ueberschreiben? Aktuelle Daten gehen verloren.")`
|
||||
- If confirmed: `saveProgress(db, { ...parsed.progress, id: 1 })`, `saveSettings(db, { ...parsed.settings, id: 1 })`. Show "Importiert!" feedback. Reload after 1.5s.
|
||||
|
||||
3. Add Reset function (per D-14):
|
||||
- `async function resetAllData(db: IDBDatabase)`: First confirm: `confirm("Wirklich alles loeschen?")`. Second confirm: `confirm("Alle Fortschritte und Einstellungen werden geloescht. Bist du sicher?")`. If both confirmed:
|
||||
- Clear all 5 stores: `db.transaction(storeName, 'readwrite').objectStore(storeName).clear()` for each of: progress, companionAssets, styleReference, forestElements, settings
|
||||
- After all clear: `location.reload()`
|
||||
- Optionally add a helper `clearStore(db, name)` returning a Promise.
|
||||
|
||||
4. Wire buttons in `loadParentData()` (called after code entry):
|
||||
- `document.getElementById('export-btn')!.onclick = () => exportData(db)`
|
||||
- `document.getElementById('import-btn')!.onclick = () => document.getElementById('import-file')!.click()`
|
||||
- `document.getElementById('import-file')!.addEventListener('change', (e) => { const file = (e.target as HTMLInputElement).files?.[0]; if (file) importData(db, file); })`
|
||||
- `document.getElementById('reset-btn')!.onclick = () => resetAllData(db)`
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/dev/workspace/zauberwald && npx tsc --noEmit 2>&1 | head -20</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- parent.ts contains exportData function that creates JSON download
|
||||
- parent.ts contains importData function that validates and confirms before overwriting
|
||||
- parent.ts contains resetAllData function with double confirmation
|
||||
- Export excludes Blobs (only progress + settings)
|
||||
- Import validates required fields before saving
|
||||
- Reset clears all 5 IndexedDB stores
|
||||
- All three buttons wired in loadParentData
|
||||
- TypeScript compiles without errors
|
||||
</acceptance_criteria>
|
||||
<done>Export downloads zauberwald-backup.json, Import validates+confirms+overwrites, Reset double-confirms+clears+reloads</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
- `npx tsc --noEmit` passes
|
||||
- `npm run lint` passes
|
||||
- grep confirms export-btn, import-btn, reset-btn in index.html
|
||||
- grep confirms exportData, importData, resetAllData in parent.ts
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
Parent area has working Export (JSON download), Import (file upload + validation + confirmation), and Reset (double confirmation + full wipe).
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/04-polish-audio/04-03-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user