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 5d07234ebb3b637e9e8e964f25a761b1cdbc1b6b
parent 80fdd5ff69ad856fefa6e7196edb947e62f00dd2
Author: Andreas Gruhler <andreas.gruhler@adfinis.com>
Date:   Sun, 18 Aug 2024 13:17:24 +0200

feat(heats): export to csv

Diffstat:
Msrc/Heats.jsx | 13+++++++++++++
Msrc/Leaderboard.jsx | 4++--
Msrc/utils.js | 54++++++++++++++++++++++++++++++++++++++++--------------
3 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/src/Heats.jsx b/src/Heats.jsx @@ -1,6 +1,7 @@ import { lazy, useEffect, useState } from 'react' import { generatePath, Link } from 'react-router-dom' import { supabase } from './supabaseClient' +import { exportHeatsToCSV } from './utils' const Auth = lazy(() => import('./Auth')) @@ -41,6 +42,17 @@ async function deleteHeat(e, heatId, heatName) { } } +// export heats +function ExportForm({heats}) { + return ( + <div className='exportForm'> + <form method='post' onSubmit={e => exportHeatsToCSV(e)}> + <button type='submit'>&#9663; export</button> + </form> + </div> + ) +} + function HeatForm({session}) { const [loading, setLoading] = useState(false) const [heats, setHeats] = useState([]) @@ -99,6 +111,7 @@ function HeatForm({session}) { </tbody> </table> </form> + <ExportForm /> </div> ) } diff --git a/src/Leaderboard.jsx b/src/Leaderboard.jsx @@ -1,5 +1,5 @@ import { supabase } from './supabaseClient' -import { exportCSV, rankByHeat, getScores } from './utils' +import { exportLeaderboardToCSV, rankByHeat, getScores } from './utils' import { Fragment, useEffect, useState, useRef } from 'react' import Select from 'react-select' @@ -112,7 +112,7 @@ async function newHeatFromLeaderboard(e, {leaderboard, rankingComp, selectHeatRe function ExportForm({leaderboard, heatSelection, rankingComp}) { return ( <div className='exportForm'> - <form method='post' onSubmit={e => exportCSV( + <form method='post' onSubmit={e => exportLeaderboardToCSV( e, leaderboard, heatSelection, diff --git a/src/utils.js b/src/utils.js @@ -1,4 +1,25 @@ -export const exportCSV = async function(e, leaderboard, heatSelection, rankingComp) { +import { supabase } from './supabaseClient' + +export const exportHeatsToCSV = async function(e) { + e.preventDefault() + + const { data, error } = await supabase + .from('heats') + .select('created_at,name,location,planned_start') + .csv() + + if (error !== null) { + alert(error.message) + return + } else if (data.length === 0) { + alert('No heats yet, nothing to export') + return + } + + exportCSV(data, "heats") +} + +export const exportLeaderboardToCSV = async function(e, leaderboard, heatSelection, rankingComp) { e.preventDefault() if (leaderboard.length === 0) { @@ -32,19 +53,7 @@ export const exportCSV = async function(e, leaderboard, heatSelection, rankingCo + leaderboard[i].bestHeat + "," + leaderboard[i].worstHeat + "," + leaderboard[i].sum + "\n" } - // create blob from csv - const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }) - - // download blob - const url = URL.createObjectURL(blob) - const link = document.createElement('a') - link.href = url - link.download = "scores-" + new Date().toISOString() + ".csv" - document.body.appendChild(link) - link.click() - document.body.removeChild(link) - // let browser know not to keep the reference to the file - URL.revokeObjectURL(url) + exportCSV(csv, "scores") } // define the ranking logic @@ -84,3 +93,20 @@ export const getScores = function(i, h) { const scores = i.heats.find(heat => heat.heatId === h.value)?.scores?.map(s => s.score).join(" + ") return scores === "" ? 0 : scores } + +// export CSV as blob +const exportCSV = function(csv, fileSlug) { + // create blob from csv + const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }) + + // download blob + const url = URL.createObjectURL(blob) + const link = document.createElement('a') + link.href = url + link.download = fileSlug + "-" + new Date().toISOString() + ".csv" + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + // let browser know not to keep the reference to the file + URL.revokeObjectURL(url) +}