Stay on reason screen
This commit is contained in:
parent
a7e37024f5
commit
3e7b89bcad
3 changed files with 28 additions and 8 deletions
2
App.tsx
2
App.tsx
|
|
@ -58,6 +58,7 @@ function App() {
|
||||||
hasAnswered,
|
hasAnswered,
|
||||||
lastPointsEarned,
|
lastPointsEarned,
|
||||||
nextQuestion,
|
nextQuestion,
|
||||||
|
showScoreboard,
|
||||||
currentCorrectShape,
|
currentCorrectShape,
|
||||||
selectedOption,
|
selectedOption,
|
||||||
currentPlayerScore,
|
currentPlayerScore,
|
||||||
|
|
@ -158,6 +159,7 @@ function App() {
|
||||||
correctOption={correctOpt}
|
correctOption={correctOpt}
|
||||||
selectedOption={selectedOption}
|
selectedOption={selectedOption}
|
||||||
role={role}
|
role={role}
|
||||||
|
onNext={showScoreboard}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { motion, useSpring, useTransform } from 'framer-motion';
|
import { motion, useSpring, useTransform } from 'framer-motion';
|
||||||
import { Check, X, Flame, Trophy } from 'lucide-react';
|
import { Check, X, Flame, ChevronRight } from 'lucide-react';
|
||||||
import { AnswerOption, Player, GameRole } from '../types';
|
import { AnswerOption, Player, GameRole } from '../types';
|
||||||
import { SHAPES, COLORS } from '../constants';
|
import { SHAPES, COLORS } from '../constants';
|
||||||
import confetti from 'canvas-confetti';
|
import confetti from 'canvas-confetti';
|
||||||
|
|
@ -34,6 +34,7 @@ interface RevealScreenProps {
|
||||||
correctOption: AnswerOption;
|
correctOption: AnswerOption;
|
||||||
selectedOption?: AnswerOption | null;
|
selectedOption?: AnswerOption | null;
|
||||||
role: GameRole;
|
role: GameRole;
|
||||||
|
onNext?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RevealScreen: React.FC<RevealScreenProps> = ({
|
export const RevealScreen: React.FC<RevealScreenProps> = ({
|
||||||
|
|
@ -43,7 +44,8 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
|
||||||
streak,
|
streak,
|
||||||
correctOption,
|
correctOption,
|
||||||
selectedOption,
|
selectedOption,
|
||||||
role
|
role,
|
||||||
|
onNext
|
||||||
}) => {
|
}) => {
|
||||||
const isHost = role === 'HOST';
|
const isHost = role === 'HOST';
|
||||||
|
|
||||||
|
|
@ -59,19 +61,18 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
|
||||||
}
|
}
|
||||||
}, [isCorrect, isHost]);
|
}, [isCorrect, isHost]);
|
||||||
|
|
||||||
// -- HOST VIEW --
|
|
||||||
if (isHost) {
|
if (isHost) {
|
||||||
const ShapeIcon = SHAPES[correctOption.shape];
|
const ShapeIcon = SHAPES[correctOption.shape];
|
||||||
const colorClass = COLORS[correctOption.color];
|
const colorClass = COLORS[correctOption.color];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center justify-center h-screen bg-gray-900 text-white p-8 relative overflow-hidden">
|
<div className="flex flex-col items-center justify-center h-screen bg-gray-900 text-white p-8 relative overflow-hidden">
|
||||||
<div className="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10"></div>
|
<div className="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10 pointer-events-none"></div>
|
||||||
|
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: -50 }}
|
initial={{ opacity: 0, y: -50 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
className="text-4xl font-bold uppercase tracking-widest mb-12 opacity-80"
|
className="text-4xl font-bold uppercase tracking-widest mb-12 opacity-80 relative z-10"
|
||||||
>
|
>
|
||||||
The correct answer is
|
The correct answer is
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
@ -80,7 +81,7 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
|
||||||
initial={{ scale: 0, rotate: -10 }}
|
initial={{ scale: 0, rotate: -10 }}
|
||||||
animate={{ scale: 1, rotate: 0 }}
|
animate={{ scale: 1, rotate: 0 }}
|
||||||
transition={{ type: "spring", bounce: 0.5 }}
|
transition={{ type: "spring", bounce: 0.5 }}
|
||||||
className={`${colorClass} p-12 rounded-[3rem] shadow-[0_20px_0_rgba(0,0,0,0.3)] flex flex-col items-center max-w-4xl w-full border-8 border-white/20`}
|
className={`${colorClass} p-12 rounded-[3rem] shadow-[0_20px_0_rgba(0,0,0,0.3)] flex flex-col items-center max-w-4xl w-full border-8 border-white/20 relative z-10`}
|
||||||
>
|
>
|
||||||
<div className="bg-black/20 p-6 rounded-full mb-6">
|
<div className="bg-black/20 p-6 rounded-full mb-6">
|
||||||
<ShapeIcon size={80} fill="currentColor" />
|
<ShapeIcon size={80} fill="currentColor" />
|
||||||
|
|
@ -99,6 +100,19 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
|
||||||
</motion.p>
|
</motion.p>
|
||||||
)}
|
)}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
|
{onNext && (
|
||||||
|
<motion.button
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ delay: 0.5 }}
|
||||||
|
onClick={onNext}
|
||||||
|
className="mt-12 bg-white text-gray-900 px-8 py-4 rounded-2xl 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 relative z-10 cursor-pointer"
|
||||||
|
>
|
||||||
|
Continue to Scoreboard
|
||||||
|
<ChevronRight size={28} strokeWidth={3} />
|
||||||
|
</motion.button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -241,7 +241,11 @@ export const useGame = () => {
|
||||||
if (timerRef.current) clearInterval(timerRef.current);
|
if (timerRef.current) clearInterval(timerRef.current);
|
||||||
setGameState('REVEAL');
|
setGameState('REVEAL');
|
||||||
broadcast({ type: 'TIME_UP', payload: {} });
|
broadcast({ type: 'TIME_UP', payload: {} });
|
||||||
setTimeout(() => setGameState('SCOREBOARD'), 4000);
|
};
|
||||||
|
|
||||||
|
const showScoreboard = () => {
|
||||||
|
setGameState('SCOREBOARD');
|
||||||
|
broadcast({ type: 'SHOW_SCOREBOARD', payload: { players: playersRef.current } });
|
||||||
};
|
};
|
||||||
|
|
||||||
const nextQuestion = () => {
|
const nextQuestion = () => {
|
||||||
|
|
@ -391,6 +395,6 @@ export const useGame = () => {
|
||||||
return {
|
return {
|
||||||
role, gameState, quiz, players, currentQuestionIndex, timeLeft, error, gamePin, hasAnswered, lastPointsEarned, currentCorrectShape, selectedOption, currentPlayerScore, currentStreak, currentPlayerId,
|
role, gameState, quiz, players, currentQuestionIndex, timeLeft, error, gamePin, hasAnswered, lastPointsEarned, currentCorrectShape, selectedOption, currentPlayerScore, currentStreak, currentPlayerId,
|
||||||
pendingQuizToSave, dismissSavePrompt,
|
pendingQuizToSave, dismissSavePrompt,
|
||||||
startQuizGen, startManualCreation, finalizeManualQuiz, loadSavedQuiz, joinGame, startGame: startHostGame, handleAnswer, nextQuestion
|
startQuizGen, startManualCreation, finalizeManualQuiz, loadSavedQuiz, joinGame, startGame: startHostGame, handleAnswer, nextQuestion, showScoreboard
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue