Fix screen issues

This commit is contained in:
Joey Yakimowich-Payne 2026-01-25 08:18:12 -07:00
commit 2a8811e9dc
No known key found for this signature in database
GPG key ID: 6BFE655FA5ABD1E1
2 changed files with 180 additions and 132 deletions

View file

@ -254,12 +254,13 @@ export const Lobby: React.FC<LobbyProps> = ({ quizTitle, players, gamePin, role,
</motion.div>
</>
) : (
<div className="flex flex-col items-center justify-center flex-1 text-center p-4 md:p-8">
<div className="flex flex-col items-center flex-1 text-center p-4 md:p-8 overflow-hidden">
<div className="flex flex-col items-center shrink-0">
<motion.div
initial={{ scale: 0.5 }}
animate={{ scale: 1 }}
transition={{ type: 'spring', bounce: 0.6 }}
className={`bg-white p-6 md:p-8 rounded-2xl md:rounded-[2rem] shadow-[0_10px_0_rgba(0,0,0,0.1)] mb-4 md:mb-8 relative ${isPresenter ? 'ring-4 ring-yellow-400' : ''}`}
className={`bg-white p-5 md:p-8 rounded-2xl md:rounded-[2rem] shadow-[0_10px_0_rgba(0,0,0,0.1)] mb-3 md:mb-6 relative ${isPresenter ? 'ring-4 ring-yellow-400' : ''}`}
>
{isPresenter && (
<div className="absolute -top-3 -right-3 bg-yellow-400 p-2 rounded-full shadow-lg">
@ -267,25 +268,71 @@ export const Lobby: React.FC<LobbyProps> = ({ quizTitle, players, gamePin, role,
</div>
)}
{currentPlayer ? (
<PlayerAvatar seed={currentPlayer.avatarSeed} size={60} className="md:w-20 md:h-20" />
<PlayerAvatar seed={currentPlayer.avatarSeed} size={48} className="md:w-20 md:h-20" />
) : (
<User size={60} strokeWidth={2.5} className="text-theme-primary md:w-20 md:h-20" />
<User size={48} strokeWidth={2.5} className="text-theme-primary md:w-20 md:h-20" />
)}
</motion.div>
<h2 className="text-3xl md:text-5xl font-black mb-2 md:mb-4 font-display">
<h2 className="text-2xl md:text-5xl font-black mb-1 md:mb-4 font-display">
{currentPlayer?.name || "You're in!"}
</h2>
{isPresenter ? (
<div className="flex flex-col items-center gap-2">
<span className="bg-yellow-400 text-yellow-900 px-4 py-1 rounded-full font-bold text-sm flex items-center gap-2">
<Crown size={16} />
<div className="flex flex-col items-center gap-1 md:gap-2">
<span className="bg-yellow-400 text-yellow-900 px-3 md:px-4 py-1 rounded-full font-bold text-xs md:text-sm flex items-center gap-2">
<Crown size={14} className="md:w-4 md:h-4" />
You are the Presenter
</span>
<p className="text-lg md:text-xl font-bold opacity-80">You can advance screens during the game</p>
<p className="text-sm md:text-xl font-bold opacity-80">You can advance screens during the game</p>
</div>
) : (
<p className="text-lg md:text-2xl font-bold opacity-80">Waiting for the host to start...</p>
<p className="text-sm md:text-2xl font-bold opacity-80">Waiting for the host to start...</p>
)}
</div>
{/* Player list */}
<div className="mt-4 md:mt-6 flex-1 min-h-0 w-full max-w-md overflow-hidden flex flex-col">
<div className="text-xs md:text-sm font-bold uppercase tracking-widest opacity-60 mb-2 md:mb-3">
{players.length} Player{players.length !== 1 ? 's' : ''} Connected
</div>
<div className="flex-1 overflow-y-auto">
<div className="flex flex-wrap gap-2 justify-center pb-20">
<AnimatePresence>
{players.map((player) => {
const isCurrentPlayer = player.id === currentPlayerId;
const isPlayerHost = player.id === 'host';
const isPlayerPresenter = player.id === presenterId;
return (
<motion.div
key={player.id}
initial={{ scale: 0, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0, opacity: 0 }}
className={`px-3 py-1.5 rounded-full font-bold text-sm flex items-center gap-2 ${
isCurrentPlayer
? 'bg-white text-theme-primary'
: isPlayerHost
? 'bg-yellow-400 text-black'
: 'bg-white/20 text-white'
}`}
>
{isPlayerPresenter && !isPlayerHost && (
<Crown size={12} className="text-yellow-400" />
)}
<PlayerAvatar seed={player.avatarSeed} size={16} />
<span className="max-w-[100px] truncate">{player.name}</span>
{isPlayerHost && (
<span className="text-[10px] bg-black/20 px-1.5 py-0.5 rounded-full">HOST</span>
)}
{isCurrentPlayer && !isPlayerHost && (
<span className="text-[10px] bg-theme-primary/20 px-1.5 py-0.5 rounded-full">YOU</span>
)}
</motion.div>
);
})}
</AnimatePresence>
</div>
</div>
</div>
{onLeaveGame && (
<motion.button
@ -293,7 +340,7 @@ export const Lobby: React.FC<LobbyProps> = ({ quizTitle, players, gamePin, role,
animate={{ y: 0, opacity: 1 }}
transition={{ delay: 0.3 }}
onClick={onLeaveGame}
className="mt-8 bg-white/20 hover:bg-white/30 text-white px-6 py-3 rounded-full font-bold flex items-center gap-2 transition-all active:scale-95"
className="fixed bottom-4 md:bottom-8 bg-white/20 hover:bg-white/30 text-white px-6 py-3 rounded-full font-bold flex items-center gap-2 transition-all active:scale-95"
>
<LogOut size={20} />
Leave Game

View file

@ -129,11 +129,12 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
// -- CLIENT VIEW --
const bgColor = isCorrect ? 'bg-[#22c55e]' : 'bg-[#ef4444]';
const darkerColor = isCorrect ? 'bg-[#15803d]' : 'bg-[#b91c1c]';
const ShapeIcon = SHAPES[correctOption.shape];
const showContinueButton = (isHost && onNext) || (!isHost && isPresenter && onPresenterAdvance);
const handleContinue = isHost ? onNext : onPresenterAdvance;
return (
<div className={`flex flex-col items-center justify-center h-screen ${bgColor} text-white p-4 md:p-6 relative overflow-hidden transition-colors duration-500`}>
<div className={`flex flex-col h-screen ${bgColor} text-white relative overflow-hidden transition-colors duration-500`}>
{/* Dynamic Background Circles */}
<motion.div
@ -142,21 +143,23 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
className="absolute w-[800px] h-[800px] bg-white rounded-full blur-3xl opacity-10 pointer-events-none"
/>
{/* Main content - takes available space above bottom sheet */}
<div className="flex-1 flex flex-col items-center justify-center p-4 md:p-6 z-10">
<motion.div
initial={{ scale: 0.5, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ type: "spring", bounce: 0.6 }}
className="flex flex-col items-center z-10"
className="flex flex-col items-center"
>
<div className="bg-white p-4 md:p-6 rounded-full shadow-[0_6px_0_rgba(0,0,0,0.2)] md:shadow-[0_10px_0_rgba(0,0,0,0.2)] mb-4 md:mb-8">
<div className="bg-white p-3 md:p-6 rounded-full shadow-[0_6px_0_rgba(0,0,0,0.2)] md:shadow-[0_10px_0_rgba(0,0,0,0.2)] mb-3 md:mb-8">
{isCorrect ? (
<Check className="w-12 h-12 md:w-20 md:h-20 text-[#22c55e]" strokeWidth={4} />
<Check className="w-10 h-10 md:w-20 md:h-20 text-[#22c55e]" strokeWidth={4} />
) : (
<X className="w-12 h-12 md:w-20 md:h-20 text-[#ef4444]" strokeWidth={4} />
<X className="w-10 h-10 md:w-20 md:h-20 text-[#ef4444]" strokeWidth={4} />
)}
</div>
<h1 className="text-4xl md:text-8xl font-black font-display mb-2 md:mb-4 drop-shadow-lg text-center">
<h1 className="text-3xl md:text-8xl font-black font-display mb-1 md:mb-4 drop-shadow-lg text-center">
{isCorrect ? "Correct!" : "Incorrect"}
</h1>
@ -167,7 +170,7 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
className="flex flex-col items-center"
>
{isCorrect ? (
<div className="flex flex-col items-center gap-2 md:gap-4 mb-4 md:mb-8">
<div className="flex flex-col items-center gap-2 md:gap-4 mb-2 md:mb-8">
<div className="bg-black/20 px-4 md:px-8 py-2 md:py-4 rounded-2xl md:rounded-3xl backdrop-blur-sm border-2 md:border-4 border-white/30 flex items-center gap-2 md:gap-4">
<span className="text-2xl md:text-4xl font-black">+{pointsEarned}</span>
<span className="text-sm md:text-base font-bold uppercase opacity-80">Points</span>
@ -179,8 +182,8 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
)}
</div>
) : (
<div className="text-base md:text-2xl font-bold opacity-90 mb-4 md:mb-8 max-w-xs md:max-w-md text-center px-4">
Don't worry, you can catch up in the next round!
<div className="text-sm md:text-2xl font-bold opacity-90 mb-2 md:mb-8 max-w-xs md:max-w-md text-center px-4">
Don't worry, you'll get the next one!
</div>
)}
@ -192,21 +195,20 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
</div>
)}
<div className="mt-4 md:mt-8 bg-black/20 px-4 md:px-6 py-2 rounded-xl text-base md:text-xl font-bold">
<div className="mt-2 md:mt-8 bg-black/20 px-4 md:px-6 py-1.5 md:py-2 rounded-xl text-sm md:text-xl font-bold">
Total Score: <AnimatedCounter from={newScore - (pointsEarned || 0)} to={newScore} />
</div>
</motion.div>
</motion.div>
</div>
{/* Bottom sheet for incorrect answers - includes button inside */}
{!isCorrect && (
<div className={`absolute bottom-0 left-0 right-0 overflow-hidden z-20 ${(isHost || isPresenter) ? 'pb-16 md:pb-20' : ''}`}>
<motion.div
initial={{ y: "100%" }}
animate={{ y: 0 }}
transition={{ delay: 0.5, type: 'spring' }}
className="bg-black/30 backdrop-blur-md p-4 md:p-6 pb-8 md:pb-12"
className="bg-black/30 backdrop-blur-md p-4 md:p-6 z-20 shrink-0"
>
{selectedOption && selectedOption.reason && (
<div className="mb-3 md:mb-4 pb-3 md:pb-4 border-b border-white/20">
@ -216,45 +218,44 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
</p>
</div>
)}
<p className="text-center text-xs md:text-sm font-bold uppercase tracking-widest mb-2 md:mb-4 opacity-70">The correct answer was</p>
<p className="text-center text-xs md:text-sm font-bold uppercase tracking-widest mb-2 md:mb-3 opacity-70">The correct answer was</p>
<div className="flex flex-col items-center gap-2 md:gap-3">
<div className="flex items-center gap-3 md:gap-4">
<div className={`${COLORS[correctOption.color]} p-2 md:p-3 rounded-lg md:rounded-xl shadow-lg`}>
<ShapeIcon className="w-5 h-5 md:w-6 md:h-6" fill="currentColor" />
</div>
<span className="text-xl md:text-2xl font-black">{correctOption.text}</span>
<span className="text-lg md:text-2xl font-black">{correctOption.text}</span>
</div>
{correctOption.reason && (
<p className="text-center text-xs md:text-sm opacity-80 max-w-md mt-1 md:mt-2">
<p className="text-center text-xs md:text-sm opacity-80 max-w-md">
{correctOption.reason}
</p>
)}
</div>
</motion.div>
</div>
)}
{/* Host participating gets the continue button */}
{isHost && onNext && (
{/* Continue button inside bottom sheet for incorrect answers */}
{showContinueButton && (
<motion.button
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.5 }}
onClick={onNext}
className="fixed bottom-6 left-1/2 -translate-x-1/2 bg-white text-gray-900 px-6 md:px-8 py-3 md:py-4 rounded-xl md:rounded-2xl text-base md:text-xl font-black shadow-[0_6px_0_rgba(0,0,0,0.3)] active:shadow-none active:translate-y-[6px] transition-all flex items-center gap-2 hover:bg-gray-100 z-30 cursor-pointer"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.7 }}
onClick={handleContinue}
className="mt-4 w-full bg-gray-900 text-white px-6 py-3 md:py-4 rounded-xl md:rounded-2xl text-base md:text-xl font-black shadow-[0_4px_0_rgba(0,0,0,0.5)] active:shadow-none active:translate-y-[4px] transition-all flex items-center justify-center gap-2 cursor-pointer"
>
Continue to Scoreboard
<ChevronRight className="w-5 h-5 md:w-7 md:h-7" strokeWidth={3} />
<ChevronRight className="w-5 h-5 md:w-6 md:h-6" strokeWidth={3} />
</motion.button>
)}
</motion.div>
)}
{/* Presenter (non-host) gets the continue button */}
{!isHost && isPresenter && onPresenterAdvance && (
{/* Continue button for correct answers - fixed at bottom */}
{isCorrect && showContinueButton && (
<motion.button
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.5 }}
onClick={onPresenterAdvance}
onClick={handleContinue}
className="fixed bottom-6 left-1/2 -translate-x-1/2 bg-white text-gray-900 px-6 md:px-8 py-3 md:py-4 rounded-xl md:rounded-2xl text-base md:text-xl font-black shadow-[0_6px_0_rgba(0,0,0,0.3)] active:shadow-none active:translate-y-[6px] transition-all flex items-center gap-2 hover:bg-gray-100 z-30 cursor-pointer"
>
Continue to Scoreboard