myheats

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

commit e2f243718ec2cdb04267fba22b2167d02dba0bcc
parent ceeaa524f0dd0e9cc5859092c2c371003f390da2
Author: Andreas Gruhler <andreas.gruhler@adfinis.com>
Date:   Wed,  5 Apr 2023 00:21:10 +0200

feat(athletes): UI to delete athletes

Diffstat:
Msrc/App.js | 3+++
Asrc/Athletes.js | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 77 insertions(+), 0 deletions(-)

diff --git a/src/App.js b/src/App.js @@ -6,6 +6,7 @@ import { supabase } from './supabaseClient' const Rate = lazy(() => import('./Rate')); const Heats = lazy(() => import('./Heats')); +const Athletes = lazy(() => import('./Athletes')); const Auth = lazy(() => import('./Auth')); const Leaderboard = lazy(() => import('./Leaderboard')); @@ -19,6 +20,7 @@ function Layout({session}) { <li><Link to="/leaderboard">Leaderboard</Link></li> <li><Link to="/rate">Rate</Link></li> <li><Link to="/heats">Manage Heats</Link></li> + <li><Link to="/athletes">Manage Athletes</Link></li> {session ? <li><button onClick={() => supabase.auth.signOut()}>Sign out {session.user.email}</button></li> : ""} </ul> </nav> @@ -62,6 +64,7 @@ function App() { <Route path="/leaderboard" element={<Leaderboard />} /> <Route path="/rate" element={<Rate session={session} />} /> <Route path="/heats" element={<Heats session={session} />} /> + <Route path="/athletes" element={<Athletes session={session} />} /> <Route path="/auth" element={<Auth />} /> <Route path="*" element={<NoMatch />} /> </Route> diff --git a/src/Athletes.js b/src/Athletes.js @@ -0,0 +1,74 @@ +import { lazy, useEffect, useState } from 'react' +import { supabase } from './supabaseClient'; + +const Auth = lazy(() => import('./Auth')); + +async function deleteAthlete(e, athleteId, athleteFirstName, athleteLastName) { + e.preventDefault() + + const athleteName = athleteFirstName + (athleteLastName ? ' ' + athleteLastName : '') + if (window.confirm('Do you really want to delete athlete "' + athleteName + '"?')) { + await supabase + .from('athletes') + .delete() + .eq('id', athleteId) + window.location.reload() + } +} + +function AthleteForm({session}) { + const [loading, setLoading] = useState(false) + const [athletes, setAthletes] = useState([]) + + useEffect(() => { + (async () => { + setLoading(true) + const athleteList = await supabase.from('athletes').select() + if (athleteList.error === null) + setAthletes(athleteList.data) + setLoading(false) + })(); + }, []) + + return ( + <div> + <h1>Manage Athletes <button disabled={!loading}>{loading ? '🔄 loading' : ''}</button></h1> + <table> + <thead> + <tr> + <th>Created at</th> + <th>Nr</th> + <th>Firstname</th> + <th>Lastname</th> + <th>Birthday</th> + <th>School</th> + <th>Delete</th> + </tr> + </thead> + <tbody> + {athletes.map(a => ( + <tr key={a.id}> + <td className='right'>{new Date(a.created_at).toLocaleString()}</td> + <td className='right'>{a.nr}</td> + <td>{a.firstname}</td> + <td>{a.lastname}</td> + <td className='right'>{a.birthday}</td> + <td>{a.school}</td> + <td className='right'><button onClick={e => deleteAthlete(e, a.id, a.firstname, a.lastname)}>🗑️</button></td> + </tr> + ))} + </tbody> + </table> + </div> + ) +} + +function Athletes({session}) { + return ( + <div> + {!session ? <Auth /> : <AthleteForm key={session.user.id} session={session} />} + </div> + ) + } + + export default Athletes;