File size: 5,069 Bytes
7822956
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import React, { useState, useEffect } from 'react'
import Board from './components/Board'
import Score from './components/Score'
import AudioPlayer from './components/AudioPlayer'
import FinalJeopardy from './components/FinalJeopardy'

// Use relative URLs in production, localhost in development
const API_URL = import.meta.env.DEV ? 'http://localhost:3001' : ''

export default function App() {
  const [data, setData] = useState(null)
  const [showId, setShowId] = useState(null)
  const [showNumber, setShowNumber] = useState(null)
  const [approxYear, setApproxYear] = useState(null)
  const [round, setRound] = useState('jeopardy')
  const [score, setScore] = useState(0)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)
  const [finalData, setFinalData] = useState(null)
  const [showFinal, setShowFinal] = useState(false)

  const loadRandomGame = async () => {
    setLoading(true)
    setError(null)
    try {
      // Server will always scrape a new game (deletes old ones automatically)
      const response = await fetch(`${API_URL}/api/random-game`)
      if (!response.ok) throw new Error('Failed to load game')
      const gameData = await response.json()
      setData({ categories: gameData.categories })
      setShowId(gameData.showId)
      setShowNumber(gameData.showNumber)
      setApproxYear(gameData.approxYear)
      setRound('jeopardy')
      setScore(0)
    } catch (err) {
      console.error('Error loading game:', err)
      setError(err.message)
    } finally {
      setLoading(false)
    }
  }

  const loadDoubleJeopardy = async () => {
    if (!showId) return
    setLoading(true)
    try {
      const response = await fetch(`${API_URL}/api/game/${showId}/double`)
      if (!response.ok) throw new Error('Failed to load double jeopardy')
      const doubleData = await response.json()
      setData({ categories: doubleData.categories })
      setRound('double')
    } catch (err) {
      console.error('Error loading double jeopardy:', err)
      setError(err.message)
    } finally {
      setLoading(false)
    }
  }

  const loadFinalJeopardy = async () => {
    if (!showId) return
    setLoading(true)
    try {
      const response = await fetch(`${API_URL}/api/game/${showId}/final`)
      if (!response.ok) throw new Error('Failed to load final jeopardy')
      const finalData = await response.json()
      setFinalData(finalData)
      setShowFinal(true)
    } catch (err) {
      console.error('Error loading final jeopardy:', err)
      setError(err.message)
    } finally {
      setLoading(false)
    }
  }

  const handleFinalComplete = () => {
    setShowFinal(false)
    setFinalData(null)
    loadRandomGame()
  }

  useEffect(() => {
    loadRandomGame()
  }, [])

  if (loading) return <div className="p-8 text-white text-center text-2xl">Loading game...</div>
  if (error) return <div className="p-8 text-red-500 text-center text-2xl">Error: {error}</div>
  if (!data) return <div className="p-8 text-white text-center text-2xl">No game data</div>

  return (
    <div className="min-h-screen flex flex-col">
      <header className="bg-black border-b border-gray-800">
        <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between p-3 sm:p-4 gap-3 sm:gap-4">
          <div>
            <h1 className="text-2xl sm:text-3xl font-bold" style={{ color: 'var(--money-gold)' }}>
              JEOPARDY!
            </h1>
            {showNumber && (
              <p className="text-white text-xs sm:text-sm mt-1">
                Game #{showNumber} from {approxYear}
              </p>
            )}
          </div>
          <div className="flex flex-wrap items-center gap-2 sm:gap-4">
            <Score score={score} />
            <AudioPlayer />
            <button
              className="px-3 py-2 sm:px-4 sm:py-2 bg-gray-800 text-white rounded hover:bg-gray-700 text-sm sm:text-base min-h-[44px]"
              onClick={() => {
                if (round === 'jeopardy') {
                  loadDoubleJeopardy()
                } else if (round === 'double') {
                  loadFinalJeopardy()
                }
              }}
              disabled={showFinal}
            >
              {round === 'jeopardy' ? 'Next Round' : round === 'double' ? 'Final Jeopardy' : 'Next Round'}
            </button>
            <button
              className="px-3 py-2 sm:px-4 sm:py-2 bg-yellow-500 text-black rounded hover:bg-yellow-400 font-bold text-sm sm:text-base min-h-[44px]"
              onClick={loadRandomGame}
            >
              New Game
            </button>
          </div>
        </div>
      </header>

      <main className="flex-1 p-2 sm:p-4 md:p-6 bg-black">
        {showFinal && finalData ? (
          <FinalJeopardy 
            finalData={finalData} 
            score={score} 
            setScore={setScore}
            onComplete={handleFinalComplete}
          />
        ) : (
          <Board data={data} round={round} score={score} setScore={setScore} />
        )}
      </main>
    </div>
  )
}