Skip to content

Commit 1f37e39

Browse files
fix(lightning): restore buzzer team activation in lightning round
- Update buzzer handler to set current_team_id when team buzzes in - Broadcast team-selected event to sync all clients - Clear active team when transitioning to lightning round - Properly manage team state during incorrect answers and question transitions
1 parent 4f2df45 commit 1f37e39

File tree

3 files changed

+139
-109
lines changed

3 files changed

+139
-109
lines changed

app/Livewire/LightningRound.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,15 @@ public function handleBuzzer($teamId)
6565

6666
if (count($this->buzzerOrder) === 1) {
6767
$this->currentAnsweringTeam = Team::find($teamId);
68+
69+
// Update game state to set active team
70+
$this->game->update(['current_team_id' => $teamId]);
71+
$this->game->refresh();
72+
6873
$this->dispatch('buzzer-accepted', teamId: $teamId);
74+
75+
// Broadcast to all clients that a team has buzzed in
76+
broadcast(new \App\Events\GameStateChanged($this->game->id, 'team-selected', ['teamId' => $teamId]));
6977
}
7078
}
7179

@@ -130,10 +138,18 @@ public function markLightningIncorrect()
130138
if (! empty($this->buzzerOrder)) {
131139
$nextTeamId = $this->buzzerOrder[0];
132140
$this->currentAnsweringTeam = Team::find($nextTeamId);
141+
142+
// Update game state to set next active team
143+
$this->game->update(['current_team_id' => $nextTeamId]);
144+
$this->game->refresh();
145+
133146
$this->dispatch('buzzer-accepted', teamId: $nextTeamId);
147+
broadcast(new \App\Events\GameStateChanged($this->game->id, 'team-selected', ['teamId' => $nextTeamId]));
134148
} else {
135-
// No more teams buzzed, move to next question
149+
// No more teams buzzed, clear active team and move to next question
136150
$this->currentAnsweringTeam = null;
151+
$this->game->update(['current_team_id' => null]);
152+
$this->game->refresh();
137153
$this->nextQuestion();
138154
}
139155

@@ -149,6 +165,9 @@ public function nextQuestion()
149165
]);
150166
}
151167

168+
// Clear active team when moving to next question
169+
$this->game->update(['current_team_id' => null]);
170+
152171
$nextQuestion = $this->game->lightningQuestions
153172
->where('is_answered', false)
154173
->sortBy('order_position')
@@ -161,7 +180,7 @@ public function nextQuestion()
161180
} else {
162181
// Lightning round complete
163182
$this->dispatch('lightning-round-complete');
164-
$this->game->update(['status' => 'finished']);
183+
$this->game->update(['status' => 'finished', 'current_team_id' => null]);
165184
$this->game->refresh();
166185
}
167186
}

app/Services/GameService.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,11 @@ public function transitionToLightningRound(int $gameId): void
9191
$game = Game::findOrFail($gameId);
9292

