refactor: Update Race To step UI and logic
- Renames 'Offen' to 'Endlos' and moves it to a separate line. - Extends quick-pick buttons to include 1-9. - Removes 'Custom' button and makes numeric input always visible. - Updates placeholder text for the custom input. - Closes #10
This commit is contained in:
2
.gitea
2
.gitea
@@ -1 +1 @@
|
||||
@https://gitea.schwenk.online/froxxxy/bscscore/issues/9
|
||||
@https://gitea.schwenk.online/froxxxy/bscscore/issues/10
|
||||
@@ -2,7 +2,7 @@ import { h } from 'preact';
|
||||
import { useState, useEffect, useCallback } from 'preact/hooks';
|
||||
import GameList from './GameList.jsx';
|
||||
import GameDetail from './GameDetail.jsx';
|
||||
import { Player1Step, Player2Step, Player3Step, GameTypeStep } from './NewGame.jsx';
|
||||
import { Player1Step, Player2Step, Player3Step, GameTypeStep, RaceToStep } from './NewGame.jsx';
|
||||
import Modal from './Modal.jsx';
|
||||
import ValidationModal from './ValidationModal.jsx';
|
||||
import GameCompletionModal from './GameCompletionModal.jsx';
|
||||
@@ -156,10 +156,9 @@ const App = () => {
|
||||
setNewGameStep('raceTo');
|
||||
};
|
||||
const handleRaceToNext = (raceTo) => {
|
||||
setNewGameData(data => ({ ...data, raceTo }));
|
||||
// Finalize game creation here
|
||||
// For now, just go back to game list
|
||||
setScreen('game-list');
|
||||
const finalData = { ...newGameData, raceTo };
|
||||
const newId = handleCreateGame(finalData);
|
||||
showGameDetail(newId);
|
||||
setNewGameStep(null);
|
||||
setNewGameData({ player1: '', player2: '', player3: '', gameType: '', raceTo: '' });
|
||||
};
|
||||
@@ -221,10 +220,11 @@ const App = () => {
|
||||
/>
|
||||
)}
|
||||
{newGameStep === 'raceTo' && (
|
||||
<div style={{ padding: 40, textAlign: 'center' }}>
|
||||
<h2>Race To Step (TODO)</h2>
|
||||
<button onClick={() => handleRaceToNext(5)}>5</button>
|
||||
</div>
|
||||
<RaceToStep
|
||||
onNext={handleRaceToNext}
|
||||
onCancel={() => setNewGameStep('gameType')}
|
||||
initialValue={newGameData.raceTo}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -483,4 +483,86 @@ const GameTypeStep = ({ onNext, onCancel, initialValue = '' }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export { Player1Step, Player2Step, Player3Step, GameTypeStep };
|
||||
/**
|
||||
* Race To selection step for multi-step game creation wizard.
|
||||
* @param {object} props
|
||||
* @param {Function} props.onNext
|
||||
* @param {Function} props.onCancel
|
||||
* @param {string|number} [props.initialValue]
|
||||
* @returns {import('preact').VNode}
|
||||
*/
|
||||
const RaceToStep = ({ onNext, onCancel, initialValue = '' }) => {
|
||||
const [currentValue, setCurrentValue] = useState(initialValue);
|
||||
const quickPicks = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
const handleQuickPick = (value) => {
|
||||
onNext(value);
|
||||
};
|
||||
|
||||
const handleInputChange = (e) => {
|
||||
setCurrentValue(e.target.value);
|
||||
};
|
||||
|
||||
const handleCustomSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
onNext(parseInt(currentValue, 10) || 0);
|
||||
};
|
||||
|
||||
return (
|
||||
<form className={styles['new-game-form']} onSubmit={handleCustomSubmit} aria-label="Race To auswählen">
|
||||
<div className={styles['screen-title']}>Neues Spiel – Schritt 5/5</div>
|
||||
<div className={styles['progress-indicator']} style={{ marginBottom: 24 }}>
|
||||
<span className={styles['progress-dot']} />
|
||||
<span className={styles['progress-dot']} />
|
||||
<span className={styles['progress-dot']} />
|
||||
<span className={styles['progress-dot']} />
|
||||
<span className={styles['progress-dot'] + ' ' + styles['active']} />
|
||||
</div>
|
||||
<div className={styles['endlos-container']}>
|
||||
<button
|
||||
type="button"
|
||||
className={`${styles['race-to-btn']} ${styles['endlos-btn']} ${initialValue === 0 ? styles.selected : ''}`}
|
||||
onClick={() => handleQuickPick(0)}
|
||||
>
|
||||
Endlos
|
||||
</button>
|
||||
</div>
|
||||
<div className={styles['race-to-selection']}>
|
||||
{quickPicks.map(value => (
|
||||
<button
|
||||
key={value}
|
||||
type="button"
|
||||
className={`${styles['race-to-btn']} ${parseInt(initialValue, 10) === value ? styles.selected : ''}`}
|
||||
onClick={() => handleQuickPick(value)}
|
||||
>
|
||||
{value}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className={styles['custom-race-to']}>
|
||||
<input
|
||||
type="number"
|
||||
pattern="[0-9]*"
|
||||
value={currentValue}
|
||||
onInput={handleInputChange}
|
||||
className={styles['name-input']}
|
||||
placeholder="manuelle Eingabe"
|
||||
/>
|
||||
<button type="submit" className={styles['arrow-btn']} aria-label="Bestätigen">✓</button>
|
||||
</div>
|
||||
<div className={styles['arrow-nav']} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 48 }}>
|
||||
<button
|
||||
type="button"
|
||||
className={styles['arrow-btn']}
|
||||
aria-label="Zurück"
|
||||
onClick={onCancel}
|
||||
>
|
||||
←
|
||||
</button>
|
||||
<div style={{ width: 80 }} />
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export { Player1Step, Player2Step, Player3Step, GameTypeStep, RaceToStep };
|
||||
@@ -215,4 +215,63 @@
|
||||
.game-type-btn.selected {
|
||||
background: #4a4a4a;
|
||||
border-color: #777;
|
||||
}
|
||||
|
||||
.race-to-selection {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(60px, 1fr));
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.race-to-btn {
|
||||
background: #2a2a2a;
|
||||
border: 2px solid #333;
|
||||
color: #fff;
|
||||
font-size: 1.3rem;
|
||||
font-weight: 600;
|
||||
padding: 16px 8px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
transition: background 0.2s, border-color 0.2s;
|
||||
min-height: 70px;
|
||||
}
|
||||
|
||||
.race-to-btn:hover {
|
||||
background: #333;
|
||||
border-color: #555;
|
||||
}
|
||||
|
||||
.race-to-btn.selected {
|
||||
background: #4a4a4a;
|
||||
border-color: #777;
|
||||
}
|
||||
|
||||
.custom-race-to {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-top: 24px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.custom-race-to input {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.custom-race-to .arrow-btn {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
font-size: 32px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.endlos-container {
|
||||
width: 100%;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.endlos-btn {
|
||||
width: 100%;
|
||||
}
|
||||
Reference in New Issue
Block a user