feat(storage): migrate to IndexedDB with localStorage fallback and async app flow
- Add IndexedDB service with schema, indexes, and player stats - Migrate GameService to async IndexedDB and auto-migrate from localStorage - Update hooks and App handlers to async; add error handling and UX feedback - Convert remaining JSX components to TSX - Add test utility for IndexedDB and migration checks - Extend game types with sync fields for future online sync
This commit is contained in:
@@ -49,10 +49,10 @@ export default function GameList({
|
||||
}
|
||||
};
|
||||
|
||||
const filterButtons: Array<{ key: GameFilter; label: string; ariaLabel: string }> = [
|
||||
{ key: 'all', label: 'Alle', ariaLabel: 'Alle Spiele anzeigen' },
|
||||
{ key: 'active', label: 'Aktiv', ariaLabel: 'Nur aktive Spiele anzeigen' },
|
||||
{ key: 'completed', label: 'Abgeschlossen', ariaLabel: 'Nur abgeschlossene Spiele anzeigen' },
|
||||
const filterButtons = [
|
||||
{ key: 'all' as const, label: 'Alle', ariaLabel: 'Alle Spiele anzeigen' },
|
||||
{ key: 'active' as const, label: 'Aktiv', ariaLabel: 'Nur aktive Spiele anzeigen' },
|
||||
{ key: 'completed' as const, label: 'Abgeschlossen', ariaLabel: 'Nur abgeschlossene Spiele anzeigen' },
|
||||
];
|
||||
|
||||
return (
|
||||
@@ -87,15 +87,26 @@ export default function GameList({
|
||||
<div
|
||||
className={styles['game-info']}
|
||||
onClick={() => onShowGameDetail(game.id)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
onShowGameDetail(game.id);
|
||||
}
|
||||
}}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-label={`Details für Spiel ${playerNames}`}
|
||||
aria-describedby={`game-${game.id}-description`}
|
||||
>
|
||||
<div className={styles['game-type']}>
|
||||
{game.gameType}{game.raceTo ? ` | ${game.raceTo}` : ''}
|
||||
</div>
|
||||
<div className={styles['player-names']}>{playerNames}</div>
|
||||
<div className={styles['game-scores']}>{scores}</div>
|
||||
<div id={`game-${game.id}-description`} className="sr-only">
|
||||
{game.gameType} Spiel zwischen {playerNames} mit dem Stand {scores}.
|
||||
{game.status === 'completed' ? 'Abgeschlossen' : 'Aktiv'}
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
variant="danger"
|
||||
|
||||
Reference in New Issue
Block a user