Dev session, graphics, prizes, login

This commit is contained in:
Felix Albrigtsen 2022-04-23 13:34:00 +02:00
parent d69b3a1b2c
commit 176c0b5ad4
13 changed files with 155 additions and 153 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
src/client/public/react.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@ -60,7 +60,7 @@ function AdminCreator(props){
function AdminList(props){
const deleteAdmin = adminId => {
fetch(process.env.REACT_APP_API_URL + `/admins/${adminId}`, {method: "DELETE"})
fetch(process.env.REACT_APP_API_URL + `/users/${adminId}`, {method: "DELETE"})
.then(res => res.json())
.then(data => {
if(data.status !== "OK"){
@ -108,7 +108,7 @@ export default function Admins(props) {
const { adminId } = useParams();
function getAdmins() {
fetch(process.env.REACT_APP_API_URL + `/admins/getAdmins`)
fetch(process.env.REACT_APP_API_URL + `/users/getUsers`)
.then((res) => res.json())
.then((data) =>{
if(data.status !== "OK") {

View File

@ -1,5 +1,6 @@
import * as React from "react";
import { BrowserRouter as Router, Link, Route, Routes } from "react-router-dom";
import TournamentCreator from "./TournamentCreator.js";
import TournamentOverview from "./TournamentOverview.js";
import TournamentManager from "./TournamentManager.js";
@ -8,6 +9,10 @@ import TournamentTeams from "./TournamentTeams";
import LoginPage from "./LoginPage";
import ProfilePage from "./ProfilePage";
import AppBar from './components/AsuraBar';
import SuccessSnackbar from "./components/SuccessSnackbar";
import ErrorSnackbar from "./components/ErrorSnackbar";
import AdminsOverview from "./AdminsOverview";
import { Button, Container, Typography, Box, Stack, Card, CardContent, CardMedia, Paper, Grid, Icon, TextField } from "@mui/material";
import AddCircleIcon from '@mui/icons-material/AddCircle';
import KeyboardDoubleArrowDownIcon from '@mui/icons-material/KeyboardDoubleArrowDown';
@ -111,6 +116,8 @@ function TournamentListItem(props) {
<Typography variant="h5" color="text.primary" gutterBottom> Players: {props.tournament.teamCount} / {props.tournament.teamLimit} </Typography>
<Description />
<Typography variant="body" color="text.primary"><EmojiEventsIcon alt="A trohpy" color="gold"/> Prize: {props.tournament.prize} </Typography>
<Countdown />
<Box sx={{flexGrow: 1, marginTop: "20px"}}>
<Grid container spacing={4} justifyContent="center" wrap="wrap">
@ -131,8 +138,6 @@ function TournamentListItem(props) {
</Grid>
</Box>
<Countdown />
<Typography variant="body" color="text.primary"> <EmojiEventsIcon alt="A trohpy" color="gold" /> Prize: {props.tournament.teamCount} </Typography>
</CardContent>
</Card>
</Paper>
@ -157,7 +162,7 @@ function TournamentList() {
for (let i = 0; i < tournaments.length; i++) {
tournaments[i].startTime = new Date(tournaments[i].startTime);
tournaments[i].endTime = new Date(tournaments[i].endTime);
if(today - tournaments[i].endTime <= 24*60*60*1000) {
if(today - tournaments[i].endTime <= 2*60*60*1000) {
currenttournaments.push(tournaments[i])
}
}
@ -209,7 +214,7 @@ class LoginManager {
.then(res => res.json())
.then(data => {
if (data.status !== "OK") {
console.error(data);
console.error(data.data);
return;
}
console.log(data);
@ -229,21 +234,45 @@ class LoginManager {
let login = new LoginManager();
login.checkLogin();
let showSuccess = (message) => {};
let showError = (message) => {};
export default function App() {
const [openError, setOpenError] = React.useState(false);
const [errorMessage, setErrorMessage] = React.useState("");
showError = (message) => {
setOpenError(false);
setErrorMessage(message);
setOpenError(true);
}
const [openSuccess, setOpenSuccess] = React.useState(false);
const [successMessage, setSuccessMessage] = React.useState("");
showSuccess = (message) => {
setOpenSuccess(false);
setSuccessMessage(message);
setOpenSuccess(true);
}
return (
<React.StrictMode>
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/create" element={<TournamentCreator />} />
<Route path="/" element={<Home showError={showError} showSuccess={showSuccess} />} />
<Route path="/create" element={<TournamentCreator showError={showError} showSuccess={showSuccess} />} />
<Route path="/tournament/:tournamentId" element={<TournamentOverview />} />
<Route path="/tournament/:tournamentId/manage" element={<TournamentManager />} />
<Route path="/tournament/:tournamentId/teams" element={<TournamentTeams />} />
<Route path="/history" element={<TournamentHistory />} />
<Route path="/tournament/:tournamentId/manage" element={<TournamentManager showError={showError} showSuccess={showSuccess} />} />
<Route path="/tournament/:tournamentId/teams" element={<TournamentTeams showError={showError} showSuccess={showSuccess} />} />
<Route path="/history" element={<TournamentHistory showError={showError} showSuccess={showSuccess} />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/profile" element={<ProfilePage login={login} />} />
<Route path="/admins" element={<AdminsOverview />} />
</Routes>
</Router>
<SuccessSnackbar message={successMessage} open={openSuccess} setOpen={setOpenSuccess} />
<ErrorSnackbar message={errorMessage} open={openError} setOpen={setOpenError} />
</React.StrictMode>
);
}

View File

@ -5,11 +5,6 @@ import ErrorSnackbar from "./components/ErrorSnackbar";
import {Button, Textfield, Stack, InputLabel, Paper, Typography} from '@mui/material';
function ProfileView() {
return "lol";
}
export default function LoginPage() {
return (
<>
@ -17,9 +12,9 @@ export default function LoginPage() {
<Paper x={{width: "70vw", margin: "1.5% auto"}} component={Stack} direction="column" justifyContent="center" alignItems="center">
<Stack direction="column" paddingTop={'0.5%'} alignItems={'center'}>
<Typography>Sign in with google</Typography>
<Link to={process.env.REACT_APP_LOGIN_URL}>
<a href={process.env.REACT_APP_LOGIN_URL}>
<img src="/btn_google_signing_dark.png" alt="Sign in with google" />
</Link>
</a>
</Stack>
</Paper>
</>

View File

@ -9,7 +9,7 @@ import AdapterDateFns from '@mui/lab/AdapterDateFns';
import LocalizationProvider from '@mui/lab/LocalizationProvider';
import { setDate } from "date-fns";
function postTournament(showError, tournamentName, tournamentDescription, tournamentStartDate, tournamentEndDate, tournamentMaxTeams) {
function postTournament(tournamentName, tournamentDescription, tournamentStartDate, tournamentEndDate, tournamentMaxTeams, tournamentPrize) {
if (!tournamentName || tournamentName === "") {
showError("Tournament name cannot be empty");
return;
@ -44,10 +44,10 @@ function postTournament(showError, tournamentName, tournamentDescription, tourna
let formData = new FormData();
formData.append("name", tournamentName);
formData.append("description", tournamentDescription);
// formData.append("image", tournamentImageFile);
formData.append("startDate", tournamentStartDate);
formData.append("endDate", tournamentEndDate);
formData.append("teamLimit", tournamentMaxTeams);
formData.append("prize", tournamentPrize)
let body = new URLSearchParams(formData);
fetch(process.env.REACT_APP_API_URL + `/tournament/create`, {
@ -85,12 +85,12 @@ function TournamentForm(props) {
let tournamentStart = new Date(startTime.setSeconds(0, 0, 0)).valueOf() - new Date().getTimezoneOffset() * 60*1000;
let tournamentEnd = new Date(endTime.setSeconds(0, 0, 0)).valueOf() - new Date().getTimezoneOffset() * 60*1000;
postTournament(
props.showError,
document.getElementById("nameInput").value,
document.getElementById("descriptionInput").value,
tournamentStart,
tournamentEnd,
maxTeams
maxTeams,
document.getElementById("prizeInput").value
);
}
@ -110,6 +110,7 @@ function TournamentForm(props) {
<TextField type="text" id="nameInput" label="Tournament Name" placeholder="Tournament Name" InputLabelProps={{shrink: true}}/>
{/* <InputLabel htmlFor="descriptionInput">Description: </InputLabel */}
<TextField type="text" multiline={true} id="descriptionInput" label="Description" placeholder="Description" InputLabelProps={{shrink: true}}/>
<TextField type="text" id="prizeInput" label="Prize" placeholder="Prize" InputLabelProps={{shrink: true}}/>
<Box flexGrow={1}>
<Grid container spacing={2} justifyContent="center">
<Grid item xs={4}>
@ -156,10 +157,12 @@ function TournamentForm(props) {
);
}
let showError = (message) => {};
export default function TournamentCreator(props) {
const [openError, setOpenError] = React.useState(false);
const [errorMessage, setErrorMessage] = React.useState("");
function showError(message) {
showError = (message) => {
setOpenError(false);
setErrorMessage(message);
setOpenError(true);
@ -169,7 +172,7 @@ export default function TournamentCreator(props) {
<>
<AppBar pageTitle="New tournament" />
<Paper sx={{minHeight: "30vh", width: "90vw", margin: "20px auto", padding: "20px 20px"}} component={Container} direction="column" align="center">
<TournamentForm showError={showError} />
<TournamentForm />
</Paper>
<ErrorSnackbar message={errorMessage} open={openError} setOpen={setOpenError} />

View File

@ -5,6 +5,8 @@ import AddCircleIcon from '@mui/icons-material/AddCircle';
import KeyboardDoubleArrowDownIcon from '@mui/icons-material/KeyboardDoubleArrowDown';
import KeyboardDoubleArrowUpIcon from '@mui/icons-material/KeyboardDoubleArrowUp';
import Appbar from './components/AsuraBar';
import EmojiEventsIcon from '@mui/icons-material/EmojiEvents';
function shorten(description, maxLength) {
if (description.length > maxLength) {
@ -65,6 +67,7 @@ function shorten(description, maxLength) {
</Grid>
</Grid>
</Box>
<Typography variant="body" color="text.primary"><EmojiEventsIcon alt="A trohpy" color="gold" align="vertical-center"/> Prize: {props.tournament.prize} </Typography>
</CardContent>
</Card>
</Paper>
@ -90,7 +93,7 @@ function shorten(description, maxLength) {
for (let i = 0; i < tournaments.length; i++) {
tournaments[i].startTime = new Date(tournaments[i].startTime);
tournaments[i].endTime = new Date(tournaments[i].endTime);
if(today - tournaments[i].endTime >= 24*60*60*1000) {
if(today - tournaments[i].endTime >= 2*60*60*1000) {
tournamenthistory.push(tournaments[i])
}
}

View File

@ -2,7 +2,6 @@ import * as React from "react";
import { BrowserRouter as Router, Link, Route, Routes } from "react-router-dom";
// import { AlertContainer, alert } from "react-custom-alert";
import AppBar from "./components/AsuraBar";
import ErrorSnackbar from "./components/ErrorSnackbar";
import TournamentBar from "./components/TournamentBar";
import { useParams } from "react-router-dom";
import { Button, TextField, Grid, Box, Container, Paper, Stack } from "@mui/material";
@ -23,6 +22,7 @@ let submitChanges = curryTournamentId => event => {
// let tournamentImageFile = document.getElementById("editImage").files[0];
let tournamentStartDate = document.getElementById("editStartDate").value;
let tournamentEndDate = document.getElementById("editEndDate").value;
let tournamentPrize = document.getElementById("editPrize").value
if (!tournamentName || tournamentName === "") {
showError("Tournament name cannot be empty");
@ -61,6 +61,7 @@ let submitChanges = curryTournamentId => event => {
formData.append("startDate", tournamentStartDate);
formData.append("endDate", tournamentEndDate);
// formData.append("teamLimit", tournamentMaxTeams);
formData.append("prize", tournamentPrize)
let body = new URLSearchParams(formData);
fetch(process.env.REACT_APP_API_URL + `/tournament/${tournamentId}/edit`, {
@ -70,7 +71,7 @@ let submitChanges = curryTournamentId => event => {
.then((response) => response.json())
.then((data) => {
if (data.status === "OK") {
alert("Tournament Changed successfully");
showSuccess("Tournament Changed successfully");
window.location.href = `/tournament/${tournamentId}`;
} else {
showError(data.data);
@ -89,8 +90,7 @@ let deleteTournament = tournamentId => event => {
.then((response) => response.json())
.then((data) => {
if (data.status === "OK") {
// TODO: Replace alert with Snackbar
alert("Tournament Deleted successfully");
showSuccess("Tournament Deleted successfully");
window.location.href = "/";
} else {
showError(data.data);
@ -116,6 +116,7 @@ function ManageTournament(props) {
document.getElementById("editName").value = data.data.name;
document.getElementById("editDesc").value = data.data.description;
document.getElementById("editPrize").value = data.data.prize
// Get the time from the server, add the local timezone offset and set the input fields
let startDate = new Date(data.data.startTime.slice(0, 16));
let endDate = new Date(data.data.endTime.slice(0, 16));
@ -135,6 +136,7 @@ function ManageTournament(props) {
<Stack sx={{minHeight: "30vh", margin: "10px auto"}} direction="column" justifyContent="center" spacing={2} align="center">
<TextField type="text" id="editName" label="Edit Name:" placeholder="Edit Name" InputLabelProps={{shrink: true}}/>
<TextField type="text" multiline={true} id="editDesc" label="Edit Description:" placeholder="Edit Description" InputLabelProps={{shrink: true}} />
<TextField type="text" id="editPrize" label="Edit Prize:" placeholder="Edit Prize" InputLabelProps={{shrink: true}}/>
<Box sx={{flexGrow: 1}}>
<Grid container spacing={2} justifyContent="center">
<Grid item xs={4}>
@ -165,16 +167,10 @@ function ManageTournament(props) {
);
}
function showError(error) {
alert("Something went wrong. \n" + error);
console.error(error);
}
function ConfirmationDialogRaw(props) {
const { tournamentId } = useParams();
const { onClose, value: valueProp, open, ...other } = props;
const [value, setValue] = React.useState(valueProp);
const radioGroupRef = React.useRef(null);
React.useEffect(() => {
if (!open) {
@ -210,32 +206,21 @@ function ConfirmationDialogRaw(props) {
ConfirmationDialogRaw.propTypes = {
onClose: PropTypes.func.isRequired,
open: PropTypes.bool.isRequired,
value: PropTypes.string.isRequired,
};
let showError = (message) => {};
let showSuccess = (message) => {};
export default function TournamentManager(props) {
const { tournamentId } = useParams();
const [open, setOpen] = React.useState(false);
const [value, setValue] = React.useState("");
const handleClickListItem = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const [openError, setOpenError] = React.useState(false);
const [errorMessage, setErrorMessage] = React.useState("");
function showError(message) {
setOpenError(false);
setErrorMessage(message);
setOpenError(true);
}
const [dialogOpen, setDialogOpen] = React.useState(false);
const handleDialogClickListItem = () => { setDialogOpen(true); };
const handleDialogClose = () => { setDialogOpen(false); };
showError = props.showError;
showSuccess = props.showSuccess;
return (
<>
<AppBar pageTitle="Edit Tournament" />
<TournamentBar pageTitle="Edit Tournament"/>
@ -243,20 +228,17 @@ export default function TournamentManager(props) {
<ManageTournament tournamentId={tournamentId} showError={showError} />
{/* <AnnounceButton /> */}
<Box sx={{width: "100%"}}>
<Button variant="contained" color="error" onClick={handleClickListItem} sx={{margin: "auto 5px"}} endIcon={<DeleteIcon />}>
<Button variant="contained" color="error" onClick={handleDialogClickListItem} sx={{margin: "auto 5px"}} endIcon={<DeleteIcon />}>
Delete Tournament
</Button>
<ConfirmationDialogRaw
id="ringtone-menu"
id="confirmation-dialog"
keepMounted
open={open}
onClose={handleClose}
value={value}
open={dialogOpen}
onClose={handleDialogClose}
/>
</Box>
</Paper>
<ErrorSnackbar message={errorMessage} open={openError} setOpen={setOpenError} />
</>
);
}

View File

@ -18,12 +18,10 @@ function showError(error) {
}
function TournamentTier(props){
const { tournamentId } = useParams();
let roundTypes = ["finals", "semifinals", "quarterfinals", "eighthfinals", "sixteenthfinals", "thirtysecondfinals"];
let roundTypes = ["winner","finals", "semifinals", "quarterfinals", "eighthfinals", "sixteenthfinals", "thirtysecondfinals"];
let matches = [];
for (let i = 0; i < props.matches.length; i++) {
matches.push(<Match tournamentId={tournamentId} teams={props.teams} match={props.matches[i]} key={i} />);
matches.push(<Match tournament={props.tournament} teams={props.teams} match={props.matches[i]} key={i} />);
}
return(
<ul className={`round ${roundTypes[props.tier]}`}>
@ -45,15 +43,11 @@ function Match(props){
let setWinner = curryTeamId => event => {
let teamId = curryTeamId;
console.log(teamId)
// console.log(teamId)
if (!teamId || teamId == null) {
showError("No team selected");
return;
}
// if(props.match.winnerId === teamId){
// showError("Team already won");
// return;
// }
let formData = new FormData();
formData.append("winnerId",teamId);
let body = new URLSearchParams(formData);
@ -71,43 +65,40 @@ function Match(props){
}
})
.catch(error => showError(error));
}
};
const [endTime, setendTime] = React.useState(null);
React.useEffect(() => {
fetch(process.env.REACT_APP_API_URL + `/tournament/${props.tournamentId}`)
.then(res => res.json())
let curryUnsetContestant = teamId => (e) => {
console.log("wack")
let formData = new FormData();
formData.append("teamId", teamId);
let body = new URLSearchParams(formData);
console.log(props.match)
fetch(process.env.REACT_APP_API_URL + `/match/${props.match.id}/unsetContestant`, {
method: "POST",
body: body
})
.then(response => response.json())
.then(data => {
if (data.status !== "OK") {
// Do your error thing
console.error(data);
return;
if (data.status === "OK") {
console.log("wacky smacky");
window.location.reload();
}
let endTime = data.data.endTime;
setendTime(endTime);
})
.catch(err => showError(err));
})
console.log(props)
let today = new Date()
let yesterday = today.setDate(today.getDate() - 1)
let isComplete = new Date(endTime) < yesterday
.catch(error => showError(error));
}
return (
<>
{/* Team 1 (Winner-status?) (Team name) */}
<li className={`game game-top ${props.match.winnerId && (props.match.team1Id === props.match.winnerId) ? "winner" : "loser"}`}>
<li className={`game game-top ${props.match.winnerId !== null ? (props.match.team1Id === props.match.winnerId) ? "winner" : "loser" : ""}`}>
<Stack direction={"row"}>
<Typography className={`teamName`} align={'center'} sx={{fontSize:'1.5rem', maxWidth:'15vw', overflow:'hidden', wordWrap:'none'}}>
{team1Name}
</Typography>
{ props.match.teamId !== null && !isComplete && props.match.tier !== Math.log2(4) - 1 && props.match.winnerId === null && team1Name !== "TBA" ?
<IconButton color="error" aria-label="remmove winner" component="span"><BackspaceIcon /></IconButton> : null
{ props.match.team1Id !== null && !props.tournament.hasEnded && props.match.tier !== Math.log2(props.tournament.teamLimit) - 1 && props.match.winnerId === null ?
<IconButton color="error" aria-label="remmove winner" component="span" onClick={curryUnsetContestant(props.match.team1Id)}><BackspaceIcon /></IconButton> : null
}
{ props.match.team1Id !== null && props.match.winnerId === null && !isComplete && team1Name !== "TBA" ?
{ props.match.team1Id !== null && props.match.winnerId === null && !props.tournament.hasEnded ?
<IconButton onClick={setWinner(props.match.team1Id)} color="success" aria-label="select winner" component="span"><AddCircleIcon /></IconButton> : null
}
{/* { props.match.winnerId && (props.match.team1Id === props.match.winnerId) &&
@ -117,15 +108,15 @@ function Match(props){
</li>
<li className="game game-spacer">&nbsp;</li>
{/* Team 2 (Winner-status?) (Team name) */}
<li className={`game game-bottom ${props.match.winnerId && (props.match.team2Id === props.match.winnerId) ? "winner" : "loser"}`}>
<li className={`game game-bottom ${props.match.winnerId !== null ? (props.match.team1Id === props.match.winnerId) ? "winner" : "loser" : ""}`}>
<Stack direction={"row"} sx={{alignItems:'center'}}>
<Typography className={`teamName`} sx={{fontSize:'1.5rem', maxWidth:'15vw', overflow:'hidden', wordWrap:'none'}}>
{team2Name}
</Typography>
{ props.match.teamId !== null && !isComplete && props.match.tier !== Math.log2(props.maxTeams) - 1 && props.match.winnerId === null && team2Name !== "TBA" ?
<IconButton color="error" aria-label="remmove winner" component="span"><BackspaceIcon /></IconButton> : null
{ props.match.team2Id !== null && !props.tournament.hasEnded && props.match.tier !== Math.log2(props.tournament.teamLimit) - 1 && props.match.winnerId === null ?
<IconButton color="error" aria-label="remmove winner" component="span" onClick={curryUnsetContestant(props.match.team2Id)}><BackspaceIcon /></IconButton> : null
}
{ props.match.team1Id !== null && props.match.winnerId === null && !isComplete && team2Name !== "TBA" ?
{ props.match.team2Id !== null && props.match.winnerId === null && !props.tournament.hasEnded ?
<IconButton onClick={setWinner(props.match.team2Id)} color="success" aria-label="select winner" component="span"><AddCircleIcon /></IconButton> : null
}
{/* { props.match.winnerId && (props.match.team2Id === props.match.winnerId) &&
@ -139,25 +130,11 @@ function Match(props){
}
function BracketViewer(props){
const [tournament, setTournament] = React.useState(null);
const [matches, setMatches] = React.useState(null);
const [teams, setTeams] = React.useState(null);
React.useEffect(() => {
fetch(process.env.REACT_APP_API_URL + `/tournament/${props.tournamentId}`)
.then(res => res.json())
.then(data => {
if (data.status !== "OK") {
// Do your error thing
showError(data.data);
return;
}
let tournament = data.data;
setTournament(tournament);
})
.catch(err => showError(err));
fetch(process.env.REACT_APP_API_URL + `/tournament/${props.tournamentId}/getMatches`)
.then(res => res.json())
.then(data => {
@ -196,56 +173,46 @@ function BracketViewer(props){
.catch(err => showError(err));
}, []);
return (
(matches && teams) ?
(props.tournament && matches && teams) ?
// <div sx={{width: "100vw", height: "80vh", overflow: "scroll"}} className="bracket">
<div className="bracket">
{matches.map(tier => {
let tierNum = tier[0].tier;
return <TournamentTier key={tierNum} tier={tierNum} matches={tier} teams={teams} />
return <TournamentTier tournament={props.tournament} key={tierNum} tier={tierNum} matches={tier} teams={teams} />
})}
</div>
: <Box sx={{display:'flex', justifyContent:'center', alignItems:'center', position:'relative', marginTop:'5%'}}><CircularProgress size={"20vw"}/></Box>
);
}
function RemovableBar(props) {
const [endTime, setendTime] = React.useState(null);
export default function TournamentOverview(props) {
const { tournamentId } = useParams();
const [tournament, setTournament] = React.useState(false);
React.useEffect(() => {
fetch(process.env.REACT_APP_API_URL + `/tournament/${props.tournamentId}`)
fetch(process.env.REACT_APP_API_URL + `/tournament/${tournamentId}`)
.then(res => res.json())
.then(data => {
if (data.status !== "OK") {
// Do your error thing
console.error(data);
showError(data.data);
return;
}
let endTime = data.data.endTime;
setendTime(endTime);
let tourn = data.data;
let now = new Date();
let endTime = new Date(tourn.endTime);
tourn.hasEnded = (now - 2*60*60*1000) > endTime; // 2 hours in the past
setTournament(tourn);
})
.catch(err => showError(err));
})
let today = new Date()
let yesterday = today.setDate(today.getDate() - 1)
let isComplete = new Date(endTime) < yesterday
if (isComplete) {
return (null)
} else {
return (<TournamentBar pageTitle="View Tournament" />)
}
}
export default function TournamentOverview(props) {
const { tournamentId } = useParams();
}, [tournamentId]);
return (
<>
<Appbar pageTitle="View Tournament" />
{ isLoggedIn ?
<RemovableBar tournamentId={tournamentId} /> : null
<Appbar pageTitle={tournament.name} />
{ isLoggedIn && !tournament.hasEnded ?
<TournamentBar tournamentId={tournamentId} viewTournament={true} /> : null
}
<BracketViewer tournamentId={tournamentId} className="bracketViewer" />
<BracketViewer tournament={tournament} tournamentId={tournamentId} className="bracketViewer" />
</>
);
}

View File

@ -36,6 +36,7 @@ function TeamCreator(props) {
}
document.getElementById("teamNameInput").value = "";
props.onTeamCreated();
}
)
}
@ -108,14 +109,8 @@ function TeamList(props) {
);
}
function PlayerList(props) {
// Something like https://react-list-editable.netlify.app/
return <h1>PlayerList coming...</h1>
}
function TeamEditor(props) {
const [team, setTeam] = React.useState({});
const [players, setPlayers] = React.useState([]);
React.useEffect(() => {
if (props.selectedTeamId === -1) {
setTeam({});
@ -180,7 +175,6 @@ function TeamEditor(props) {
<h2><b>Edit Team:</b></h2>
<form>
<TextField id="newTeamNameInput" label="Team Name" value={team.name || ""} onChange={nameInputChanged} onFocus={handleFocus} sx={{width: "80%"}} />
{/* <PlayerList players={players} setPlayers={setPlayers} /> */}
<Button type="submit" variant="contained" sx={{margin: "auto 5px"}} color="primary" onClick={saveTeam}>Save</Button>
</form>
</div>

View File

@ -0,0 +1,29 @@
import * as React from 'react';
import Stack from '@mui/material/Stack';
import Button from '@mui/material/Button';
import Snackbar from '@mui/material/Snackbar';
import MuiAlert from '@mui/material/Alert';
const Alert = React.forwardRef(function Alert(props, ref) {
return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />;
});
export default function showError(props) {
const handleClose = (event, reason) => {
if (reason === 'clickaway') {
return;
}
props.setOpen(false);
};
return (
<Stack spacing={2} sx={{ width: '100%' }}>
<Snackbar open={props.open} autoHideDuration={6000} onClose={handleClose}>
<Alert onClose={handleClose} severity="success" sx={{ width: '100%' }}>
{props.message}
</Alert>
</Snackbar>
</Stack>
);
}

View File

@ -31,7 +31,7 @@ function ClipboardButton(props) {
function ButtonLink(props) {
return (
<Link to={`/tournament/${props.tournamentId}` + props.targetPath} >
<Button variant="contained" color="primary" disabled={props.activeTitle === props.title} sx={{margin: "15px", fontSize: "1.2em"}} >{props.title}</Button>
<Button variant="contained" color="primary" disabled={props.activeTitle === props.title || props.viewTournament} sx={{margin: "15px", fontSize: "1.2em"}} >{props.title}</Button>
</Link>
);
}
@ -41,7 +41,7 @@ export default function TournamentBar(props) {
return (
<Paper sx={{width: "90vw", margin: "1.5% auto"}} component={Stack} direction="column" justifyContent="center" alignItems="center">
<Stack direction="row" paddingTop={'0.5%'}>
<ButtonLink targetPath="" tournamentId={tournamentId} activeTitle={props.pageTitle} title="View Tournament" />
<ButtonLink targetPath="" tournamentId={tournamentId} activeTitle={props.pageTitle} title="View Tournament" viewTournament={props.viewTournament} />
<ButtonLink targetPath="/manage" tournamentId={tournamentId} activeTitle={props.pageTitle} title="Edit Tournament" />
<ButtonLink targetPath="/teams" tournamentId={tournamentId} activeTitle={props.pageTitle} title="Manage Teams" />
</Stack>

View File

@ -10,7 +10,7 @@
display:flex;
flex-direction:column;
justify-content:center;
width:20vw;
width:20%;
list-style:none;
padding:0;
font-size: 1.5rem;