8085d2ecc8
- 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
36 lines
1.3 KiB
TypeScript
36 lines
1.3 KiB
TypeScript
import { h } from 'preact';
|
||
import styles from './Modal.module.css';
|
||
|
||
interface ModalProps {
|
||
open: boolean;
|
||
title: string;
|
||
message: string;
|
||
onCancel: () => void;
|
||
onConfirm: () => void;
|
||
}
|
||
|
||
/**
|
||
* Generic modal dialog for confirmation.
|
||
*/
|
||
const Modal = ({ open, title, message, onCancel, onConfirm }: ModalProps) => {
|
||
if (!open) return null;
|
||
return (
|
||
<div className={styles['modal'] + ' ' + styles['show']} role="dialog" aria-modal="true" aria-labelledby="modal-title">
|
||
<div className={styles['modal-content']}>
|
||
<div className={styles['modal-header']}>
|
||
<span className={styles['modal-title']} id="modal-title">{title}</span>
|
||
<button className={styles['close-button']} onClick={onCancel} aria-label="Schließen">×</button>
|
||
</div>
|
||
<div className={styles['modal-body']}>
|
||
<div className={styles['modal-message']}>{message}</div>
|
||
</div>
|
||
<div className={styles['modal-footer']}>
|
||
<button className={styles['modal-button'] + ' ' + styles['cancel']} onClick={onCancel} aria-label="Abbrechen">Abbrechen</button>
|
||
<button className={styles['modal-button'] + ' ' + styles['confirm']} onClick={onConfirm} aria-label="Löschen">Löschen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default Modal;
|