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 83353f5db8b953a2e09965846066a1ca91f21add
parent 1e2681bd081fc686d0520e51f3d9b6ee5ee391d6
Author: Andreas Gruhler <andreas.gruhler@adfinis.com>
Date:   Mon, 13 Mar 2023 19:21:35 +0100

feat: new heat from leaderboard

Diffstat:
Mschema/heats.sql | 7+++++++
Mschema/startlist.sql | 7+++++++
Msrc/Leaderboard.js | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/Rate.js | 3---
4 files changed, 69 insertions(+), 11 deletions(-)

diff --git a/schema/heats.sql b/schema/heats.sql @@ -65,6 +65,13 @@ ALTER TABLE ONLY public.heats -- +-- Name: heats Enable insert for authenticated users only; Type: POLICY; Schema: public; Owner: postgres +-- + +CREATE POLICY "Enable insert for authenticated users only" ON public.heats FOR INSERT TO authenticated WITH CHECK (true); + + +-- -- Name: heats Enable read access for all users; Type: POLICY; Schema: public; Owner: postgres -- diff --git a/schema/startlist.sql b/schema/startlist.sql @@ -80,6 +80,13 @@ ALTER TABLE ONLY public.startlist -- +-- Name: startlist Enable insert for authenticated users only; Type: POLICY; Schema: public; Owner: postgres +-- + +CREATE POLICY "Enable insert for authenticated users only" ON public.startlist FOR INSERT TO authenticated WITH CHECK (true); + + +-- -- Name: startlist Enable read access for all users; Type: POLICY; Schema: public; Owner: postgres -- diff --git a/src/Leaderboard.js b/src/Leaderboard.js @@ -1,5 +1,5 @@ import { supabase } from './supabaseClient' -import { Fragment, lazy, useEffect, useState } from 'react' +import { Fragment, useEffect, useState } from 'react' import Select from 'react-select' async function getStartlistForHeats(heatIds) { @@ -87,11 +87,45 @@ function rankByHeat(rankingComp) { } } +async function newHeatFromLeaderboard(e, leaderboard, rankingComp, newHeatSize, newHeatName) { + e.preventDefault() + + if (leaderboard.length === 0) { + // cannot create new heat from empty leaderboard + return + } + + // create new heat + const { data, error } = await supabase + .from('heats') + .insert({ name: newHeatName }) + .select() + + if (error !== null) { + alert('Failed to create new heat') + return + } + + let sortedBoard = leaderboard.sort(rankByHeat(rankingComp)) + for (let i = 0; i < newHeatSize && i < sortedBoard.length; i++ ) { + // add top N athletes from current leaderboard to new heat + await supabase + .from('startlist') + .insert({ heat: data[0].id, athlete: sortedBoard[i].athlete }) + } + + alert('Created new heat "' + newHeatName + '" with top ' + newHeatSize + ' athletes') +} + function Leaderboard() { - const [leaderboard, setLeaderboard] = useState([]); - const [heatSelection, setHeatSelection] = useState([{value: 0, label: ''}]); - const [heats, setHeats] = useState([]); - const [rankingComp, setRankingComp] = useState([{value: 0, label: ''}]); + const [leaderboard, setLeaderboard] = useState([]) + const [heatSelection, setHeatSelection] = useState([{value: 0, label: ''}]) + const [heats, setHeats] = useState([]) + const [rankingComp, setRankingComp] = useState([{value: 0, label: ''}]) + + // state for new heat from top N leaderboard + const [newHeatSize, setNewHeatSize] = useState(6) + const [newHeatName, setNewHeatName] = useState("Heat name") // add options to select or rank by heat let heatOpts = heats.map(h => { @@ -145,8 +179,6 @@ function Leaderboard() { <div className="Leaderboard"> <header> <div> - Startlist: - <Select /> Heats to display: <Select closeMenuOnSelect={false} @@ -161,7 +193,22 @@ function Leaderboard() { options={rankOpts} onChange={h => setRankingComp(h)} /> - Top N to new startlist: <input type="number" size="5" /><button>Level up!</button> + <form> + New heat from top <input + type="number" + size="5" + value={newHeatSize} + onChange={(e) => setNewHeatSize(e.target.value)} + />: + <input type="text" value={newHeatName} onChange={(e) => setNewHeatName(e.target.value)} /> + <button onClick={(e) => newHeatFromLeaderboard( + e, + leaderboard, + rankingComp, + newHeatSize, + newHeatName + )}>Create</button> + </form> </div> <h1>Leaderboard</h1> </header> diff --git a/src/Rate.js b/src/Rate.js @@ -12,9 +12,6 @@ function RatingForm(session) { } function Rate(session) { - - console.log(session) - return ( <div> {!session.session ? <Auth /> : <RatingForm key={session.session.user.id} session={session.session} />}