Files
bscscore/src/components/GameCompletionModal.tsx
T
Frank Schwenk 8a46a8a019 refactor: extract reusable library
- move reusable domain, data, state, ui code into src/lib
- update host screens to consume new library exports
- document architecture and configure path aliases
- bump astro integration dependencies for compatibility

Refs #30
2025-11-13 10:41:55 +01:00

63 lines
2.6 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 modalStyles from '@lib/ui/Modal.module.css';
import styles from './GameCompletionModal.module.css';
import type { Game } from '@lib/domain/types';
interface GameCompletionModalProps {
open: boolean;
game: Game | null;
onConfirm: () => void;
onClose: () => void;
onRematch: () => void;
}
/**
* Modal shown when a game is completed.
*/
const GameCompletionModal = ({ open, game, onConfirm, onClose, onRematch }: GameCompletionModalProps) => {
if (!open || !game) return null;
const playerNames = [game.player1, game.player2, game.player3].filter(Boolean);
const scores = [game.score1, game.score2, game.score3].filter((_, i) => playerNames[i]);
let maxScore, winners, winnerText;
if (game.forfeitedBy) {
winnerText = `${game.winner} hat gewonnen, da ${game.forfeitedBy} aufgegeben hat.`;
} else {
maxScore = Math.max(...scores);
winners = playerNames.filter((name, idx) => scores[idx] === maxScore);
winnerText = winners.length > 1
? `Unentschieden zwischen ${winners.join(' und ')}`
: `${winners[0]} hat gewonnen!`;
}
return (
<div id="game-completion-modal" className={modalStyles['modal'] + ' ' + modalStyles['show']} role="dialog" aria-modal="true" aria-labelledby="completion-modal-title">
<div className={modalStyles['modal-content']}>
<div className={modalStyles['modal-header']}>
<span className={modalStyles['modal-title']} id="completion-modal-title">Spiel beendet</span>
<button className={modalStyles['close-button']} onClick={onClose} aria-label="Schließen">×</button>
</div>
<div className={modalStyles['modal-body']}>
<div className={styles['final-scores']}>
{playerNames.map((name, idx) => (
<div className={styles['final-score']} key={name + idx}>
<span className={styles['player-name']}>{name}</span>
<span className={styles['score']}>{scores[idx]}</span>
</div>
))}
</div>
<div className={styles['winner-announcement']}><h3>{winnerText}</h3></div>
</div>
<div className={modalStyles['modal-footer']}>
<button className={styles['btn'] + ' ' + styles['btn--warning']} onClick={onConfirm} aria-label="Bestätigen">Bestätigen</button>
<button className={styles['btn'] + ' ' + styles['btn--primary']} onClick={onRematch} aria-label="Rematch">Rematch</button>
<button className={styles['btn']} onClick={onClose} aria-label="Abbrechen">Abbrechen</button>
</div>
</div>
</div>
);
};
export default GameCompletionModal;