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 (5632B)


      1 import { lazy, useEffect, useState } from 'react'
      2 import { useParams } from 'react-router-dom'
      3 const Auth = lazy(() => import('./Auth'))
      4 import { addAthleteToHeat } from './Leaderboard'
      5 import Select from 'react-select'
      6 
      7 const api_uri = import.meta.env.VITE_API_URI
      8 const api_port = import.meta.env.VITE_API_PORT
      9 
     10 async function addtoHeat(e, athlete, heatId, session) {
     11   e.preventDefault()
     12   try {
     13     await addAthleteToHeat(athlete.value, heatId, session)
     14     window.location.reload()
     15   } catch(error) {
     16     console.error(error)
     17   }
     18 }
     19 
     20 async function removeAthleteFromHeat(e, startlistId, athleteFirstName, athleteLastName, heatName, session) {
     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     const res = await fetch(`${api_uri}:${api_port}/v1/leaderboard/removeAthleteFromHeat`, {
     26       method: 'POST',
     27       headers: {
     28               'Content-Type': 'application/json',
     29               'Authorization': `Bearer ${session.auth.token}`,
     30       },
     31       body: JSON.stringify({
     32         "startlist_id": startlistId,
     33       }),
     34     })
     35     const { data, error } = await res.json()
     36     if (error) {
     37       console.error(error)
     38     }
     39     window.location.reload()
     40   }
     41 }
     42 
     43 async function startlistWithAthletes(heatId, session) {
     44   const res = await fetch(`${api_uri}:${api_port}/v1/leaderboard/startlistWithAthletes`, {
     45     method: 'POST',
     46     headers: {
     47             'Content-Type': 'application/json',
     48             'Authorization': `Bearer ${session.auth.token}`,
     49     },
     50     body: JSON.stringify({
     51       "heat_id": heatId,
     52     }),
     53   })
     54   const { data, error } = await res.json()
     55   if (error) {
     56     throw error
     57   }
     58   return data
     59 }
     60 
     61 async function getHeat(heatId, session) {
     62   const res = await fetch(`${api_uri}:${api_port}/v1/leaderboard/getHeat`, {
     63     method: 'POST',
     64     headers: {
     65             'Content-Type': 'application/json',
     66             'Authorization': `Bearer ${session.auth.token}`,
     67     },
     68     body: JSON.stringify({
     69       "heat_id": heatId,
     70     }),
     71   })
     72   const { data, error } = await res.json()
     73   if (error) {
     74     throw error
     75   }
     76   return data
     77 }
     78 
     79 function StartlistForm({heatId, session}) {
     80   const [heatName, setheatName] = useState("")
     81   const [heatLocation, setheatLocation] = useState("")
     82   const [heatStart, setheatStart] = useState("")
     83   const [startlist, setStartlist] = useState([])
     84   const [athleteOpts, setAthleteOpts] = useState([])
     85   const [selectedAthlete, setselectedAthlete] = useState({})
     86 
     87   const [loading, setLoading] = useState(false)
     88 
     89   useEffect(() => {
     90     (async () => {
     91       setLoading(true)
     92 
     93       try {
     94         const startlist = await startlistWithAthletes(heatId, session)
     95         setStartlist(startlist)
     96 
     97         const heat = await getHeat(heatId, session)
     98         setheatName(heat.name)
     99         setheatLocation(heat.location)
    100         setheatStart(heat.planned_start)
    101       } catch (error) {
    102         console.error(error)
    103       }
    104 
    105       const res = await fetch(`${api_uri}:${api_port}/v1/leaderboard/allAthletes`, {
    106         headers: {
    107                 'Content-Type': 'application/json',
    108                 'Authorization': `Bearer ${session.auth.token}`,
    109         },
    110       })
    111       const { data, error } = await res.json()
    112       if (error) {
    113         console.error(error)
    114       } else {
    115         let options = data.map(a => {
    116           return {
    117             value: a.id,
    118             label: a.nr + " " + a.firstname + " " + (a.lastname ? a.lastname : "")
    119           }
    120         })
    121         setAthleteOpts(options)
    122       }
    123       setLoading(false)
    124     })();
    125   }, [heatId])
    126 
    127   return (
    128     <div>
    129       <button disabled={!loading}>{loading ? '↺ loading' : ''}</button>
    130       <h1>Startlist #{heatId} {heatName}</h1>
    131       <div className='heatInfo'>
    132         <ul>
    133           <li><b>Location:</b> {heatLocation ? heatLocation : 'n/a'}</li>
    134           <li><b>Planned start:</b> {heatStart ? heatStart : 'n/a'}</li>
    135         </ul>
    136       </div>
    137       <table>
    138         <thead>
    139           <tr>
    140             <th>Start Nr.</th>
    141             <th>Firstname</th>
    142             <th>Lastname</th>
    143             <th>Birthday</th>
    144             <th>School</th>
    145             <th>Add/Delete</th>
    146           </tr>
    147         </thead>
    148         <tbody>
    149         {startlist.map(i => (
    150             <tr key={i.startlist_id}>
    151               <td data-title='Start Nr.' className='right'>{i.nr}</td>
    152               <td data-title='Firstname'>{i.firstname}</td>
    153               <td data-title='Lastname'>{i.lastname}</td>
    154               <td data-title='Birthday'>{i.birthday}</td>
    155               <td data-title='School'>{i.school}</td>
    156               <td><button onClick={e => removeAthleteFromHeat(
    157                 e,
    158                 i.startlist_id,
    159                 i.firstname,
    160                 i.lastname,
    161                 heatName,
    162 		session
    163               )}>&ndash; del</button></td>
    164             </tr>
    165           ))}
    166           <tr className='input'>
    167             <td data-title='Athlete' colSpan={5}>
    168               <Select
    169                 options={athleteOpts}
    170                 onChange={(e) => setselectedAthlete(e)}
    171               />
    172             </td>
    173             <td>
    174               <button onClick={(e) => addtoHeat(e, selectedAthlete, heatId, session)}>&#43; add</button>
    175             </td>
    176           </tr>
    177         </tbody>
    178       </table>
    179     </div>
    180   )
    181 }
    182 
    183 function Startlist({session}) {
    184     const { heatId } = useParams();
    185 
    186     return (
    187       <div>
    188         {!session.auth ? <Auth /> : <StartlistForm heatId={heatId} session={session} />}
    189       </div>
    190     )
    191   }
    192   
    193 export default Startlist