Heats.js (3780B)
1 import { lazy, useEffect, useState } from 'react' 2 import { useNavigate, generatePath } from 'react-router-dom' 3 import { supabase } from './supabaseClient' 4 5 const Auth = lazy(() => import('./Auth')) 6 7 async function addHeat(e) { 8 e.preventDefault() 9 10 // Read the form data 11 const formData = new FormData(e.target); 12 const formJson = Object.fromEntries(formData.entries()); 13 14 if (defaultsSet(formJson)) { 15 alert('Check data of the new heat, seems like the defaults') 16 return 17 } 18 19 // create new heat 20 const { error } = await supabase 21 .from('heats') 22 .insert({ 23 name: formJson.name, 24 location: formJson.location, 25 // planned_start is an empty string if unset 26 // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/time 27 planned_start: formJson.planned_start === '' ? null : formJson.planned_start 28 }) 29 30 if (error === null) { 31 window.location.reload() 32 } else { 33 alert('Failed to create new heat: ' + error.message) 34 } 35 } 36 37 export function defaultsSet({name, location}) { 38 return (name === 'Name' || location === 'Location') 39 } 40 41 function navigateToHeat(e, n, heatId) { 42 e.preventDefault() 43 n(generatePath('/startlist/:heatId', {heatId:heatId})) 44 } 45 46 async function deleteHeat(e, heatId, heatName) { 47 e.preventDefault() 48 49 if (window.confirm('Do you really want to delete heat "' + heatName + '"?')) { 50 await supabase 51 .from('heats') 52 .delete() 53 .eq('id', heatId) 54 window.location.reload() 55 } 56 } 57 58 function HeatForm({session}) { 59 const [loading, setLoading] = useState(false) 60 const [heats, setHeats] = useState([]) 61 62 const navigate = useNavigate() 63 64 useEffect(() => { 65 (async () => { 66 setLoading(true) 67 const heatList = await supabase.from('heats').select() 68 if (heatList.error === null) 69 setHeats(heatList.data) 70 setLoading(false) 71 })(); 72 }, []) 73 74 return ( 75 <div> 76 <h1>Heats and Startlists <button disabled={!loading}>{loading ? '🔄 loading' : ''}</button></h1> 77 <form method='post' onSubmit={addHeat}> 78 <table> 79 <thead> 80 <tr> 81 <th>Created at</th> 82 <th>Name</th> 83 <th>Location</th> 84 <th>Planned start</th> 85 <th>Startlist</th> 86 <th>New/delete</th> 87 </tr> 88 </thead> 89 <tbody> 90 {heats.map(h => ( 91 <tr key={h.id}> 92 <td className='right'>{new Date(h.created_at).toLocaleString()}</td> 93 <td>{h.name}</td> 94 <td>{h.location}</td> 95 <td className='right'>{h.planned_start}</td> 96 <td className='right'> 97 <button onClick={e => navigateToHeat(e, navigate, h.id)}>🏁 startlist</button> 98 </td> 99 <td className='right'><button onClick={e => deleteHeat(e, h.id, h.name)}>🗑️ delete</button></td> 100 </tr> 101 ))} 102 <tr> 103 <td className='right'><i>* required</i></td> 104 <td> 105 <input type='text' name='name' defaultValue='Name' /> * 106 </td> 107 <td> 108 <input type='text' name='location' defaultValue='Location' /> 109 </td> 110 <td className='right'> 111 <input 112 type='time' 113 name='planned_start' /> 114 </td> 115 <td></td> 116 <td className='right'> 117 <button type='submit'>➕ new</button> 118 </td> 119 </tr> 120 </tbody> 121 </table> 122 </form> 123 </div> 124 ) 125 } 126 127 function Heats({session}) { 128 return ( 129 <div> 130 {!session ? <Auth /> : <HeatForm session={session} />} 131 </div> 132 ) 133 } 134 135 export default Heats;