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