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 e68968cac97aed5e53bd8f67af0785016aa743f6
parent 0f683a96c79ecc2b74d35e5bde19fdf30cf731e7
Author: Andreas Gruhler <andreas.gruhler@adfinis.com>
Date:   Thu, 13 Apr 2023 22:04:53 +0200

feat(heats): create empty new heat

Diffstat:
Msrc/Athletes.js | 1-
Msrc/Heats.js | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
2 files changed, 83 insertions(+), 25 deletions(-)

diff --git a/src/Athletes.js b/src/Athletes.js @@ -25,7 +25,6 @@ async function addAthlete(e) { birthday: formJson.birthday ? formJson.birthday : null, school: formJson.school }) - .select() if (error === null) { window.location.reload() diff --git a/src/Heats.js b/src/Heats.js @@ -4,6 +4,45 @@ import { supabase } from './supabaseClient' const Auth = lazy(() => import('./Auth')) +async function addHeat(e) { + e.preventDefault() + + // Read the form data + const formData = new FormData(e.target); + const formJson = Object.fromEntries(formData.entries()); + + if (defaultsSet(formJson)) { + alert('Check data of the new heat, seems like the defaults') + return + } + + // create new heat + const { error } = await supabase + .from('heats') + .insert({ + name: formJson.name, + location: formJson.location, + // planned_start is an empty string if unset + // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/time + planned_start: formJson.planned_start === '' ? null : formJson.planned_start + }) + + if (error === null) { + window.location.reload() + } else { + alert('Failed to create new heat: ' + error.message) + } +} + +function defaultsSet({name, location}) { + return (name === 'Name' || location === 'Location') +} + +function navigateToHeat(e, n, heatId) { + e.preventDefault() + n(generatePath('/startlist/:heatId', {heatId:heatId})) +} + async function deleteHeat(e, heatId, heatName) { e.preventDefault() @@ -35,32 +74,52 @@ function HeatForm({session}) { return ( <div> <h1>Heats <button disabled={!loading}>{loading ? '🔄 loading' : ''}</button></h1> - <table> - <thead> - <tr> - <th>Created at</th> - <th>Name</th> - <th>Location</th> - <th>Planned start</th> - <th>Startlist</th> - <th>Delete</th> - </tr> - </thead> - <tbody> - {heats.map(h => ( - <tr key={h.id}> - <td className='right'>{new Date(h.created_at).toLocaleString()}</td> - <td>{h.name}</td> - <td>{h.location}</td> - <td className='right'>{h.planned_start}</td> + <form method='post' onSubmit={addHeat}> + <table> + <thead> + <tr> + <th>Created at</th> + <th>Name</th> + <th>Location</th> + <th>Planned start</th> + <th>Startlist</th> + <th>New/delete</th> + </tr> + </thead> + <tbody> + {heats.map(h => ( + <tr key={h.id}> + <td className='right'>{new Date(h.created_at).toLocaleString()}</td> + <td>{h.name}</td> + <td>{h.location}</td> + <td className='right'>{h.planned_start}</td> + <td className='right'> + <button onClick={e => navigateToHeat(e, navigate, h.id)}>🏁 startlist</button> + </td> + <td className='right'><button onClick={e => deleteHeat(e, h.id, h.name)}>🗑️ delete</button></td> + </tr> + ))} + <tr> + <td className='right'><i>* required</i></td> + <td> + <input type='text' name='name' defaultValue='Name' /> * + </td> + <td> + <input type='text' name='location' defaultValue='Location' /> + </td> + <td className='right'> + <input + type='time' + name='planned_start' /> + </td> + <td></td> <td className='right'> - <button onClick={e => navigate(generatePath('/startlist/:heatId', {heatId:h.id}))}>🏁 startlist</button> - </td> - <td className='right'><button onClick={e => deleteHeat(e, h.id, h.name)}>🗑️ delete</button></td> + <button type='submit'>➕ new</button> + </td> </tr> - ))} - </tbody> - </table> + </tbody> + </table> + </form> </div> ) }