Files
bscscore/src/components/new-game/Player3Step.tsx
Frank Schwenk af0ffe8517 refactor(new-game): extract Player2Step and Player3Step modules
Refs #30

- Add Player2Step.tsx and Player3Step.tsx under src/components/new-game
- Replace inline definitions with imports in NewGame.tsx
- No behavior changes
2025-10-30 15:14:01 +01:00

165 lines
5.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { h } from 'preact';
import { useEffect, useRef, useState } from 'preact/hooks';
import styles from '../NewGame.module.css';
interface PlayerStepProps {
playerNameHistory: string[];
onNext: (name: string) => void;
onCancel: () => void;
initialValue?: string;
}
export const Player3Step = ({ playerNameHistory, onNext, onCancel, initialValue = '' }: PlayerStepProps) => {
const [player3, setPlayer3] = useState(initialValue);
const [filteredNames, setFilteredNames] = useState(playerNameHistory);
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
const el = inputRef.current;
if (el) {
el.focus();
const end = el.value.length;
try {
el.setSelectionRange(end, end);
} catch {}
}
}, []);
useEffect(() => {
if (!player3) {
setFilteredNames(playerNameHistory);
} else {
setFilteredNames(
playerNameHistory.filter(name =>
name.toLowerCase().includes(player3.toLowerCase())
)
);
}
}, [player3, playerNameHistory]);
const handleSubmit = (e: Event) => {
e.preventDefault();
onNext(player3.trim());
};
const handleQuickPick = (name: string) => {
onNext(name);
};
const handleClear = () => {
setPlayer3('');
if (inputRef.current) inputRef.current.focus();
};
const handleSkip = (e: Event) => {
e.preventDefault();
onNext('');
};
return (
<form className={styles['new-game-form']} onSubmit={handleSubmit} aria-label="Spieler 3 Eingabe" autoComplete="off">
<div className={styles['screen-title']}>Name Spieler 3 (optional)</div>
<div className={styles['progress-indicator']} style={{ marginBottom: 24 }}>
<span className={styles['progress-dot']} />
<span className={styles['progress-dot']} />
<span className={styles['progress-dot'] + ' ' + styles['active']} />
<span className={styles['progress-dot']} />
<span className={styles['progress-dot']} />
<span className={styles['progress-dot']} />
<span className={styles['progress-dot']} />
</div>
<div className={styles['player-input'] + ' ' + styles['player3-input']} style={{ marginBottom: 32, position: 'relative' }}>
<label htmlFor="player3-input" style={{ fontSize: '1.3rem', fontWeight: 600 }}>Spieler 3 (optional)</label>
<div style={{ position: 'relative', width: '100%' }}>
<input
id="player3-input"
className={styles['name-input']}
placeholder="Name Spieler 3 (optional)"
value={player3}
onInput={(e: Event) => {
const target = e.target as HTMLInputElement;
setPlayer3(target.value);
}}
autoComplete="off"
aria-label="Name Spieler 3"
style={{ fontSize: '1.2rem', minHeight: 48, marginTop: 12, marginBottom: 12, width: '100%', paddingRight: 44 }}
ref={inputRef}
/>
{player3 && (
<button
type="button"
className={styles['clear-input-btn']}
aria-label="Feld leeren"
onClick={handleClear}
style={{
position: 'absolute',
right: 8,
top: '50%',
transform: 'translateY(-50%)',
background: 'none',
border: 'none',
cursor: 'pointer',
fontSize: 24,
color: '#aaa',
padding: 0,
zIndex: 2
}}
tabIndex={0}
>
×
</button>
)}
</div>
{filteredNames.length > 0 && (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 12, marginTop: 8 }}>
{filteredNames.slice(0, 10).map((name, idx) => (
<button
type="button"
key={name + idx}
className={styles['quick-pick-btn']}
style={{ fontSize: '1.1rem', padding: '12px 20px', borderRadius: 8, background: '#333', color: '#fff', border: 'none', cursor: 'pointer' }}
onClick={() => handleQuickPick(name)}
aria-label={`Schnellauswahl: ${name}`}
>
{name}
</button>
))}
</div>
)}
</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}
style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer' }}
>
&#8592;
</button>
<div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
<button
type="button"
onClick={handleSkip}
className={styles['quick-pick-btn']}
style={{ fontSize: '1.1rem', padding: '12px 20px', borderRadius: 8, background: '#333', color: '#fff', border: 'none', cursor: 'pointer' }}
>
Überspringen
</button>
<button
type="submit"
className={styles['arrow-btn']}
aria-label="Weiter"
disabled={!player3.trim()}
style={{ fontSize: 48, width: 80, height: 80, borderRadius: '50%', background: '#222', color: '#fff', border: 'none', boxShadow: '0 2px 8px rgba(0,0,0,0.15)', cursor: 'pointer', opacity: !player3.trim() ? 0.5 : 1 }}
>
&#8594;
</button>
</div>
</div>
</form>
);
};