myheats

Live heats, scoring and leaderboard for sport events
git clone https://git.in0rdr.ch/myheats.git
Log | Files | Refs | README | LICENSE

Score.js (2730B)


      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 
     24   // add options to select or rank by heat
     25   const heatOpts = heats.map(h => {
     26     return {
     27       value: h.id,
     28       label: h.name
     29     }
     30   })
     31 
     32   useEffect(() => {
     33     (async () => {
     34       const heatList = await supabase.from('heats').select()
     35       setHeats(heatList.data)
     36 
     37       const startlist = await getStartlistForHeats([heatSelection.value])
     38 
     39       if (startlist.error)
     40         return
     41 
     42       setAthleteOpts(startlist.data.map(s => {
     43         return {
     44           value: s.athlete,
     45           label: s.nr + " " + s.firstname + " " + (s.lastname ? s.lastname : "")
     46         }
     47       }))
     48 
     49       if (heatSelection.value === undefined || athleteSelection.value === undefined)
     50         return
     51 
     52       // check if existing score for heat and athlete exists
     53       const currentScore = await supabase.from('scores').select()
     54         .eq('heat', heatSelection.value)
     55         .eq('athlete', athleteSelection.value)
     56         .eq('judge', session.user.id)
     57 
     58       if (score === 0 && currentScore.data?.length > 0) {
     59         // fallback to current score when no new scoring took place
     60         setScore(currentScore.data[0].score)
     61       } else {
     62         // store new score
     63         updateScore(score,
     64           heatSelection.value,
     65           athleteSelection.value,
     66           session.user.id)
     67       }
     68     })();
     69   }, [heatSelection, athleteSelection, session.user.id, score]);
     70 
     71   return (
     72     <div>
     73       <h1>Score Athletes</h1>
     74       Heat:
     75           <Select
     76             options={heatOpts}
     77             onChange={h => { setHeatSelection(h); setScore(0) }}
     78           />
     79       Athlete:
     80       <Select
     81             options={athleteOpts}
     82             onChange={a => { setAthleteSelection(a); setScore(0) }}
     83           />
     84       Score:
     85       <input
     86             type="number"
     87             size="5"
     88             value={score}
     89             onChange={(e) => setScore(e.target.value)}
     90           />
     91     </div>
     92   )
     93 }
     94 
     95 function Score({session}) {
     96   return (
     97     <div>
     98       {!session ? <Auth /> : <ScoringForm session={session} />}
     99     </div>
    100   )
    101 }
    102 
    103 export default Score