You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
3.5 KiB
TypeScript

import { useEffect, useState, type CSSProperties } from 'react';
import { REVIVE_TIMER_SECONDS } from '../shared/constants';
import { useT, t } from '../i18n';
interface DeathScreenProps {
visible: boolean;
onRevive: () => void;
/** Free revives left for non-subscribers; omit when subscribed / unlimited. */
revivesRemaining?: number;
}
/** Full-screen dimming; `pointerEvents: 'none'` so HUD controls (e.g. hero sheet) stay clickable. */
const overlayStyle: CSSProperties = {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundColor: 'rgba(0, 0, 0, 0.7)',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
zIndex: 100,
transition: 'opacity 0.5s ease',
pointerEvents: 'none',
};
/** Death UI captures taps; overlay around it passes clicks through to the game HUD. */
const deathPanelStyle: CSSProperties = {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: 24,
pointerEvents: 'auto',
};
const titleStyle: CSSProperties = {
fontSize: 36,
fontWeight: 900,
color: '#cc3333',
textShadow: '0 0 20px rgba(204, 51, 51, 0.5)',
letterSpacing: 4,
};
const timerStyle: CSSProperties = {
fontSize: 48,
fontWeight: 700,
color: '#ffffff',
fontVariantNumeric: 'tabular-nums',
};
const buttonStyle: CSSProperties = {
padding: '14px 40px',
fontSize: 18,
fontWeight: 700,
color: '#fff',
backgroundColor: '#cc3333',
border: 'none',
borderRadius: 8,
cursor: 'pointer',
transition: 'background-color 0.2s',
};
export function DeathScreen({ visible, onRevive, revivesRemaining }: DeathScreenProps) {
const tr = useT();
const [timer, setTimer] = useState(REVIVE_TIMER_SECONDS);
const canRevive = revivesRemaining === undefined || revivesRemaining > 0;
// Countdown timer
useEffect(() => {
if (!visible) {
setTimer(REVIVE_TIMER_SECONDS);
return;
}
const interval = setInterval(() => {
setTimer((t) => {
if (t <= 1) {
clearInterval(interval);
return 0;
}
return t - 1;
});
}, 1000);
return () => clearInterval(interval);
}, [visible]);
// Auto-revive when timer hits 0 (only if server still allows free revives)
useEffect(() => {
if (visible && timer === 0 && canRevive) {
onRevive();
}
}, [visible, timer, onRevive, canRevive]);
if (!visible) return null;
return (
<div style={overlayStyle}>
<div style={deathPanelStyle}>
<div style={titleStyle}>{tr.youDied}</div>
<div style={timerStyle}>{canRevive ? timer : '—'}</div>
{revivesRemaining !== undefined && (
<div style={{ color: '#aaa', fontSize: 14 }}>
{t(tr.freeRevivesLeft, { count: Math.max(0, revivesRemaining) })}
</div>
)}
<button
style={{
...buttonStyle,
opacity: canRevive ? 1 : 0.45,
cursor: canRevive ? 'pointer' : 'not-allowed',
}}
disabled={!canRevive}
onClick={onRevive}
onMouseEnter={(e) => {
if (!canRevive) return;
e.currentTarget.style.backgroundColor = '#ee4444';
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = '#cc3333';
}}
>
{tr.reviveNow}
</button>
<div style={{ color: '#888', fontSize: 13 }}>
{canRevive ? t(tr.autoReviveIn, { timer }) : tr.noFreeRevives}
</div>
</div>
</div>
);
}