9393
DB::transaction(function () use ($game) {
94-
$game->update(['status' => 'lightning_round']);
94+
// Clear current team when transitioning to lightning round
95+
$game->update([
96+
'status' => 'lightning_round',
97+
'current_team_id' => null,
98+
]);
9599

96100
$allQuestions = config('jeopardy.lightning_questions', []);
97101

Lines changed: 113 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,169 +1,176 @@
1-
<div
2-
x-data="{
1+
<div
2+
x-data="{
33
mounted: false,
44
lightning: false,
5-
pulseEffect: false
6-
}"
5+
pulseEffect: false,
6+
createElectricParticles() {
7+
// Electric particle effect
8+
function randomInRange(min, max) {
9+
return Math.random() * (max - min) + min;
10+
}
11+
12+
// Continuous electric sparkles
13+
setInterval(() => {
14+
// Electric sparks from random positions
15+
window.confetti({
16+
particleCount: 4,
17+
startVelocity: 20,
18+
spread: 160,
19+
gravity: 0.3,
20+
ticks: 50,
21+
shapes: ['circle'],
22+
scalar: 0.6,
23+
drift: randomInRange(-0.5, 0.5),
24+
origin: {
25+
x: Math.random(),
26+
y: randomInRange(-0.1, 0.4)
27+
},
28+
colors: ['#fbbf24', '#fde68a', '#c084fc', '#60a5fa'],
29+
disableForReducedMotion: true
30+
});
31+
}, 200);
32+
33+
// Electric arc bursts
34+
setInterval(() => {
35+
const x = Math.random();
36+
window.confetti({
37+
particleCount: 20,
38+
startVelocity: 35,
39+
spread: 70,
40+
gravity: 0.6,
41+
ticks: 60,
42+
shapes: ['circle'],
43+
scalar: 0.5,
44+
origin: { x: x, y: -0.1 },
45+
colors: ['#fbbf24', '#e9d5ff', '#60a5fa'],
46+
disableForReducedMotion: true
47+
});
48+
}, 2000);
49+
50+
// Side electric streams
51+
setInterval(() => {
52+
// Left side
53+
window.confetti({
54+
particleCount: 10,
55+
startVelocity: 25,
56+
angle: 45,
57+
spread: 30,
58+
gravity: 0.4,
59+
ticks: 45,
60+
shapes: ['circle'],
61+
scalar: 0.5,
62+
origin: { x: 0, y: randomInRange(0.3, 0.7) },
63+
colors: ['#a78bfa', '#fbbf24'],
64+
disableForReducedMotion: true
65+
});
66+
// Right side
67+
window.confetti({
68+
particleCount: 10,
69+
startVelocity: 25,
70+
angle: 135,
71+
spread: 30,
72+
gravity: 0.4,
73+
ticks: 45,
74+
shapes: ['circle'],
75+
scalar: 0.5,
76+
origin: { x: 1, y: randomInRange(0.3, 0.7) },
77+
colors: ['#a78bfa', '#fbbf24'],
78+
disableForReducedMotion: true
79+
});
80+
}, 3000);
81+
}
82+
}"
783
x-init="
884
mounted = true;
85+
// Start electric particles
86+
createElectricParticles();
87+
988
// Create lightning effect
1089
setInterval(() => {
1190
lightning = true;
1291
setTimeout(() => lightning = false, 200);
1392
}, 3000);
93+
1494
// Pulse effect
1595
setInterval(() => {
1696
pulseEffect = !pulseEffect;
1797
}, 1000);
1898
"
1999
class="min-h-screen bg-gradient-to-br from-purple-900 via-indigo-900 to-black relative overflow-hidden">
20-
100+
21101
<!-- Lightning Background Effect -->
22102
<div class="absolute inset-0 pointer-events-none">
23-
<!-- Electric particles -->
24-
<div class="absolute inset-0">
25-
@for($i = 0; $i < 20; $i++)
26-
<div
27-
class="absolute w-1 h-1 bg-yellow-400 rounded-full animate-float-{{ $i % 5 }}"
28-
style="left: {{ rand(0, 100) }}%; top: {{ rand(0, 100) }}%; animation-delay: {{ $i * 0.2 }}s">
29-
</div>
30-
@endfor
31-
</div>
32-
33-
<!-- Lightning Strike Effect -->
34-
<div
35-
x-show="lightning"
36-
x-transition:enter="transition ease-out duration-100"
37-
x-transition:enter-start="opacity-0"
38-
x-transition:enter-end="opacity-100"
39-
x-transition:leave="transition ease-in duration-100"
40-
x-transition:leave-start="opacity-100"
41-
x-transition:leave-end="opacity-0"
42-
class="absolute inset-0 bg-gradient-to-b from-purple-400/20 via-yellow-400/10 to-transparent">
43-
</div>
103+
<!-- Canvas confetti replaces static particles -->
44104
</div>
45-
105+
46106
@if($game && $currentQuestion)
47107
<script>
48108
window.gameId = {{ $game->id }};
49109
</script>
50-
110+
51111
<div class="relative container mx-auto px-4 py-8">
52112
<!-- Title with Electric Effect -->
53-
<div
113+
<div
54114
x-show="mounted"
55115
x-transition:enter="transition ease-out duration-1000"
56116
x-transition:enter-start="opacity-0 scale-150"
57117
x-transition:enter-end="opacity-100 scale-100"
58118
class="text-center mb-8">
59119
<h1 class="text-6xl md:text-7xl font-black relative inline-block">
60-
<span class="absolute inset-0 blur-xl bg-gradient-to-r from-purple-400 via-pink-400 to-yellow-400 opacity-75 animate-pulse"></span>
61-
<span class="relative bg-clip-text text-transparent bg-gradient-to-r from-purple-400 via-pink-400 to-yellow-400">
120+
<span
121+
class="absolute inset-0 blur-xl bg-gradient-to-r from-purple-400 via-pink-400 to-yellow-400 opacity-75 animate-pulse"></span>
122+
<span
123+
class="relative bg-clip-text text-transparent bg-gradient-to-r from-purple-400 via-pink-400 to-yellow-400">
62124
⚡ LIGHTNING ROUND ⚡
63125
</span>
64126
</h1>
65127
<div class="mt-4 text-xl text-purple-300 tracking-[0.5em] uppercase animate-pulse">
66128
Rapid Fire Mode
67129
</div>
68130
</div>
69-
131+
70132
<!-- Team Scoreboard with Glow -->
71-
<div
133+
<div
72134
x-show="mounted"
73135
x-transition:enter="transition ease-out duration-1000 delay-200"
74136
x-transition:enter-start="opacity-0 translate-y-10"
75-
x-transition:enter-end="opacity-100 translate-y-0">
76-
<livewire:team-scoreboard :game-id="$game->id" />
137+
x-transition:enter-end="opacity-100 translate-y-0"
138+
class="mb-8">
139+
<livewire:team-scoreboard :game-id="$game->id"/>
77140
</div>
78-
79-
141+
142+
80143
<!-- Current Question with Electric Border -->
81-
<div
144+
<div
82145
x-show="mounted"
83146
x-transition:enter="transition ease-out duration-700 delay-600"
84147
x-transition:enter-start="opacity-0 scale-95 rotate-3"
85148
x-transition:enter-end="opacity-100 scale-100 rotate-0"
86-
class="relative max-w-5xl mx-auto mb-8">
87-
149+
class="relative max-w-5xl mx-auto mt-8">
150+
88151
<!-- Animated Border -->
89-
<div class="absolute -inset-1 bg-gradient-to-r from-purple-600 via-pink-600 to-yellow-600 rounded-2xl blur opacity-75 animate-pulse"></div>
90-
152+
<div
153+
class="absolute -inset-1 bg-gradient-to-r from-purple-600 via-pink-600 to-yellow-600 rounded-2xl blur opacity-75 animate-pulse"></div>
154+
91155
<!-- Question Card -->
92-
<div class="relative backdrop-blur-xl bg-gradient-to-br from-purple-900/90 to-indigo-900/90 rounded-2xl p-12 border-2 border-white/20 shadow-2xl">
156+
<div
157+
class="relative backdrop-blur-xl bg-gradient-to-br from-purple-900/90 to-indigo-900/90 rounded-2xl p-12 border-2 border-white/20 shadow-2xl">
93158
<div class="text-center">
94-
<div class="text-lg text-purple-300 mb-4 uppercase tracking-wider">Quick! Answer this:</div>
95159
<p class="text-3xl md:text-5xl font-bold text-white leading-tight animate-pulse">
96160
{{ $currentQuestion->question_text }}
97161
</p>
98162
</div>
99-
100-
<!-- Lightning Bolt Decorations -->
101-
<div class="absolute -top-6 -left-6 text-4xl animate-bounce">⚡</div>
102-
<div class="absolute -top-6 -right-6 text-4xl animate-bounce" style="animation-delay: 0.5s">⚡</div>
103-
<div class="absolute -bottom-6 -left-6 text-4xl animate-bounce" style="animation-delay: 1s">⚡</div>
104-
<div class="absolute -bottom-6 -right-6 text-4xl animate-bounce" style="animation-delay: 1.5s">⚡</div>
105163
</div>
106164
</div>
107-
108-
<!-- Buzzer Order Display with Animation -->
109-
@if(count($buzzerOrder) > 0)
110-
<div
111-
x-show="mounted"
112-
x-transition:enter="transition ease-out duration-500"
113-
x-transition:enter-start="opacity-0 translate-y-4"
114-
x-transition:enter-end="opacity-100 translate-y-0"
115-
class="max-w-4xl mx-auto mb-8">
116-
<h3 class="text-xl text-center mb-4 text-purple-300">Buzzer Order:</h3>
117-
<div class="flex justify-center gap-3 flex-wrap">
118-
@foreach($buzzerOrder as $index => $teamId)
119-
@php
120-
$team = $game->teams->find($teamId);
121-
@endphp
122-
@if($team)
123-
<div
124-
class="relative group transform transition-all duration-300 hover:scale-110"
125-
style="animation-delay: {{ $index * 0.1 }}s">
126-
<div class="absolute -inset-0.5 bg-gradient-to-r from-purple-600 to-pink-600 rounded-lg blur opacity-50 group-hover:opacity-100 transition duration-200"></div>
127-
<div
128-
class="relative px-4 py-2 rounded-lg backdrop-blur-lg bg-black/50 border"
129-
style="border-color: {{ $team->color_hex }}">
130-
<span class="font-bold" style="color: {{ $team->color_hex }}">
131-
{{ $index + 1 }}. {{ $team->name }}
132-
</span>
133-
</div>
134-
</div>
135-
@endif
136-
@endforeach
137-
</div>
138-
</div>
139-
@endif
140-
141-
<!-- Current Answering Team with Spotlight Effect -->
142-
@if($currentAnsweringTeam)
143-
<div
144-
x-show="mounted"
145-
x-transition:enter="transition ease-out duration-500"
146-
x-transition:enter-start="opacity-0 scale-0"
147-
x-transition:enter-end="opacity-100 scale-100"
148-
class="text-center mb-8">
149-
<div class="relative inline-block">
150-
<div class="absolute inset-0 blur-3xl opacity-50" style="background-color: {{ $currentAnsweringTeam->color_hex }}"></div>
151-
<div class="relative text-4xl font-black animate-pulse" style="color: {{ $currentAnsweringTeam->color_hex }}">
152-
{{ $currentAnsweringTeam->name }} is answering!
153-
</div>
154-
</div>
155-
</div>
156-
@endif
157-
158165
</div>
159-
166+
160167
<!-- Buzzer Listener -->
161-
<livewire:buzzer-listener :game-id="$game->id" />
162-
168+
<livewire:buzzer-listener :game-id="$game->id"/>
169+
163170
@include('partials.buzzer-audio')
164171
@else
165172
<div class="flex items-center justify-center h-screen">
166-
<div
173+
<div
167174
x-show="mounted"
168175
x-transition:enter="transition ease-out duration-700"
169176
x-transition:enter-start="opacity-0 scale-75"
@@ -174,4 +181,4 @@ class="text-center backdrop-blur-lg bg-black/50 rounded-2xl p-12 border border-p
174181
</div>
175182
</div>
176183
@endif
177-
</div>
184+
</div>

0 commit comments

Comments
 (0)