Fix host screen
This commit is contained in:
parent
0de5a3bd8c
commit
5242f8d1f3
3 changed files with 44 additions and 8 deletions
1
App.tsx
1
App.tsx
|
|
@ -299,6 +299,7 @@ function App() {
|
||||||
onNext={showScoreboard}
|
onNext={showScoreboard}
|
||||||
isPresenter={currentPlayerId === presenterId}
|
isPresenter={currentPlayerId === presenterId}
|
||||||
onPresenterAdvance={() => sendAdvance('SCOREBOARD')}
|
onPresenterAdvance={() => sendAdvance('SCOREBOARD')}
|
||||||
|
hostParticipates={gameConfig.hostParticipates}
|
||||||
/>
|
/>
|
||||||
) : currentPlayerName ? (
|
) : currentPlayerName ? (
|
||||||
<WaitingToRejoin
|
<WaitingToRejoin
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ interface RevealScreenProps {
|
||||||
onNext?: () => void;
|
onNext?: () => void;
|
||||||
isPresenter?: boolean;
|
isPresenter?: boolean;
|
||||||
onPresenterAdvance?: () => void;
|
onPresenterAdvance?: () => void;
|
||||||
|
hostParticipates?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RevealScreen: React.FC<RevealScreenProps> = ({
|
export const RevealScreen: React.FC<RevealScreenProps> = ({
|
||||||
|
|
@ -49,10 +50,13 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
|
||||||
role,
|
role,
|
||||||
onNext,
|
onNext,
|
||||||
isPresenter = false,
|
isPresenter = false,
|
||||||
onPresenterAdvance
|
onPresenterAdvance,
|
||||||
|
hostParticipates = false
|
||||||
}) => {
|
}) => {
|
||||||
const isHost = role === 'HOST';
|
const isHost = role === 'HOST';
|
||||||
const canAdvance = isHost || isPresenter;
|
const canAdvance = isHost || isPresenter;
|
||||||
|
// When host is participating, show client-style feedback view instead of presentation view
|
||||||
|
const showPlayerFeedback = !isHost || hostParticipates;
|
||||||
|
|
||||||
// Trigger confetti for correct answers
|
// Trigger confetti for correct answers
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -66,7 +70,8 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
|
||||||
}
|
}
|
||||||
}, [isCorrect, isHost]);
|
}, [isCorrect, isHost]);
|
||||||
|
|
||||||
if (isHost) {
|
// Host spectating (not participating) - show presentation view with big answer card
|
||||||
|
if (isHost && !hostParticipates) {
|
||||||
const ShapeIcon = SHAPES[correctOption.shape];
|
const ShapeIcon = SHAPES[correctOption.shape];
|
||||||
const colorClass = COLORS[correctOption.color];
|
const colorClass = COLORS[correctOption.color];
|
||||||
|
|
||||||
|
|
@ -196,7 +201,7 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
{!isCorrect && (
|
{!isCorrect && (
|
||||||
<div className={`absolute bottom-0 left-0 right-0 overflow-hidden z-20 ${isPresenter ? 'pb-20' : ''}`}>
|
<div className={`absolute bottom-0 left-0 right-0 overflow-hidden z-20 ${(isHost || isPresenter) ? 'pb-20' : ''}`}>
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ y: "100%" }}
|
initial={{ y: "100%" }}
|
||||||
animate={{ y: 0 }}
|
animate={{ y: 0 }}
|
||||||
|
|
@ -229,16 +234,31 @@ export const RevealScreen: React.FC<RevealScreenProps> = ({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isPresenter && onPresenterAdvance && (
|
{/* Host participating gets the continue button */}
|
||||||
|
{isHost && onNext && (
|
||||||
|
<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"
|
||||||
|
>
|
||||||
|
Continue to Scoreboard
|
||||||
|
<ChevronRight className="w-5 h-5 md:w-7 md:h-7" strokeWidth={3} />
|
||||||
|
</motion.button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Presenter (non-host) gets the continue button */}
|
||||||
|
{!isHost && isPresenter && onPresenterAdvance && (
|
||||||
<motion.button
|
<motion.button
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ delay: 0.5 }}
|
transition={{ delay: 0.5 }}
|
||||||
onClick={onPresenterAdvance}
|
onClick={onPresenterAdvance}
|
||||||
className="fixed bottom-6 left-1/2 -translate-x-1/2 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 z-30 cursor-pointer"
|
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
|
Continue to Scoreboard
|
||||||
<ChevronRight size={28} strokeWidth={3} />
|
<ChevronRight className="w-5 h-5 md:w-7 md:h-7" strokeWidth={3} />
|
||||||
</motion.button>
|
</motion.button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -544,11 +544,26 @@ export const useGame = (defaultGameConfig?: GameConfig) => {
|
||||||
await updateHostPeerId(session.pin, session.hostSecret!, peerId);
|
await updateHostPeerId(session.pin, session.hostSecret!, peerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hostData.gameState === 'LOBBY') {
|
// Determine which state to restore to
|
||||||
|
const savedState = hostData.gameState;
|
||||||
|
const restoredPlayers = hostData.players || [];
|
||||||
|
const allAnswered = restoredPlayers.length > 0 && restoredPlayers.every((p: Player) => p.lastAnswerCorrect !== null);
|
||||||
|
|
||||||
|
if (savedState === 'LOBBY') {
|
||||||
setGameState('LOBBY');
|
setGameState('LOBBY');
|
||||||
} else if (hostData.gameState === 'PODIUM') {
|
} else if (savedState === 'PODIUM') {
|
||||||
setGameState('PODIUM');
|
setGameState('PODIUM');
|
||||||
|
} else if (savedState === 'REVEAL') {
|
||||||
|
// Go directly to reveal screen - players may have already seen their results
|
||||||
|
setGameState('REVEAL');
|
||||||
|
} else if (savedState === 'SCOREBOARD') {
|
||||||
|
// Go directly to scoreboard
|
||||||
|
setGameState('SCOREBOARD');
|
||||||
|
} else if (savedState === 'QUESTION' && allAnswered) {
|
||||||
|
// All players answered while host was disconnected - go directly to reveal
|
||||||
|
setGameState('REVEAL');
|
||||||
} else {
|
} else {
|
||||||
|
// For QUESTION or COUNTDOWN states where not everyone answered, show HOST_RECONNECTED to let them resume
|
||||||
setGameState('HOST_RECONNECTED');
|
setGameState('HOST_RECONNECTED');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue