Show loading spinner while awaiting backend score
This commit is contained in:
@@ -8,13 +8,13 @@ import {
|
||||
} from '@/components/ui/dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useGameStore } from '@/stores/game-store';
|
||||
import { useAuthStore } from '@/stores/auth-store';
|
||||
import { submitScore } from '@/api/leaderboards';
|
||||
import ScoreDisplay from './ScoreDisplay';
|
||||
import ShareableResult from './ShareableResult';
|
||||
import type { GameMode } from './ShareableResult';
|
||||
import CelebrationOverlay from './CelebrationOverlay';
|
||||
import { playSound } from '@/lib/sounds';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
|
||||
function formatElapsed(seconds: number): string {
|
||||
const m = Math.floor(seconds / 60);
|
||||
@@ -31,11 +31,15 @@ export default function GameCompletionModal() {
|
||||
const hintsUsed = useGameStore((s) => s.hintsUsed);
|
||||
const isDailyChallenge = useGameStore((s) => s.isDailyChallenge);
|
||||
const dailyChallengeDate = useGameStore((s) => s.dailyChallengeDate);
|
||||
const validationError = useGameStore((s) => s.validationError);
|
||||
const resetGame = useGameStore((s) => s.resetGame);
|
||||
const user = useAuthStore((s) => s.user);
|
||||
const navigate = useNavigate();
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
|
||||
const gameMode: GameMode = isDailyChallenge && dailyChallengeDate
|
||||
? { type: 'daily', date: dailyChallengeDate }
|
||||
: { type: 'freeplay' };
|
||||
|
||||
useEffect(() => {
|
||||
if (status === 'completed') {
|
||||
setShowModal(true);
|
||||
@@ -45,18 +49,6 @@ export default function GameCompletionModal() {
|
||||
if (isDailyChallenge && dailyChallengeDate) {
|
||||
localStorage.setItem('daily-completed-' + dailyChallengeDate, 'true');
|
||||
}
|
||||
|
||||
// Auto-submit score if logged in
|
||||
if (user && score) {
|
||||
submitScore(
|
||||
score.totalScore,
|
||||
score.linkCount,
|
||||
score.elapsedSeconds,
|
||||
hintsUsed,
|
||||
).catch(() => {
|
||||
// Silent fail — score is still shown locally
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setShowModal(false);
|
||||
}
|
||||
@@ -88,6 +80,17 @@ export default function GameCompletionModal() {
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="py-4">
|
||||
{!score && !validationError && (
|
||||
<div className="flex flex-col items-center gap-2 py-4">
|
||||
<Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
|
||||
<span className="text-sm text-muted-foreground">Calculating score...</span>
|
||||
</div>
|
||||
)}
|
||||
{validationError && (
|
||||
<div className="text-center text-sm text-destructive py-4">
|
||||
{validationError}
|
||||
</div>
|
||||
)}
|
||||
{score && (
|
||||
<>
|
||||
<ScoreDisplay score={score} />
|
||||
@@ -107,6 +110,7 @@ export default function GameCompletionModal() {
|
||||
chain={chain}
|
||||
movieATitle={movieA.title}
|
||||
movieBTitle={movieB.title}
|
||||
mode={gameMode}
|
||||
/>
|
||||
)}
|
||||
<div className="flex gap-3">
|
||||
|
||||
Reference in New Issue
Block a user