import React, { useEffect, useRef, useState } from 'react'; import type { WizardChallengeResult } from '../types'; interface WizardChallengeModalProps { challenge: WizardChallengeResult | null; onClose: () => void; } export const WizardChallengeModal: React.FC = ({ challenge, onClose, }) => { const [countdown, setCountdown] = useState(5); const [progressPercent, setProgressPercent] = useState(100); const onCloseRef = useRef(onClose); useEffect(() => { onCloseRef.current = onClose; }); const challengeKey = challenge ? `${challenge.challenger_id}_${challenge.player_bouts_won}_${challenge.wizard_bouts_won}_${challenge.reward_chosen}_${challenge.score_change}_${challenge.strength_change}_${challenge.health_change}_${challenge.wizard_respawn_position?.x}_${challenge.wizard_respawn_position?.y}` : null; useEffect(() => { if (!challengeKey) { setCountdown(5); setProgressPercent(100); return; } const DURATION_MS = 5000; const targetEndTime = Date.now() + DURATION_MS; setCountdown(5); setProgressPercent(100); const timer = window.setInterval(() => { const now = Date.now(); const remainingMs = targetEndTime - now; if (remainingMs <= 0) { window.clearInterval(timer); setCountdown(0); setProgressPercent(0); onCloseRef.current(); return; } const seconds = Math.ceil(remainingMs / 1000); const percent = Math.min(100, Math.max(0, (remainingMs / DURATION_MS) * 100)); setCountdown(seconds); setProgressPercent(percent); }, 100); return () => { window.clearInterval(timer); }; }, [challengeKey]); if (!challenge) return null; const playerName = challenge.challenger_name; const wizardName = challenge.wizard_name || 'Gary the Wizard'; return (
{/* Glowing cyber wizard header banner */}
{/* 5-second automatic progress bar */}
🧙‍♂️

WIZARD NPC DUEL: 3-BOUT D20 CHALLENGE

{playerName} vs{' '} {wizardName}

{/* 3 Bouts Breakdown */}
{challenge.bouts.map((bout) => (
{/* Bout Index */}
Bout #{bout.bout_number}
{/* Player Bout Score */}
{playerName}
🎲 D20({bout.player_roll}) × ⚡Str({bout.player_strength}) = {bout.player_score}
{/* VS Divider */}
VS
{/* Wizard Bout Score */}
{wizardName}
{bout.wizard_score} = ⚡Str({bout.wizard_strength}) × 🎲 D20({bout.wizard_roll})
{/* Bout Outcome Badge */}
{bout.winner === 'player' ? 'Player' : bout.winner === 'wizard' ? 'Wizard' : 'Tie'}
))}
{/* Overall Match Outcome Banner */}
Duel Outcome: {challenge.player_bouts_won} - {challenge.wizard_bouts_won}
{challenge.player_won ? '✨ CHALLENGE VICTORY ✨' : '💀 CHALLENGE DEFEAT 💀'}
{challenge.player_won ? (
{challenge.reward_chosen === 'strength' ? (
⚡ Victory Reward: +{challenge.strength_change || 2} Strength! (Total Strength: {challenge.new_strength ?? '?'})
) : challenge.reward_chosen === 'health' ? (
❤️ Victory Reward: +{challenge.health_change || 2} Health! (Total HP: {challenge.new_health})
) : (
🏆 Victory Reward: +{challenge.score_change || 2} Score Points! (Total Score: {challenge.new_score})
)}
) : (
{challenge.health_change < 0 ? ( 💔 Lost {Math.abs(challenge.health_change)} Health! (Remaining HP: {challenge.new_health}) ) : ( 📉 Out of HP! Lost {Math.abs(challenge.score_change)} Score points! (Score: {challenge.new_score}) )}
)}
🔮 The Wizard vanished in a puff of smoke and teleported to ({challenge.wizard_respawn_position?.x}, {challenge.wizard_respawn_position?.y}).
{/* Modal Controls / Auto-close countdown */}
Auto-closing in {countdown}s...
); };