myheats

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

Judges.jsx (4373B)


      1 import { lazy, useEffect, useState } from 'react'
      2 import { exportJudgesToCSV } from './utils'
      3 const Auth = lazy(() => import('./Auth'))
      4 
      5 const api_uri = import.meta.env.VITE_API_URI
      6 const api_port = import.meta.env.VITE_API_PORT
      7 const locale = import.meta.env.VITE_LOCALE
      8 
      9 async function addJudge(e, session) {
     10   e.preventDefault()
     11 
     12   // Read the form data
     13   const formData = new FormData(e.target);
     14   const formJson = Object.fromEntries(formData.entries());
     15 
     16   // create new judge
     17   const res = await fetch(`${api_uri}:${api_port}/v1/leaderboard/addJudge`, {
     18     method: 'POST',
     19     headers: {
     20             'Content-Type': 'application/json',
     21             'Authorization': `Bearer ${session.auth.token}`,
     22     },
     23     body: JSON.stringify({
     24       "email": formJson.email,
     25       "firstname": formJson.firstname,
     26       "lastname": formJson.lastname
     27     }),
     28   })
     29   const { data, error } = await res.json()
     30   if (error) {
     31     alert('Failed to create new judge: ' + error.message)
     32   }
     33   window.location.reload()
     34 }
     35 
     36 async function deleteJudge(e, judgeId, email, session) {
     37   e.preventDefault()
     38 
     39   if (window.confirm(`Do you really want to delete judge ${email}?`)) {
     40     const res = await fetch(`${api_uri}:${api_port}/v1/leaderboard/removeJudge`, {
     41       method: 'POST',
     42       headers: {
     43               'Content-Type': 'application/json',
     44               'Authorization': `Bearer ${session.auth.token}`,
     45       },
     46       body: JSON.stringify({
     47         "judge_id": judgeId,
     48       }),
     49     })
     50     const { data, error } = await res.json()
     51     if (error) {
     52       alert('Failed to delete judge: ' + error.message)
     53     }
     54     window.location.reload()
     55   }
     56 }
     57 
     58 // export judges
     59 function ExportForm(judges) {
     60   return (
     61     <div className='exportForm'>
     62       <form method='post' onSubmit={e => exportJudgesToCSV(e, judges)}>
     63         <button type='submit'>&#9663; export</button>
     64       </form>
     65     </div>
     66   )
     67 }
     68 
     69 function JudgeForm({session}) {
     70   const [loading, setLoading] = useState(false)
     71   const [judges, setJudges] = useState([])
     72   const dateOptions = {
     73             year: "numeric",
     74             month: "2-digit",
     75             day: "2-digit",
     76         }
     77 
     78   useEffect(() => {
     79     (async () => {
     80       setLoading(true)
     81       const res = await fetch(`${api_uri}:${api_port}/v1/leaderboard/allJudges`, {
     82         headers: {
     83                 'Content-Type': 'application/json',
     84                 'Authorization': `Bearer ${session.auth.token}`,
     85         }
     86       })
     87       const { data, error } = await res.json()
     88       if (error) {
     89         console.log(error)
     90       } else {
     91         setJudges(data)
     92       }
     93       setLoading(false)
     94     })();
     95   }, [])
     96 
     97   return (
     98     <div className='JudgeForm'>
     99       <button disabled={!loading} className='loading'>↺ loading</button>
    100       <form method='post' onSubmit={e => addJudge(e, session)}>
    101         <table>
    102           <thead>
    103             <tr>
    104               <th>Created at</th>
    105               <th>Email *</th>
    106               <th>Firstname</th>
    107               <th>Lastname</th>
    108             </tr>
    109           </thead>
    110           <tbody>
    111             {judges.map(j => (
    112               <tr key={j.id}>
    113                 <td data-title='Created at' className='right'>{new Date(j.created_at).toLocaleDateString(locale, dateOptions)}</td>
    114                 <td data-title='Email'>{j.email}</td>
    115                 <td data-title='Firstname'>{j.firstname}</td>
    116                 <td data-title='Lastname'>{j.lastname}</td>
    117                 <td><button onClick={e => deleteJudge(e, j.id, j.email, session)}>&ndash; del</button></td>
    118               </tr>
    119             ))}
    120             <tr className='input'>
    121               <td className='right'><i>* required</i></td>
    122               <td data-title='Email *'>
    123                 <input type='text' name='email' />
    124               </td>
    125               <td data-title='Firstname'>
    126                 <input type='text' name='firstname' />
    127               </td>
    128               <td data-title='Lastname'>
    129                 <input type='text' name='lastname' />
    130               </td>
    131               <td>
    132                 <button type='submit'>&#43; new</button>
    133               </td>
    134             </tr>
    135           </tbody>
    136         </table>
    137       </form>
    138       <ExportForm judges={judges} />
    139     </div>
    140   )
    141 }
    142 
    143 function Judges({session}) {
    144     return (
    145       <div>
    146         {!session.auth ? <Auth /> : <JudgeForm session={session} />}
    147       </div>
    148     )
    149   }
    150   
    151 export default Judges