myheats

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

Startlist.jsx (4476B)


      1 import { lazy, useEffect, useState } from 'react'
      2 import { useParams } from 'react-router-dom'
      3 import Select from 'react-select'
      4 import { supabase } from './supabaseClient'
      5 
      6 const Auth = lazy(() => import('./Auth'))
      7 
      8 async function addAthleteToHeat(e, selectedAthlete, heatId) {
      9   e.preventDefault()
     10 
     11   const { error } = await supabase.from('startlist').upsert({
     12     athlete: selectedAthlete.value,
     13     heat: heatId
     14   })
     15 
     16   if (error === null)
     17     window.location.reload()
     18 }
     19 
     20 async function removeAthleteFromHeat(e, startlistId, athleteFirstName, athleteLastName, heatName) {
     21   e.preventDefault()
     22   const athleteName = athleteFirstName + (athleteLastName ? ' ' + athleteLastName : '')
     23 
     24   if (window.confirm('Do you really want to remove athlete "' + athleteName + '" from heat "' + heatName + '"?')) {
     25     await supabase
     26       .from('startlist')
     27       .delete()
     28       .eq('id', startlistId)
     29     window.location.reload()
     30   }
     31 }
     32 
     33 function StartlistForm({heatId}) {
     34   const [heatName, setheatName] = useState("")
     35   const [heatLocation, setheatLocation] = useState("")
     36   const [heatStart, setheatStart] = useState("")
     37   const [startlist, setStartlist] = useState([])
     38   const [athleteOpts, setAthleteOpts] = useState([])
     39   const [selectedAthlete, setselectedAthlete] = useState({})
     40 
     41   const [loading, setLoading] = useState(false)
     42 
     43   useEffect(() => {
     44     (async () => {
     45       setLoading(true)
     46 
     47       const startlistData = await supabase
     48         .from('startlist')
     49         .select(`
     50           id,
     51           heat,
     52           athlete (
     53             id,
     54             nr,
     55             firstname,
     56             lastname,
     57             birthday,
     58             school
     59           )
     60         `)
     61       .eq('heat', heatId)
     62 
     63       if (startlistData.error === null)
     64         setStartlist(startlistData.data)
     65 
     66       const heatData = await supabase
     67         .from('heats')
     68         .select('name, location, planned_start')
     69         .eq('id', heatId)
     70         .single()
     71 
     72       if (heatData.error === null) {
     73         setheatName(heatData.data.name)
     74         setheatLocation(heatData.data.location)
     75         setheatStart(heatData.data.planned_start)
     76       }
     77 
     78       const athleteList = await supabase.from('athletes').select()
     79       if (athleteList.error === null) {
     80         let options = athleteList.data.map(a => {
     81           return {
     82             value: a.id,
     83             label: a.nr + " " + a.firstname + " " + (a.lastname ? a.lastname : "")
     84           }
     85         })
     86         setAthleteOpts(options)
     87       }
     88 
     89       setLoading(false)
     90     })();
     91   }, [heatId])
     92 
     93   return (
     94     <div>
     95       <button disabled={!loading}>{loading ? '↺ loading' : ''}</button>
     96       <h1>Startlist #{heatId} {heatName}</h1>
     97       <div className='heatInfo'>
     98         <ul>
     99           <li><b>Location:</b> {heatLocation ? heatLocation : 'n/a'}</li>
    100           <li><b>Planned start:</b> {heatStart ? heatStart : 'n/a'}</li>
    101         </ul>
    102       </div>
    103       <table>
    104         <thead>
    105           <tr>
    106             <th>Start Nr.</th>
    107             <th>Firstname</th>
    108             <th>Lastname</th>
    109             <th>Birthday</th>
    110             <th>School</th>
    111             <th>Add/Delete</th>
    112           </tr>
    113         </thead>
    114         <tbody>
    115         {startlist.map(i => (
    116             <tr key={i.id}>
    117               <td data-title='Start Nr.' className='right'>{i.athlete.nr}</td>
    118               <td data-title='Firstname'>{i.athlete.firstname}</td>
    119               <td data-title='Lastname'>{i.athlete.lastname}</td>
    120               <td data-title='Birthday'>{i.athlete.birthday}</td>
    121               <td data-title='School'>{i.athlete.school}</td>
    122               <td><button onClick={e => removeAthleteFromHeat(
    123                 e,
    124                 i.id,
    125                 i.athlete.firstname,
    126                 i.athlete.lastname,
    127                 heatName
    128               )}>&ndash; del</button></td>
    129             </tr>
    130           ))}
    131           <tr className='input'>
    132             <td data-title='Athlete' colSpan={5}>
    133               <Select
    134                 options={athleteOpts}
    135                 onChange={(e) => setselectedAthlete(e)}
    136               />
    137             </td>
    138             <td>
    139               <button onClick={(e) => addAthleteToHeat(e, selectedAthlete, heatId)}>&#43; add</button>
    140             </td>
    141           </tr>
    142         </tbody>
    143       </table>
    144     </div>
    145   )
    146 }
    147 
    148 function Startlist({session}) {
    149     const { heatId } = useParams();
    150 
    151     return (
    152       <div>
    153         {!session ? <Auth /> : <StartlistForm heatId={heatId} />}
    154       </div>
    155     )
    156   }
    157   
    158 export default Startlist