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:
@@ -27,39 +27,44 @@ export function validatePlayerName(name: string): ValidationResult {
|
||||
export function validateGameData(data: NewGameData): ValidationResult {
|
||||
const errors: string[] = [];
|
||||
|
||||
// Validate player names
|
||||
const player1Validation = validatePlayerName(data.player1);
|
||||
const player2Validation = validatePlayerName(data.player2);
|
||||
|
||||
errors.push(...player1Validation.errors);
|
||||
errors.push(...player2Validation.errors);
|
||||
try {
|
||||
// Validate player names
|
||||
const player1Validation = validatePlayerName(data.player1);
|
||||
const player2Validation = validatePlayerName(data.player2);
|
||||
|
||||
errors.push(...player1Validation.errors);
|
||||
errors.push(...player2Validation.errors);
|
||||
|
||||
// Check for duplicate player names
|
||||
const playerNames = [data.player1.trim(), data.player2.trim()];
|
||||
if (data.player3?.trim()) {
|
||||
const player3Validation = validatePlayerName(data.player3);
|
||||
errors.push(...player3Validation.errors);
|
||||
playerNames.push(data.player3.trim());
|
||||
}
|
||||
|
||||
const uniqueNames = new Set(playerNames.filter(name => name.length > 0));
|
||||
if (uniqueNames.size !== playerNames.filter(name => name.length > 0).length) {
|
||||
errors.push(VALIDATION_MESSAGES.DUPLICATE_PLAYER_NAMES);
|
||||
}
|
||||
|
||||
// Validate game type
|
||||
if (!data.gameType?.trim()) {
|
||||
errors.push(VALIDATION_MESSAGES.GAME_TYPE_REQUIRED);
|
||||
}
|
||||
|
||||
// Validate race to
|
||||
if (!data.raceTo?.trim()) {
|
||||
errors.push(VALIDATION_MESSAGES.RACE_TO_REQUIRED);
|
||||
} else {
|
||||
const raceToNumber = parseInt(data.raceTo, 10);
|
||||
if (isNaN(raceToNumber) || raceToNumber <= 0) {
|
||||
errors.push(VALIDATION_MESSAGES.RACE_TO_INVALID);
|
||||
// Check for duplicate player names
|
||||
const playerNames = [data.player1.trim(), data.player2.trim()];
|
||||
if (data.player3?.trim()) {
|
||||
const player3Validation = validatePlayerName(data.player3);
|
||||
errors.push(...player3Validation.errors);
|
||||
playerNames.push(data.player3.trim());
|
||||
}
|
||||
|
||||
const uniqueNames = new Set(playerNames.filter(name => name.length > 0));
|
||||
if (uniqueNames.size !== playerNames.filter(name => name.length > 0).length) {
|
||||
errors.push(VALIDATION_MESSAGES.DUPLICATE_PLAYER_NAMES);
|
||||
}
|
||||
|
||||
// Validate game type
|
||||
if (!data.gameType?.trim()) {
|
||||
errors.push(VALIDATION_MESSAGES.GAME_TYPE_REQUIRED);
|
||||
}
|
||||
|
||||
// Validate race to
|
||||
if (!data.raceTo?.trim()) {
|
||||
errors.push(VALIDATION_MESSAGES.RACE_TO_REQUIRED);
|
||||
} else {
|
||||
const raceToNumber = parseInt(data.raceTo, 10);
|
||||
if (isNaN(raceToNumber) || raceToNumber <= 0) {
|
||||
errors.push(VALIDATION_MESSAGES.RACE_TO_INVALID);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Validation error:', error);
|
||||
errors.push('Ein unerwarteter Validierungsfehler ist aufgetreten');
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user