dev-comp #72
@ -1,6 +1,6 @@
|
|||||||
import {createContext, useContext, useReducer} from "react";
|
import {createContext, useContext, useReducer} from "react";
|
||||||
|
|
||||||
const PubAffContext = createContext({next: [], c1: undefined, c2: undefined, showScore: true, timeCb: undefined});
|
const PubAffContext = createContext({next: [], c1: undefined, c2: undefined, showScore: true, timeCb: undefined, scoreRouge: 0, scoreBleu: 0});
|
||||||
const PubAffDispatchContext = createContext(() => {
|
const PubAffDispatchContext = createContext(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ function CupImg() {
|
|||||||
alt=""/>
|
alt=""/>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CategorieSelect({catId, setCatId}) {
|
export function CategorieSelect({catId, setCatId, menuActions}) {
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
const {data: cats, setData: setCats} = useRequestWS('getAllCategory', {}, setLoading);
|
const {data: cats, setData: setCats} = useRequestWS('getAllCategory', {}, setLoading);
|
||||||
const {dispatch} = useWS();
|
const {dispatch} = useWS();
|
||||||
@ -41,11 +41,11 @@ export function CategorieSelect({catId, setCatId}) {
|
|||||||
<option key={c.id} value={c.id}>{c.name}</option>))}
|
<option key={c.id} value={c.id}>{c.name}</option>))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
{catId !== -1 && <CMTMatchPanel catId={catId} cat={cat}/>}
|
{catId !== -1 && <CMTMatchPanel catId={catId} cat={cat} menuActions={menuActions}/>}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
function CMTMatchPanel({catId, cat}) {
|
function CMTMatchPanel({catId, cat, menuActions}) {
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
const {sendRequest, dispatch} = useWS();
|
const {sendRequest, dispatch} = useWS();
|
||||||
const [trees, setTrees] = useState([]);
|
const [trees, setTrees] = useState([]);
|
||||||
@ -117,10 +117,10 @@ function CMTMatchPanel({catId, cat}) {
|
|||||||
}
|
}
|
||||||
}, [catId]);
|
}, [catId]);
|
||||||
|
|
||||||
return <ListMatch cat={cat} matches={matches} trees={trees}/>
|
return <ListMatch cat={cat} matches={matches} trees={trees} menuActions={menuActions}/>
|
||||||
}
|
}
|
||||||
|
|
||||||
function ListMatch({cat, matches, trees}) {
|
function ListMatch({cat, matches, trees, menuActions}) {
|
||||||
const [type, setType] = useState(1);
|
const [type, setType] = useState(1);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -146,16 +146,16 @@ function ListMatch({cat, matches, trees}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{type === 1 && <>
|
{type === 1 && <>
|
||||||
<MatchList matches={matches} cat={cat}/>
|
<MatchList matches={matches} cat={cat} menuActions={menuActions}/>
|
||||||
</>}
|
</>}
|
||||||
|
|
||||||
{type === 2 && <>
|
{type === 2 && <>
|
||||||
<BuildTree treeData={trees} matches={matches}/>
|
<BuildTree treeData={trees} matches={matches} menuActions={menuActions}/>
|
||||||
</>}
|
</>}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
function MatchList({matches, cat}) {
|
function MatchList({matches, cat, menuActions}) {
|
||||||
const [activeMatch, setActiveMatch] = useState(null)
|
const [activeMatch, setActiveMatch] = useState(null)
|
||||||
const [lice, setLice] = useState(localStorage.getItem("cm_lice") || "A")
|
const [lice, setLice] = useState(localStorage.getItem("cm_lice") || "A")
|
||||||
const publicAffDispatch = usePubAffDispatch();
|
const publicAffDispatch = usePubAffDispatch();
|
||||||
@ -249,11 +249,11 @@ function MatchList({matches, cat}) {
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{activeMatch && <LoadingProvider><ScorePanel matchId={activeMatch} match={match}/></LoadingProvider>}
|
{activeMatch && <LoadingProvider><ScorePanel matchId={activeMatch} match={match} menuActions={menuActions}/></LoadingProvider>}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
function BuildTree({treeData, matches}) {
|
function BuildTree({treeData, matches, menuActions}) {
|
||||||
const scrollRef = useRef(null)
|
const scrollRef = useRef(null)
|
||||||
const [currentMatch, setCurrentMatch] = useState(null)
|
const [currentMatch, setCurrentMatch] = useState(null)
|
||||||
const {getComb} = useCombs()
|
const {getComb} = useCombs()
|
||||||
@ -320,11 +320,12 @@ function BuildTree({treeData, matches}) {
|
|||||||
matchSelect={currentMatch?.matchSelect} matchNext={currentMatch?.matchNext} size={23}/>
|
matchSelect={currentMatch?.matchSelect} matchNext={currentMatch?.matchNext} size={23}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{currentMatch?.matchSelect && <LoadingProvider><ScorePanel matchId={currentMatch?.matchSelect} match={match}/></LoadingProvider>}
|
{currentMatch?.matchSelect &&
|
||||||
|
<LoadingProvider><ScorePanel matchId={currentMatch?.matchSelect} match={match} menuActions={menuActions}/></LoadingProvider>}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
function ScorePanel({matchId, match}) {
|
function ScorePanel({matchId, match, menuActions}) {
|
||||||
const {sendRequest} = useWS()
|
const {sendRequest} = useWS()
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
|
|
||||||
@ -335,6 +336,21 @@ function ScorePanel({matchId, match}) {
|
|||||||
const scoreRef = useRef([])
|
const scoreRef = useRef([])
|
||||||
const lastScoreClick = useRef(null)
|
const lastScoreClick = useRef(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
menuActions.current.saveScore = (scoreRed, scoreBlue) => {
|
||||||
|
const maxRound = (Math.max(...match.scores.map(s => s.n_round), -1) + 1) || 0;
|
||||||
|
const newScore = {n_round: maxRound, s1: scoreRed, s2: scoreBlue};
|
||||||
|
toast.promise(sendRequest('updateMatchScore', {matchId: matchId, ...newScore}),
|
||||||
|
{
|
||||||
|
pending: 'Sauvegarde du score...',
|
||||||
|
success: 'Score sauvegardé !',
|
||||||
|
error: 'Erreur lors de la sauvegarde du score'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return () => menuActions.current.saveScore = undefined;
|
||||||
|
}, [matchId])
|
||||||
|
|
||||||
const handleScoreClick = (e, round, comb) => {
|
const handleScoreClick = (e, round, comb) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const tableRect = tableRef.current.getBoundingClientRect();
|
const tableRect = tableRef.current.getBoundingClientRect();
|
||||||
|
|||||||
51
src/main/webapp/src/pages/competition/editor/CMTPoint.jsx
Normal file
51
src/main/webapp/src/pages/competition/editor/CMTPoint.jsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import {useEffect, useState} from "react";
|
||||||
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
|
import {faChevronDown, faChevronUp} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import {usePubAffDispatch} from "../../../hooks/useExternalWindow.jsx";
|
||||||
|
|
||||||
|
export function PointPanel({menuActions}) {
|
||||||
|
const [revers, setRevers] = useState(false)
|
||||||
|
const [scoreRouge, setScoreRouge] = useState(0)
|
||||||
|
const [scoreBleu, setScoreBleu] = useState(0)
|
||||||
|
const publicAffDispatch = usePubAffDispatch()
|
||||||
|
|
||||||
|
menuActions.current.switchSore = () => {
|
||||||
|
setRevers(!revers)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
menuActions.current.saveScore?.(scoreRouge, scoreBleu)
|
||||||
|
handleReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
setScoreRouge(0);
|
||||||
|
setScoreBleu(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
publicAffDispatch({type: 'SET_DATA', payload: {scoreRouge: scoreRouge, scoreBleu: scoreBleu}})
|
||||||
|
}, [scoreRouge, scoreBleu])
|
||||||
|
|
||||||
|
const red =
|
||||||
|
<div className="col-5 row align-items-center" style={{padding: "0 1em"}}>
|
||||||
|
<button className="btn btn-secondary" onClick={() => setScoreRouge(scoreRouge + 1)}><FontAwesomeIcon icon={faChevronUp}/></button>
|
||||||
|
<h1 style={{color: "red", fontSize: "min(15vw, 7em)", textAlign: "center"}}>{scoreRouge}</h1>
|
||||||
|
<button className="btn btn-secondary" onClick={() => setScoreRouge(scoreRouge - 1)}><FontAwesomeIcon icon={faChevronDown}/></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
return <div className="row">
|
||||||
|
{!revers && red}
|
||||||
|
<div className="col-5 row align-items-center" style={{padding: "0 1em"}}>
|
||||||
|
<button className="btn btn-secondary" onClick={() => setScoreBleu(scoreBleu + 1)}><FontAwesomeIcon icon={faChevronUp}/></button>
|
||||||
|
<h1 style={{color: "blue", fontSize: "min(15vw, 7em)", textAlign: "center"}}>{scoreBleu}</h1>
|
||||||
|
<button className="btn btn-secondary" onClick={() => setScoreBleu(scoreBleu - 1)}><FontAwesomeIcon icon={faChevronDown}/></button>
|
||||||
|
</div>
|
||||||
|
{revers && red}
|
||||||
|
|
||||||
|
<div className="col row align-items-center">
|
||||||
|
<button className="btn btn-danger" onClick={handleReset}>Réinitialiser</button>
|
||||||
|
<button className="btn btn-success" onClick={handleSave}>Sauvegarder</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
@ -5,15 +5,17 @@ import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
|||||||
import {createPortal} from "react-dom";
|
import {createPortal} from "react-dom";
|
||||||
import {copyStyles} from "../../../utils/copyStyles.js";
|
import {copyStyles} from "../../../utils/copyStyles.js";
|
||||||
import {PubAffProvider, usePubAffDispatch} from "../../../hooks/useExternalWindow.jsx";
|
import {PubAffProvider, usePubAffDispatch} from "../../../hooks/useExternalWindow.jsx";
|
||||||
import {faDisplay} from "@fortawesome/free-solid-svg-icons";
|
import {faArrowRightArrowLeft, faDisplay} from "@fortawesome/free-solid-svg-icons";
|
||||||
import {PubAffWindow} from "./PubAffWindow.jsx";
|
import {PubAffWindow} from "./PubAffWindow.jsx";
|
||||||
import {SimpleIconsScore} from "../../../assets/SimpleIconsScore.ts";
|
import {SimpleIconsScore} from "../../../assets/SimpleIconsScore.ts";
|
||||||
import {ChronoPanel} from "./CMTChronoPanel.jsx";
|
import {ChronoPanel} from "./CMTChronoPanel.jsx";
|
||||||
import {CategorieSelect} from "./CMTMatchPanel.jsx";
|
import {CategorieSelect} from "./CMTMatchPanel.jsx";
|
||||||
|
import {PointPanel} from "./CMTPoint.jsx";
|
||||||
|
|
||||||
export function CMTable() {
|
export function CMTable() {
|
||||||
const combDispatch = useCombsDispatch()
|
const combDispatch = useCombsDispatch()
|
||||||
const [catId, setCatId] = useState(-1);
|
const [catId, setCatId] = useState(-1);
|
||||||
|
const menuActions = useRef({});
|
||||||
const {data} = useRequestWS("getRegister", null)
|
const {data} = useRequestWS("getRegister", null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -32,15 +34,19 @@ export function CMTable() {
|
|||||||
<ChronoPanel/>
|
<ChronoPanel/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{backgroundColor: "#0099c7"}}>
|
|
||||||
B
|
<div className="card mb-3">
|
||||||
|
<div className="card-header">Score</div>
|
||||||
|
<div className="card-body">
|
||||||
|
<PointPanel menuActions={menuActions}/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-12 col-xl-6 col-xxl-5">
|
<div className="col-md-12 col-xl-6 col-xxl-5">
|
||||||
<div className="card mb-3">
|
<div className="card mb-3">
|
||||||
<div className="card-header">Matches</div>
|
<div className="card-header">Matches</div>
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<CategorieSelect catId={catId} setCatId={setCatId}/>
|
<CategorieSelect catId={catId} setCatId={setCatId} menuActions={menuActions}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{backgroundColor: "#c70000"}}>
|
<div style={{backgroundColor: "#c70000"}}>
|
||||||
@ -48,14 +54,14 @@ export function CMTable() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Menu/>
|
<Menu menuActions={menuActions}/>
|
||||||
</div>
|
</div>
|
||||||
</PubAffProvider>
|
</PubAffProvider>
|
||||||
}
|
}
|
||||||
|
|
||||||
const windowName = "FFSAFScorePublicWindow";
|
const windowName = "FFSAFScorePublicWindow";
|
||||||
|
|
||||||
function Menu() {
|
function Menu({menuActions}) {
|
||||||
const e = document.getElementById("actionMenu")
|
const e = document.getElementById("actionMenu")
|
||||||
const publicAffDispatch = usePubAffDispatch()
|
const publicAffDispatch = usePubAffDispatch()
|
||||||
const [showPubAff, setShowPubAff] = useState(false)
|
const [showPubAff, setShowPubAff] = useState(false)
|
||||||
@ -101,11 +107,17 @@ function Menu() {
|
|||||||
publicAffDispatch({type: 'SET_DATA', payload: {showScore: !showScore}});
|
publicAffDispatch({type: 'SET_DATA', payload: {showScore: !showScore}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleSwitchScore = () => {
|
||||||
|
menuActions.current.switchSore?.();
|
||||||
|
}
|
||||||
|
|
||||||
if (!e)
|
if (!e)
|
||||||
return <></>;
|
return <></>;
|
||||||
return <>
|
return <>
|
||||||
{createPortal(
|
{createPortal(
|
||||||
<>
|
<>
|
||||||
|
<div className="vr" style={{margin: "0 0.5em", height: "100%"}}></div>
|
||||||
|
<FontAwesomeIcon icon={faArrowRightArrowLeft} size="xl" style={{color: "#6c757d", cursor: "pointer"}} onClick={handleSwitchScore}/>
|
||||||
<div className="vr" style={{margin: "0 0.5em", height: "100%"}}></div>
|
<div className="vr" style={{margin: "0 0.5em", height: "100%"}}></div>
|
||||||
<FontAwesomeIcon icon={faDisplay} size="xl"
|
<FontAwesomeIcon icon={faDisplay} size="xl"
|
||||||
style={{color: showPubAff ? "#00c700" : "#6c757d", cursor: "pointer", marginRight: "0.25em"}}
|
style={{color: showPubAff ? "#00c700" : "#6c757d", cursor: "pointer", marginRight: "0.25em"}}
|
||||||
|
|||||||
@ -37,12 +37,12 @@ export function PubAffWindow({document}) {
|
|||||||
{showScore &&
|
{showScore &&
|
||||||
<div className="row" style={noMP}>
|
<div className="row" style={noMP}>
|
||||||
<div className="col-4" style={noMP}>
|
<div className="col-4" style={noMP}>
|
||||||
<div style={{fontSize: "30vh", lineHeight: "30vh", color: "#ff1414"}}>0</div>
|
<div style={{fontSize: "30vh", lineHeight: "30vh", color: "#ff1414"}}>{state.scoreRouge}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-4" style={noMP}>
|
<div className="col-4" style={noMP}>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-4" style={noMP}>
|
<div className="col-4" style={noMP}>
|
||||||
<div style={{fontSize: "30vh", lineHeight: "30vh", color: "#14adff"}}>0</div>
|
<div style={{fontSize: "30vh", lineHeight: "30vh", color: "#14adff"}}>{state.scoreBleu}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user