Dev session
This commit is contained in:
parent
020ab4de84
commit
d4a2190a5a
|
@ -4,9 +4,11 @@ import Appbar from "./components/AsuraBar";
|
|||
import ErrorSnackbar from "./components/ErrorSnackbar";
|
||||
import LoginPage from "./LoginPage";
|
||||
import { Button, Box, TextField, Stack, InputLabel, Paper, TableContainer, Table, TableBody, TableHead, TableCell, TableRow, Typography, Select, MenuItem, FormControl } from '@mui/material';
|
||||
import { Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from "@mui/material";
|
||||
import AddCircleIcon from '@mui/icons-material/AddCircle';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
function AdminCreator(props){
|
||||
function postCreate(){
|
||||
|
@ -55,17 +57,20 @@ function AdminCreator(props){
|
|||
}
|
||||
|
||||
function UserList(props){
|
||||
const deleteUsers = (userId) => {
|
||||
const deleteUser = (userId) => {
|
||||
openConfirmDialog(function() {
|
||||
fetch(process.env.REACT_APP_API_URL + `/users/${userId}`, {method: "DELETE"})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if(data.status !== "OK"){
|
||||
showError(data.data);
|
||||
console.log("UWU")
|
||||
return;
|
||||
}
|
||||
props.setUsers(props.users.filter(user => user.id !== userId));
|
||||
props.onUserUpdated();
|
||||
})
|
||||
.catch(error => showError(error));
|
||||
});
|
||||
}
|
||||
|
||||
let updateRank = (asuraId) => event => {
|
||||
|
@ -92,7 +97,6 @@ function UserList(props){
|
|||
return(
|
||||
<Paper sx={{minHeight: "30vh", width:"90vw", margin:"10px auto"}} component={Stack} direction="column" justifycontent="center">
|
||||
<div align="center">
|
||||
{/* TODO: scroll denne menyen, eventuelt søkefelt */}
|
||||
<Table aria-label="simple table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
|
@ -123,7 +127,7 @@ function UserList(props){
|
|||
{/* <TableCell align="right">{team.members}</TableCell> */}
|
||||
<TableCell align="center">
|
||||
{/* <Button variant="contained" sx={{margin: "auto 5px"}} color="primary" onClick={() => props.setSelectedTeamId(team.id)} endIcon={<EditIcon />}>Edit</Button> */}
|
||||
<Button variant="contained" sx={{margin: "auto 5px"}} color="error" onClick={() => {deleteUsers(user.asuraId)}} endIcon={<DeleteIcon />}>Delete</Button>
|
||||
<Button variant="contained" sx={{margin: "auto 5px"}} color="error" onClick={() => {deleteUser(user.asuraId)}} endIcon={<DeleteIcon />}>Delete</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
|
@ -134,10 +138,58 @@ function UserList(props){
|
|||
)
|
||||
}
|
||||
|
||||
function ConfirmationDialogRaw(props) {
|
||||
const { userId } = useParams();
|
||||
const { onClose, value: valueProp, open, ...other } = props;
|
||||
const [value, setValue] = React.useState(valueProp);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!open) {
|
||||
setValue(valueProp);
|
||||
}
|
||||
}, [valueProp, open]);
|
||||
|
||||
const handleCancel = () => {
|
||||
onClose();
|
||||
};
|
||||
const handleConfirm = () => {
|
||||
onClose();
|
||||
props.handleconfirm();
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
sx={{ '& .MuiDialog-paper': { width: '80%', maxHeight: 435 } }}
|
||||
maxWidth="xs"
|
||||
open={open}
|
||||
keepMounted
|
||||
>
|
||||
<DialogTitle>Delete administrator?</DialogTitle>
|
||||
<DialogContent>
|
||||
Are you sure you want to delete the administrator? This action is not reversible!
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button autoFocus onClick={handleCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={handleConfirm}>Confirm</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
ConfirmationDialogRaw.propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
open: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
// Confirmation window for "Delete user"
|
||||
function openConfirmDialog(callback) {g_setDialogCallback(callback); g_setDialogOpen(true);}
|
||||
let g_setDialogOpen = () => {};
|
||||
let g_setDialogCallback = (callback) => {};
|
||||
|
||||
let showError = (message) => {};
|
||||
|
||||
|
||||
|
||||
export default function Users(props) {
|
||||
|
||||
const [openError, setOpenError] = React.useState(false);
|
||||
|
@ -149,6 +201,12 @@ export default function Users(props) {
|
|||
}
|
||||
const [users, setUsers] = React.useState([]);
|
||||
|
||||
const [dialogOpen, setDialogOpen] = React.useState(false);
|
||||
const handleDialogClose = () => { setDialogOpen(false); };
|
||||
const [dialogOnConfirm, setDialogOnConfirm] = React.useState(() => {return function(){}});
|
||||
g_setDialogCallback = (callback) => { setDialogOnConfirm(()=>{ return callback })};
|
||||
g_setDialogOpen = (value) => { setDialogOpen(value); };
|
||||
|
||||
function getUsers() {
|
||||
fetch(process.env.REACT_APP_API_URL + `/users/getUsers`)
|
||||
.then((res) => res.json())
|
||||
|
@ -186,6 +244,13 @@ export default function Users(props) {
|
|||
</div>
|
||||
|
||||
<ErrorSnackbar message={errorMessage} open={openError} setOpen={setOpenError} />
|
||||
<ConfirmationDialogRaw
|
||||
id="confirmation-dialog"
|
||||
keepMounted
|
||||
open={dialogOpen}
|
||||
onClose={handleDialogClose}
|
||||
handleconfirm={dialogOnConfirm}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -182,7 +182,7 @@ function Home(props) {
|
|||
<>
|
||||
<Appbar user={props.user} pageTitle="Asura Tournaments" />
|
||||
<Container sx={{minHeight: "30vh", width: "90vw", padding: "20px 20px"}} component={Container} direction="column" align="center">
|
||||
<Box component={Stack} direction="row" align="center" justifyContent="space-between" alignItems="center" sx={{flexGrow: 1}}>
|
||||
<Box component={Stack} direction={['column','row']}sx={{align:'center', justifyContent:'space-between', flexGrow:1}}>
|
||||
<Typography sx={{fontSize:['1.5rem','2rem','2rem']}}>Tournaments</Typography>
|
||||
{ props.user.isLoggedIn ?
|
||||
<CreateButton /> : null
|
||||
|
|
|
@ -219,8 +219,13 @@ export default function TournamentManager(props) {
|
|||
const handleDialogClickListItem = () => { setDialogOpen(true); };
|
||||
const handleDialogClose = () => { setDialogOpen(false); };
|
||||
|
||||
showError = props.showError;
|
||||
showSuccess = props.showSuccess;
|
||||
const [openError, setOpenError] = React.useState(false);
|
||||
const [errorMessage, setErrorMessage] = React.useState("");
|
||||
showError = (message) => {
|
||||
setOpenError(false);
|
||||
setErrorMessage(message);
|
||||
setOpenError(true);
|
||||
}
|
||||
|
||||
if (!props.user.isLoggedIn) { return <LoginPage user={props.user} />; }
|
||||
|
||||
|
@ -229,7 +234,7 @@ export default function TournamentManager(props) {
|
|||
<Appbar user={props.user} pageTitle="Edit Tournament" />
|
||||
<TournamentBar pageTitle="Edit Tournament"/>
|
||||
<Paper sx={{minHeight: "30vh", width: "90vw", margin: "20px auto", padding: "20px 0"}} component={Container} direction="column" align="center">
|
||||
<ManageTournament tournamentId={tournamentId} showError={showError} />
|
||||
<ManageTournament tournamentId={tournamentId} />
|
||||
{/* <AnnounceButton /> */}
|
||||
<Box sx={{width: "100%"}}>
|
||||
<Button variant="contained" color="error" onClick={handleDialogClickListItem} sx={{margin: "auto 5px"}} endIcon={<DeleteIcon />}>
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
import * as React from "react";
|
||||
import { BrowserRouter as Router, Link, Route, Routes } from "react-router-dom";
|
||||
import Appbar from './components/AsuraBar';
|
||||
|
||||
function MatchHistory() {
|
||||
|
||||
return(
|
||||
`Hei på deg din gamle sei`
|
||||
);
|
||||
}
|
||||
|
||||
export default function TournamentMatches(props) {
|
||||
return (
|
||||
<>
|
||||
<Appbar user={props.user} />
|
||||
<MatchHistory />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -16,7 +16,7 @@ function TournamentTier(props){
|
|||
let roundTypes = ["finals", "semifinals", "quarterfinals", "eighthfinals", "sixteenthfinals", "thirtysecondfinals"];
|
||||
let matches = [];
|
||||
for (let i = 0; i < props.matches.length; i++) {
|
||||
matches.push(<Match tournament={props.tournament} user={props.user} tier={props.tier} roundTypes={roundTypes} teams={props.teams} match={props.matches[i]} key={i} />);
|
||||
matches.push(<Match tournament={props.tournament} user={props.user} tier={props.tier} roundTypes={roundTypes} teams={props.teams} match={props.matches[i]} key={i} onwinnerchange={props.onwinnerchange} />);
|
||||
}
|
||||
return(
|
||||
<>
|
||||
|
@ -40,7 +40,6 @@ function Match(props){
|
|||
|
||||
let setWinner = curryTeamId => event => {
|
||||
let teamId = curryTeamId;
|
||||
// console.log(teamId)
|
||||
if (!teamId || teamId == null) {
|
||||
showError("No team selected");
|
||||
return;
|
||||
|
@ -56,7 +55,7 @@ function Match(props){
|
|||
.then(data => {
|
||||
if (data.status === "OK") {
|
||||
//Refresh when winner is set successfully
|
||||
window.location.reload();
|
||||
props.onwinnerchange();
|
||||
} else {
|
||||
showError(data.data)
|
||||
}
|
||||
|
@ -65,11 +64,9 @@ function Match(props){
|
|||
};
|
||||
|
||||
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
|
||||
|
@ -77,8 +74,9 @@ function Match(props){
|
|||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === "OK") {
|
||||
// console.log("wacky smacky");
|
||||
window.location.reload();
|
||||
props.onwinnerchange()
|
||||
} else {
|
||||
showError(data.data);
|
||||
}
|
||||
})
|
||||
.catch(error => showError(error));
|
||||
|
@ -126,12 +124,53 @@ function Match(props){
|
|||
);
|
||||
}
|
||||
|
||||
function WinnerDisplay(props) {
|
||||
let unsetWinner = event => {
|
||||
let formData = new FormData();
|
||||
formData.append("winnerId","null");
|
||||
let body = new URLSearchParams(formData);
|
||||
fetch(process.env.REACT_APP_API_URL + `/match/${props.finalMatch.id}/setWinner`, {
|
||||
method: "POST",
|
||||
body: body
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status !== "OK") { showError(data.data); return;}
|
||||
props.onwinnerchange();
|
||||
})
|
||||
.catch(error => showError(error));
|
||||
};
|
||||
|
||||
|
||||
|
||||
if (!props.team) {
|
||||
// Winner is not yet chosen
|
||||
return <div className="winnerDisplay">
|
||||
<Typography variant="h5" component="h2">
|
||||
Winner is not chosen.<br /> Will it be you?
|
||||
</Typography>
|
||||
</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="winnerDisplay winner">
|
||||
<Typography variant="h4" component="h2" align="center">
|
||||
{props.user.isLoggedIn && <IconButton color="error" aria-label="remove winner" component="span" onClick={unsetWinner}><BackspaceIcon /></IconButton>}
|
||||
Winner:
|
||||
</Typography>
|
||||
<Typography variant="h4" component="h2">
|
||||
{props.team.name}<EmojiEventsIcon alt="A trohpy" />
|
||||
</Typography>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function BracketViewer(props){
|
||||
|
||||
const [matches, setMatches] = React.useState(null);
|
||||
const [teams, setTeams] = React.useState(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
let getMatches = () => {
|
||||
fetch(process.env.REACT_APP_API_URL + `/tournament/${props.tournamentId}/getMatches`)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
|
@ -140,20 +179,18 @@ function BracketViewer(props){
|
|||
console.error(data);
|
||||
return;
|
||||
}
|
||||
let matches = data.data;
|
||||
let allMatches = data.data;
|
||||
// Group all matches by their round/tier
|
||||
let tiers = matches.reduce((tiers, match) => {
|
||||
let tiers = allMatches.reduce((tiers, match) => {
|
||||
if (!tiers[match.tier]) {
|
||||
tiers[match.tier] = [];
|
||||
}
|
||||
tiers[match.tier].push(match);
|
||||
console.log(tiers)
|
||||
return tiers;
|
||||
}, {});
|
||||
|
||||
tiers = Object.values(tiers);
|
||||
tiers = tiers.reverse();
|
||||
|
||||
setMatches(tiers);
|
||||
})
|
||||
.catch(err => showError(err));
|
||||
|
@ -169,19 +206,35 @@ function BracketViewer(props){
|
|||
setTeams(teams);
|
||||
})
|
||||
.catch(err => showError(err));
|
||||
}
|
||||
React.useEffect(() => {
|
||||
getMatches();
|
||||
}, []);
|
||||
|
||||
let getFinalMatch = (tierMatches) => {
|
||||
let finalMatch = tierMatches[tierMatches.length - 1][0];
|
||||
return finalMatch;
|
||||
};
|
||||
let getWinnerTeam = (tierMatches) => {
|
||||
let finalMatch = getFinalMatch(tierMatches);
|
||||
if (finalMatch.winnerId === null) { return null;}
|
||||
let winnerTeam = teams.find(team => team.id === finalMatch.winnerId);
|
||||
return winnerTeam;
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
(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 user={props.user} tournament={props.tournament} key={tierNum} tier={tierNum} matches={tier} teams={teams} />
|
||||
{matches.map(tierMatches => {
|
||||
let tierNum = tierMatches[0].tier;
|
||||
return <TournamentTier user={props.user} tournament={props.tournament} key={tierNum} tier={tierNum} matches={tierMatches} teams={teams} onwinnerchange={getMatches} />
|
||||
})}
|
||||
</div>
|
||||
|
||||
<WinnerDisplay team={getWinnerTeam(matches)} user={props.user} finalMatch={getFinalMatch(matches)} onwinnerchange={getMatches} />
|
||||
</div>
|
||||
</>
|
||||
: <Box sx={{display:'flex', justifyContent:'center', alignItems:'center', position:'relative', marginTop:'5%'}}><CircularProgress size={"20vw"}/></Box>
|
||||
);
|
||||
|
|
|
@ -31,10 +31,10 @@ function LoggedInMenu(props) {
|
|||
<Menu anchorEl={anchorEl} open={open} onClose={handleClose} MenuListProps={{'aria-labelledby': 'basic-button',}} sx={{position:"absolute"}}>
|
||||
<Link to="/profile" style={{color:"black"}}><MenuItem onClick={handleClose}><Button startIcon={<AccountCircleIcon />}>{props.user.name}</Button></MenuItem></Link>
|
||||
<Link to="/history" style={{color:"black"}}><MenuItem onClick={handleClose}><Button startIcon={<HistoryIcon />}>History</Button></MenuItem></Link>
|
||||
<Link to="/api/logout" style={{color:"black"}}><MenuItem onClick={logout}><Button startIcon={<LogoutIcon />} >Logout</Button></MenuItem></Link>
|
||||
{ props.user.isManager &&
|
||||
<Link to="/admins" style={{color:"black"}}><MenuItem onClick={handleClose}><Button startIcon={<EditIcon />} >Admins</Button></MenuItem></Link>
|
||||
}
|
||||
<a href={`${process.env.REACT_APP_API_URL}/users/logout`} style={{color:"black"}}><MenuItem onClick={logout}><Button startIcon={<LogoutIcon />} >Logout</Button></MenuItem></a>
|
||||
</Menu>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -3,6 +3,11 @@ import { useParams } from "react-router-dom";
|
|||
import { BrowserRouter as Router, Link, Route, Routes, History } from "react-router-dom";
|
||||
import { Stack, Paper, Typography, Box, Button, Grid, Snackbar, IconButton } from "@mui/material"
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import MuiAlert from '@mui/material/Alert';
|
||||
|
||||
const Alert = React.forwardRef(function Alert(props, ref) {
|
||||
return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />;
|
||||
});
|
||||
|
||||
function ClipboardButton(props) {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
|
@ -23,7 +28,11 @@ function ClipboardButton(props) {
|
|||
return (
|
||||
<>
|
||||
<Button onClick={copyString} variant="outlined" color="primary" sx={{margin: "auto 5px"}} >Copy {props.name}</Button>
|
||||
<Snackbar open={open} autoHideDuration={1500} onClose={handleClose} message={props.name + " copied to clipboard"} action={closeAction} />
|
||||
<Snackbar open={open} autoHideDuration={1500} onClose={handleClose} action={closeAction}>
|
||||
<Alert onClose={handleClose} severity="info" sx={{ width: '100%' }}>
|
||||
{props.name + " copied to clipboard"}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -55,3 +55,21 @@
|
|||
border-top:1px solid #aaa;
|
||||
}
|
||||
|
||||
|
||||
.winnerDisplay {
|
||||
display:flex;
|
||||
flex-direction:row;
|
||||
align-items: center;
|
||||
border: 2px solid gray;
|
||||
border-radius: 15px;
|
||||
min-height: 10vh;
|
||||
max-height: 40vh;
|
||||
margin: auto 5px;
|
||||
padding: 10px;
|
||||
}
|
||||
.winnerDisplay.winner {
|
||||
border: 2px solid green;
|
||||
}
|
||||
.winnerDisplay > h2 {
|
||||
margin-right: 10px;
|
||||
}
|
Loading…
Reference in New Issue