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 )}>– 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)}>+ 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