Felix Zieger commited on
Commit
444233f
1 Parent(s): 5835ecd
src/components/GameContainer.tsx CHANGED
@@ -11,6 +11,7 @@ import { GuessDisplay } from "./game/GuessDisplay";
11
  import { GameOver } from "./game/GameOver";
12
  import { useTranslation } from "@/hooks/useTranslation";
13
  import { LanguageContext } from "@/contexts/LanguageContext";
 
14
 
15
  type GameState = "welcome" | "theme-selection" | "building-sentence" | "showing-guess" | "game-over";
16
 
@@ -25,10 +26,18 @@ export const GameContainer = () => {
25
  const [successfulRounds, setSuccessfulRounds] = useState<number>(0);
26
  const [totalWords, setTotalWords] = useState<number>(0);
27
  const [usedWords, setUsedWords] = useState<string[]>([]);
 
28
  const { toast } = useToast();
29
  const t = useTranslation();
30
  const { language } = useContext(LanguageContext);
31
 
 
 
 
 
 
 
 
32
  useEffect(() => {
33
  const handleKeyPress = (e: KeyboardEvent) => {
34
  if (e.key === 'Enter') {
@@ -62,6 +71,7 @@ export const GameContainer = () => {
62
  setSuccessfulRounds(0);
63
  setTotalWords(0);
64
  setUsedWords([]);
 
65
  };
66
 
67
  const handleThemeSelect = async (theme: string) => {
@@ -130,6 +140,32 @@ export const GameContainer = () => {
130
  const sentenceString = finalSentence.join(' ');
131
  const guess = await guessWord(sentenceString, language);
132
  setAiGuess(guess);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  setGameState("showing-guess");
134
  } catch (error) {
135
  console.error('Error getting AI guess:', error);
@@ -231,6 +267,7 @@ export const GameContainer = () => {
231
  onPlayAgain={handlePlayAgain}
232
  currentScore={successfulRounds}
233
  avgWordsPerRound={getAverageWordsPerRound()}
 
234
  />
235
  ) : gameState === "game-over" ? (
236
  <GameOver
 
11
  import { GameOver } from "./game/GameOver";
12
  import { useTranslation } from "@/hooks/useTranslation";
13
  import { LanguageContext } from "@/contexts/LanguageContext";
14
+ import { supabase } from "@/integrations/supabase/client";
15
 
16
  type GameState = "welcome" | "theme-selection" | "building-sentence" | "showing-guess" | "game-over";
17
 
 
26
  const [successfulRounds, setSuccessfulRounds] = useState<number>(0);
27
  const [totalWords, setTotalWords] = useState<number>(0);
28
  const [usedWords, setUsedWords] = useState<string[]>([]);
29
+ const [sessionId, setSessionId] = useState<string>("");
30
  const { toast } = useToast();
31
  const t = useTranslation();
32
  const { language } = useContext(LanguageContext);
33
 
34
+ useEffect(() => {
35
+ // Generate a new session ID when starting a new game
36
+ if (gameState === "theme-selection") {
37
+ setSessionId(crypto.randomUUID());
38
+ }
39
+ }, [gameState]);
40
+
41
  useEffect(() => {
42
  const handleKeyPress = (e: KeyboardEvent) => {
43
  if (e.key === 'Enter') {
 
71
  setSuccessfulRounds(0);
72
  setTotalWords(0);
73
  setUsedWords([]);
74
+ setSessionId("");
75
  };
76
 
77
  const handleThemeSelect = async (theme: string) => {
 
140
  const sentenceString = finalSentence.join(' ');
141
  const guess = await guessWord(sentenceString, language);
142
  setAiGuess(guess);
143
+
144
+ // Save game result with session ID
145
+ try {
146
+ const { error } = await supabase
147
+ .from('game_results')
148
+ .insert({
149
+ target_word: currentWord,
150
+ description: sentenceString,
151
+ ai_guess: guess,
152
+ is_correct: guess.toLowerCase() === currentWord.toLowerCase(),
153
+ session_id: sessionId
154
+ });
155
+
156
+ if (error) {
157
+ console.error('Error saving game result:', error);
158
+ throw error;
159
+ }
160
+ } catch (error) {
161
+ console.error('Error in database operation:', error);
162
+ toast({
163
+ title: "Error",
164
+ description: "Failed to save game result. Please try again.",
165
+ variant: "destructive",
166
+ });
167
+ }
168
+
169
  setGameState("showing-guess");
170
  } catch (error) {
171
  console.error('Error getting AI guess:', error);
 
267
  onPlayAgain={handlePlayAgain}
268
  currentScore={successfulRounds}
269
  avgWordsPerRound={getAverageWordsPerRound()}
270
+ sessionId={sessionId}
271
  />
272
  ) : gameState === "game-over" ? (
273
  <GameOver
src/components/HighScoreBoard.tsx CHANGED
@@ -28,6 +28,7 @@ interface HighScore {
28
  score: number;
29
  avg_words_per_round: number;
30
  created_at: string;
 
31
  }
32
 
33
  interface HighScoreBoardProps {
@@ -35,6 +36,7 @@ interface HighScoreBoardProps {
35
  avgWordsPerRound: number;
36
  onClose: () => void;
37
  onPlayAgain: () => void;
 
38
  }
39
 
40
  const ITEMS_PER_PAGE = 5;
@@ -57,6 +59,7 @@ export const HighScoreBoard = ({
57
  currentScore,
58
  avgWordsPerRound,
59
  onClose,
 
60
  }: HighScoreBoardProps) => {
61
  const [playerName, setPlayerName] = useState("");
62
  const [isSubmitting, setIsSubmitting] = useState(false);
@@ -86,7 +89,6 @@ export const HighScoreBoard = ({
86
  });
87
 
88
  const handleSubmitScore = async () => {
89
- // Updated regex to allow letters with diacritics and special characters
90
  if (!playerName.trim() || !/^[\p{L}0-9]+$/u.test(playerName.trim())) {
91
  toast({
92
  title: t.leaderboard.error.invalidName,
@@ -138,6 +140,7 @@ export const HighScoreBoard = ({
138
  .update({
139
  score: currentScore,
140
  avg_words_per_round: avgWordsPerRound,
 
141
  })
142
  .eq("id", existingScore.id);
143
 
@@ -172,6 +175,7 @@ export const HighScoreBoard = ({
172
  player_name: playerName.trim(),
173
  score: currentScore,
174
  avg_words_per_round: avgWordsPerRound,
 
175
  });
176
 
177
  if (insertError) {
@@ -250,7 +254,6 @@ export const HighScoreBoard = ({
250
  placeholder={t.leaderboard.enterName}
251
  value={playerName}
252
  onChange={(e) => {
253
- // Allow letters with diacritics and numbers
254
  const value = e.target.value.replace(/[^a-zA-Z脌-每0-9]/g, "");
255
  setPlayerName(value);
256
  }}
 
28
  score: number;
29
  avg_words_per_round: number;
30
  created_at: string;
31
+ session_id: string;
32
  }
33
 
34
  interface HighScoreBoardProps {
 
36
  avgWordsPerRound: number;
37
  onClose: () => void;
38
  onPlayAgain: () => void;
39
+ sessionId: string;
40
  }
41
 
42
  const ITEMS_PER_PAGE = 5;
 
59
  currentScore,
60
  avgWordsPerRound,
61
  onClose,
62
+ sessionId,
63
  }: HighScoreBoardProps) => {
64
  const [playerName, setPlayerName] = useState("");
65
  const [isSubmitting, setIsSubmitting] = useState(false);
 
89
  });
90
 
91
  const handleSubmitScore = async () => {
 
92
  if (!playerName.trim() || !/^[\p{L}0-9]+$/u.test(playerName.trim())) {
93
  toast({
94
  title: t.leaderboard.error.invalidName,
 
140
  .update({
141
  score: currentScore,
142
  avg_words_per_round: avgWordsPerRound,
143
+ session_id: sessionId
144
  })
145
  .eq("id", existingScore.id);
146
 
 
175
  player_name: playerName.trim(),
176
  score: currentScore,
177
  avg_words_per_round: avgWordsPerRound,
178
+ session_id: sessionId
179
  });
180
 
181
  if (insertError) {
 
254
  placeholder={t.leaderboard.enterName}
255
  value={playerName}
256
  onChange={(e) => {
 
257
  const value = e.target.value.replace(/[^a-zA-Z脌-每0-9]/g, "");
258
  setPlayerName(value);
259
  }}
src/components/game/GuessDisplay.tsx CHANGED
@@ -20,6 +20,7 @@ interface GuessDisplayProps {
20
  onBack?: () => void;
21
  currentScore: number;
22
  avgWordsPerRound: number;
 
23
  }
24
 
25
  export const GuessDisplay = ({
@@ -31,6 +32,7 @@ export const GuessDisplay = ({
31
  onBack,
32
  currentScore,
33
  avgWordsPerRound,
 
34
  }: GuessDisplayProps) => {
35
  const isGuessCorrect = () => aiGuess.toLowerCase() === currentWord.toLowerCase();
36
  const isCheating = () => aiGuess === 'CHEATING';
@@ -145,6 +147,7 @@ export const GuessDisplay = ({
145
  setIsDialogOpen(false);
146
  onPlayAgain();
147
  }}
 
148
  />
149
  </DialogContent>
150
  </Dialog>
 
20
  onBack?: () => void;
21
  currentScore: number;
22
  avgWordsPerRound: number;
23
+ sessionId: string;
24
  }
25
 
26
  export const GuessDisplay = ({
 
32
  onBack,
33
  currentScore,
34
  avgWordsPerRound,
35
+ sessionId,
36
  }: GuessDisplayProps) => {
37
  const isGuessCorrect = () => aiGuess.toLowerCase() === currentWord.toLowerCase();
38
  const isCheating = () => aiGuess === 'CHEATING';
 
147
  setIsDialogOpen(false);
148
  onPlayAgain();
149
  }}
150
+ sessionId={sessionId}
151
  />
152
  </DialogContent>
153
  </Dialog>
src/integrations/supabase/types.ts CHANGED
@@ -16,6 +16,7 @@ export type Database = {
16
  description: string
17
  id: string
18
  is_correct: boolean
 
19
  target_word: string
20
  }
21
  Insert: {
@@ -24,6 +25,7 @@ export type Database = {
24
  description: string
25
  id?: string
26
  is_correct: boolean
 
27
  target_word: string
28
  }
29
  Update: {
@@ -32,6 +34,7 @@ export type Database = {
32
  description?: string
33
  id?: string
34
  is_correct?: boolean
 
35
  target_word?: string
36
  }
37
  Relationships: []
@@ -43,6 +46,7 @@ export type Database = {
43
  id: string
44
  player_name: string
45
  score: number
 
46
  }
47
  Insert: {
48
  avg_words_per_round: number
@@ -50,6 +54,7 @@ export type Database = {
50
  id?: string
51
  player_name: string
52
  score: number
 
53
  }
54
  Update: {
55
  avg_words_per_round?: number
@@ -57,6 +62,7 @@ export type Database = {
57
  id?: string
58
  player_name?: string
59
  score?: number
 
60
  }
61
  Relationships: []
62
  }
 
16
  description: string
17
  id: string
18
  is_correct: boolean
19
+ session_id: string
20
  target_word: string
21
  }
22
  Insert: {
 
25
  description: string
26
  id?: string
27
  is_correct: boolean
28
+ session_id?: string
29
  target_word: string
30
  }
31
  Update: {
 
34
  description?: string
35
  id?: string
36
  is_correct?: boolean
37
+ session_id?: string
38
  target_word?: string
39
  }
40
  Relationships: []
 
46
  id: string
47
  player_name: string
48
  score: number
49
+ session_id: string
50
  }
51
  Insert: {
52
  avg_words_per_round: number
 
54
  id?: string
55
  player_name: string
56
  score: number
57
+ session_id: string
58
  }
59
  Update: {
60
  avg_words_per_round?: number
 
62
  id?: string
63
  player_name?: string
64
  score?: number
65
+ session_id?: string
66
  }
67
  Relationships: []
68
  }