Files
FranciaOcupada/client/src/components/MissionReveal.tsx
Resistencia Dev b0eb3bd637
Some checks failed
CI/CD - Francia Ocupada (La Resistencia) / build-and-deploy (push) Failing after 6s
feat: shuffle mission reveal cards randomly on each client
2025-12-22 23:46:06 +01:00

75 lines
2.8 KiB
TypeScript

import { motion } from 'framer-motion';
import { useEffect, useMemo } from 'react';
import Image from 'next/image';
interface MissionRevealProps {
votes: boolean[];
onFinished?: () => void;
}
export default function MissionReveal({ votes, onFinished }: MissionRevealProps) {
// Barajar votos de forma aleatoria en cada cliente (orden diferente para cada jugador)
const shuffledVotes = useMemo(() => {
const shuffled = [...votes];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}, [votes]);
// Timer de seguridad: 5 segundos y avanza
useEffect(() => {
const timer = setTimeout(() => {
if (onFinished) onFinished();
}, 5000);
return () => clearTimeout(timer);
}, [onFinished]);
return (
<motion.div
className="fixed inset-0 flex flex-col items-center justify-center bg-black/95 z-50 pointer-events-auto"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
>
<h2 className="text-3xl font-bold text-white mb-12 uppercase tracking-widest drop-shadow-lg text-center">
Resultado de la misión
</h2>
<div className="flex gap-4 justify-center mb-12 flex-wrap max-w-[90vw]">
{shuffledVotes.map((vote, idx) => (
<motion.div
key={idx}
className="w-32 h-48 rounded-xl flex items-center justify-center shadow-2xl relative overflow-hidden"
initial={{ scale: 0, rotateY: 180 }}
animate={{ scale: 1, rotateY: 0 }}
transition={{
delay: idx * 0.3,
type: "spring",
stiffness: 200,
damping: 20
}}
>
<Image
src={vote ? '/assets/images/tokens/vote_approve.png' : '/assets/images/tokens/vote_reject.png'}
alt={vote ? 'Éxito' : 'Sabotaje'}
fill
className="object-contain"
/>
</motion.div>
))}
</div>
<motion.div
className="text-white text-xl font-mono mt-8 text-center"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: shuffledVotes.length * 0.3 + 0.5 }}
>
<span className="animate-pulse">Analizando resultado estratégico...</span>
</motion.div>
</motion.div>
);
}