import { useState } from "react"; import { supabase } from "@/integrations/supabase/client"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useToast } from "@/components/ui/use-toast"; import { useTranslation } from "@/hooks/useTranslation"; import { ThemeFilter } from "./game/leaderboard/ThemeFilter"; import { ScoreSubmissionForm } from "./game/leaderboard/ScoreSubmissionForm"; import { ScoresTable } from "./game/leaderboard/ScoresTable"; import { LeaderboardHeader } from "./game/leaderboard/LeaderboardHeader"; import { LeaderboardPagination } from "./game/leaderboard/LeaderboardPagination"; import { getDailyGames } from "@/services/dailyGameService"; import { useNavigate } from "react-router-dom"; interface HighScore { id: string; player_name: string; score: number; avg_words_per_round: number; created_at: string; session_id: string; theme: string; game?: { language: string; }; game_id?: string; } interface HighScoreBoardProps { currentScore?: number; avgWordsPerRound?: number; onClose?: () => void; gameId?: string; sessionId?: string; onScoreSubmitted?: () => void; showThemeFilter?: boolean; initialTheme?: string; } const ITEMS_PER_PAGE = 5; export const HighScoreBoard = ({ currentScore = 0, avgWordsPerRound = 0, onClose, gameId = "", sessionId = "", onScoreSubmitted, showThemeFilter = true, initialTheme = "standard", }: HighScoreBoardProps) => { const [playerName, setPlayerName] = useState(""); const [isSubmitting, setIsSubmitting] = useState(false); const [hasSubmitted, setHasSubmitted] = useState(false); const [currentPage, setCurrentPage] = useState(1); const [selectedMode, setSelectedMode] = useState<'daily' | 'all-time'>('daily'); const { toast } = useToast(); const t = useTranslation(); const queryClient = useQueryClient(); const navigate = useNavigate(); const showScoreInfo = sessionId !== "" && currentScore > 0; const { data: highScores } = useQuery({ queryKey: ["highScores", selectedMode, gameId], queryFn: async () => { console.log("Fetching high scores for mode:", selectedMode, "gameId:", gameId); let query = supabase .from("high_scores") .select("*, game:games(language)") .order("score", { ascending: false }) .order("avg_words_per_round", { ascending: true }); if (gameId) { query = query.eq('game_id', gameId); console.log("Filtering scores by game_id:", gameId); } else if (selectedMode === 'daily') { const dailyGames = await getDailyGames(); const dailyGameIds = dailyGames.map(game => game.game_id); query = query.in('game_id', dailyGameIds); console.log("Filtering scores by daily game_ids:", dailyGameIds); } const { data, error } = await query; if (error) { console.error("Error fetching high scores:", error); throw error; } console.log("Fetched high scores:", data); return data as HighScore[]; }, }); const handleSubmitScore = async () => { if (!playerName.trim() || !/^[a-zA-ZÀ-ÿ0-9-]+$/u.test(playerName.trim())) { toast({ title: t.leaderboard.error.invalidName, description: t.leaderboard.error.invalidName, variant: "destructive", }); return; } if (currentScore < 1) { toast({ title: t.leaderboard.error.noRounds, description: t.leaderboard.error.noRounds, variant: "destructive", }); return; } if (hasSubmitted) { toast({ title: t.leaderboard.error.alreadySubmitted, description: t.leaderboard.error.alreadySubmitted, variant: "destructive", }); return; } setIsSubmitting(true); try { console.log("Submitting score via Edge Function..."); const { data, error } = await supabase.functions.invoke('submit-high-score', { body: { playerName: playerName.trim(), score: currentScore, avgWordsPerRound, sessionId, theme: initialTheme, gameId } }); if (error) { console.error("Error submitting score:", error); throw error; } console.log("Score submitted successfully:", data); if (data.success) { toast({ title: data.isUpdate ? t.leaderboard.scoreUpdated : t.leaderboard.scoreSubmitted, description: data.isUpdate ? t.leaderboard.scoreUpdatedDesc : t.leaderboard.scoreSubmittedDesc, }); setHasSubmitted(true); onScoreSubmitted?.(); setPlayerName(""); await queryClient.invalidateQueries({ queryKey: ["highScores"] }); } } catch (error) { console.error("Error submitting score:", error); toast({ title: t.leaderboard.error.submitError, description: t.leaderboard.error.submitError, variant: "destructive", }); } finally { setIsSubmitting(false); } }; const handleKeyDown = async (e: React.KeyboardEvent) => { if (e.key === 'Enter') { e.preventDefault(); await handleSubmitScore(); } }; const handlePlayGame = async (gameId: string) => { try { console.log("Creating new session for game:", gameId); const { data: session, error } = await supabase .from('sessions') .insert({ game_id: gameId }) .select() .single(); if (error) throw error; console.log("Session created:", session); navigate(`/game/${gameId}`); onClose?.(); } catch (error) { console.error('Error creating session:', error); toast({ title: t.game.error.title, description: t.game.error.description, variant: "destructive", }); } }; const totalPages = highScores ? Math.ceil(highScores.length / ITEMS_PER_PAGE) : 0; const startIndex = (currentPage - 1) * ITEMS_PER_PAGE; const paginatedScores = highScores?.slice(startIndex, startIndex + ITEMS_PER_PAGE); return (
{showThemeFilter && !gameId && ( )} {!hasSubmitted && currentScore > 0 && ( )} setCurrentPage(p => Math.max(1, p - 1))} onNextPage={() => setCurrentPage(p => Math.min(totalPages, p + 1))} />
); };