Score.jsx (3381B)
1 import { lazy, useEffect, useState } from 'react' 2 import { getStartlistForHeats } from './Leaderboard' 3 import Select from 'react-select' 4 import { supabase } from './supabaseClient' 5 6 const Auth = lazy(() => import('./Auth')) 7 8 async function updateScore(score, heatId, athleteId, userId) { 9 await supabase.from('scores').upsert({ 10 score: score, 11 heat: heatId, 12 athlete: athleteId, 13 judge: userId 14 }) 15 } 16 17 function ScoringForm({session}) { 18 const [heats, setHeats] = useState([]) 19 const [heatSelection, setHeatSelection] = useState(0) 20 const [athleteOpts, setAthleteOpts] = useState([]) 21 const [athleteSelection, setAthleteSelection] = useState(0) 22 const [score, setScore] = useState(0) 23 const [loading, setLoading] = useState(false) 24 25 // add options to select or rank by heat 26 const heatOpts = heats.map(h => { 27 return { 28 value: h.id, 29 label: h.name 30 } 31 }) 32 33 useEffect(() => { 34 (async () => { 35 setLoading(true) 36 const heatList = await supabase.from('heats').select() 37 setHeats(heatList.data) 38 39 const startlist = await getStartlistForHeats([heatSelection.value]) 40 41 if (startlist.error) { 42 setLoading(false) 43 return 44 } 45 46 setAthleteOpts(startlist.data.map(s => { 47 return { 48 value: s.athlete, 49 label: s.nr + " " + s.firstname + " " + (s.lastname ? s.lastname : "") 50 } 51 })) 52 53 if (heatSelection.value === undefined || athleteSelection.value === undefined) { 54 setLoading(false) 55 return 56 } 57 58 // check if existing score for heat and athlete exists 59 const currentScore = await supabase.from('scores').select() 60 .eq('heat', heatSelection.value) 61 .eq('athlete', athleteSelection.value) 62 .eq('judge', session.user.id) 63 64 if (score === 0 && currentScore.data?.length > 0) { 65 // fallback to current score when no new scoring took place 66 setScore(currentScore.data[0].score) 67 } else { 68 // store new score 69 updateScore(score, 70 heatSelection.value, 71 athleteSelection.value, 72 session.user.id) 73 } 74 setLoading(false) 75 })(); 76 }, [heatSelection, athleteSelection, session.user.id, score]); 77 78 return ( 79 <div> 80 <button disabled={!loading}>{loading ? '↺ loading' : ''}</button> 81 <table> 82 <thead> 83 <tr> 84 <th>Heat</th> 85 <th>Athlete</th> 86 <th>Score</th> 87 </tr> 88 </thead> 89 <tbody> 90 <tr> 91 <td data-title='Heat'> 92 <Select 93 options={heatOpts} 94 onChange={h => { setHeatSelection(h); setScore(0) }} 95 /> 96 </td> 97 <td data-title='Athlete'> 98 <Select 99 options={athleteOpts} 100 onChange={a => { setAthleteSelection(a); setScore(0) }} 101 /> 102 </td> 103 <td data-title='Score'> 104 <input 105 className='scoreInput' 106 type="number" 107 value={score} 108 onChange={(e) => setScore(e.target.value)} 109 /> 110 </td> 111 </tr> 112 </tbody> 113 </table> 114 </div> 115 ) 116 } 117 118 function Score({session}) { 119 return ( 120 <div> 121 {!session ? <Auth /> : <ScoringForm session={session} />} 122 </div> 123 ) 124 } 125 126 export default Score