feat(#28): add break rule & order to games and UI

- Types: add BreakRule, break metadata to StandardGame, extend NewGameData/steps
- NewGame: add BreakRule and BreakOrder steps with auto-advance
- NewGameScreen: wire new steps into flow
- GameService: set up defaults, persist break order, compute next breaker on +1
- GameDetail: show breaker indicator; treat -1 as undo equivalent

Backfill defaults for existing games via service logic.

Refs #28
This commit is contained in:
Frank Schwenk
2025-10-30 11:34:26 +01:00
parent 147906af59
commit 1bd9919b6b
5 changed files with 186 additions and 7 deletions

View File

@@ -1,6 +1,6 @@
import { h } from 'preact';
import { Screen } from '../ui/Layout';
import { Player1Step, Player2Step, Player3Step, GameTypeStep, RaceToStep } from '../NewGame';
import { Player1Step, Player2Step, Player3Step, GameTypeStep, BreakRuleStep, BreakOrderStep, RaceToStep } from '../NewGame';
import type { NewGameStep, NewGameData } from '../../types/game';
interface NewGameScreenProps {
@@ -44,6 +44,16 @@ export default function NewGameScreen({
gameType: type as any, // Type assertion for now, could be improved with proper validation
raceTo: '8'
});
onStepChange('breakRule');
};
const handleBreakRuleNext = (rule: 'winnerbreak' | 'wechselbreak') => {
onDataChange({ breakRule: rule });
onStepChange('breakOrder');
};
const handleBreakOrderNext = (first: number, second?: number) => {
onDataChange({ breakFirst: first, breakSecond: second ?? '' });
onStepChange('raceTo');
};
@@ -63,9 +73,15 @@ export default function NewGameScreen({
case 'gameType':
onStepChange('player3');
break;
case 'raceTo':
case 'breakRule':
onStepChange('gameType');
break;
case 'breakOrder':
onStepChange('breakRule');
break;
case 'raceTo':
onStepChange('breakOrder');
break;
default:
onCancel();
}
@@ -107,6 +123,23 @@ export default function NewGameScreen({
initialValue={data.gameType}
/>
)}
{step === 'breakRule' && (
<BreakRuleStep
onNext={handleBreakRuleNext}
onCancel={handleStepBack}
initialValue={(data.breakRule as any) || 'winnerbreak'}
/>
)}
{step === 'breakOrder' && (
<BreakOrderStep
players={[data.player1, data.player2, data.player3]}
rule={(data.breakRule as any) || 'winnerbreak'}
onNext={handleBreakOrderNext}
onCancel={handleStepBack}
/>
)}
{step === 'raceTo' && (
<RaceToStep