Newer
Older
Button,
Dialog,
DialogActions,
Menu,
TablePagination,
TextField,
} from '@material-ui/core'
import FormControl from '@material-ui/core/FormControl'
import InputLabel from '@material-ui/core/InputLabel'
import MenuItem from '@material-ui/core/MenuItem'
import Paper from '@material-ui/core/Paper'
import Select from '@material-ui/core/Select'
import { createStyles, makeStyles, Theme, useTheme } from '@material-ui/core/styles'
import Table from '@material-ui/core/Table'
import TableBody from '@material-ui/core/TableBody'
import TableCell from '@material-ui/core/TableCell'
import TableContainer from '@material-ui/core/TableContainer'
import TableHead from '@material-ui/core/TableHead'
import TableRow from '@material-ui/core/TableRow'
import FileCopyIcon from '@material-ui/icons/FileCopy'
import LinkIcon from '@material-ui/icons/Link'
import MoreHorizIcon from '@material-ui/icons/MoreHoriz'
import RefreshIcon from '@material-ui/icons/Refresh'
import axios from 'axios'
import React, { useEffect } from 'react'
import { Link, useHistory } from 'react-router-dom'
import { getCompetitions, setFilterParams } from '../../../actions/competitions'
import { useAppDispatch, useAppSelector } from '../../../hooks'
import { Team } from '../../../interfaces/ApiModels'
import { CompetitionFilterParams } from '../../../interfaces/FilterParams'
import { FilterContainer, RemoveMenuItem, TopBar, YearFilterTextField } from '../styledComp'
import AddCompetition from './AddCompetition'
/**
* Component description:
* This component shows a list of all the competitions which a user can search through
* We can also start, duplicate or delete a competition
*/
// Use defined styling
const useStyles = makeStyles((theme: Theme) =>
createStyles({
table: {
},
margin: {
margin: theme.spacing(1),
},
paper: {
backgroundColor: theme.palette.background.paper,
boxShadow: theme.shadows[5],
padding: 4,
outline: 'none',
},
interface Code {
id: number
code: string
view_type_id: number
competition_id: number
team_id: number
}
const CompetitionManager: React.FC = (props: any) => {
// for dialog alert
const [openAlert, setOpen] = React.useState(false)
const theme = useTheme()
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'))
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null)
const [activeId, setActiveId] = React.useState<number | undefined>(undefined)
const [timerHandle, setTimerHandle] = React.useState<number | undefined>(undefined)
const [dialogIsOpen, setDialogIsOpen] = React.useState(false)
const [codes, setCodes] = React.useState<Code[]>([])
const [teams, setTeams] = React.useState<Team[]>([])
const [competitionName, setCompetitionName] = React.useState<string | undefined>(undefined)
const loading = useAppSelector((state) => state.user.userInfo === null)
const competitions = useAppSelector((state) => state.competitions.competitions)
const filterParams = useAppSelector((state) => state.competitions.filterParams)
const competitionTotal = useAppSelector((state) => state.competitions.total)
const cities = useAppSelector((state) => state.cities.cities)
const classes = useStyles()
const noFilterText = 'Alla'
const dispatch = useAppDispatch()
const history = useHistory()
const handleClick = (event: React.MouseEvent<HTMLButtonElement>, id: number) => {
setActiveId(id)
getCodes(id)
getTeams(id)
setAnchorEl(event.currentTarget)
}
const handleClose = () => {
setAnchorEl(null)
const handleCloseVerify = () => {
setOpen(false)
}
useEffect(() => {
dispatch(getCompetitions())
}, [])
// Searchfuntion to search for a specific string
const onSearchChange = (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
if (timerHandle) {
clearTimeout(timerHandle)
setTimerHandle(undefined)
}
//Only updates filter and api 100ms after last input was made
setTimerHandle(window.setTimeout(() => dispatch(getCompetitions()), 100))
dispatch(setFilterParams({ ...filterParams, name: event.target.value }))
}
const handleVerifyDelete = () => {
setOpen(true)
}
// Function to remove a competition from the systems database
const handleDeleteCompetition = async () => {
if (activeId) {
await axios
.then(() => {
setAnchorEl(null)
dispatch(getCompetitions()) // refresh the competition list
})
.catch(({ response }) => {
console.warn(response.data)
})
}
}
/** Start the competition by redirecting with URL with Code */
const operatorCode = codes.find((code) => code.view_type_id === 4)?.code
if (operatorCode) {
history.push(`/${operatorCode}`)
}
const getCodes = async (id: number) => {
.get(`/api/competitions/${id}/codes`)
.then((response) => {
setCodes(response.data.items)
})
.catch(console.log)
}
/** Fetch all the teams from the server that is connected to a specific competition*/
const getTeams = async (id: number) => {
.get(`/api/competitions/${id}/teams`)
.then((response) => {
setTeams(response.data.items)
})
.catch((err) => {
console.log(err)
})
}
const getCompetitionName = async () => {
await axios
.get(`/api/competitions/${activeId}`)
.then((response) => {
setCompetitionName(response.data.name)
})
.catch((err) => {
console.log(err)
})
}
const getTypeName = (code: Code) => {
let typeName = ''
switch (code.view_type_id) {
case 1:
const team = teams.find((team) => team.id === code.team_id)
if (team) {
typeName = team.name
} else {
typeName = 'Lagnamn hittades ej'
}
break
case 2:
typeName = 'Domare'
break
case 3:
typeName = 'Publik'
break
case 4:
break
default:
typeName = 'Typ hittades ej'
break
}
return typeName
}
const handleOpenDialog = async () => {
await getCompetitionName()
setDialogIsOpen(true)
}
const handleCloseDialog = () => {
setDialogIsOpen(false)
setAnchorEl(null)
const handleDuplicateCompetition = async () => {
if (activeId) {
await axios
.then(() => {
setAnchorEl(null)
dispatch(getCompetitions())
})
.catch(({ response }) => {
console.warn(response.data)
})
}
}
const handleFilterChange = (newParams: CompetitionFilterParams) => {
dispatch(setFilterParams(newParams))
dispatch(getCompetitions())
const refreshCode = async (code: Code) => {
if (activeId) {
await axios
.put(`/api/competitions/${activeId}/codes/${code.id}`)
.then(() => {
getCodes(activeId)
dispatch(getCompetitions())
})
.catch(({ response }) => {
console.warn(response.data)
})
}
<TextField className={classes.margin} value={filterParams.name || ''} onChange={onSearchChange} label="Sök" />
<FormControl className={classes.margin}>
<InputLabel shrink id="demo-customized-select-native">
Region
</InputLabel>
<Select
labelId="demo-customized-select-label"
id="demo-customized-select"
value={filterParams.cityId ? cities.find((city) => filterParams.cityId === city.id)?.name : noFilterText}
<MenuItem value={noFilterText} onClick={() => handleFilterChange({ ...filterParams, cityId: undefined })}>
{cities &&
cities.map((city) => (
<MenuItem
key={city.name}
value={city.name}
onClick={() => handleFilterChange({ ...filterParams, cityId: city.id })}
>
{city.name}
</MenuItem>
))}
<YearFilterTextField
label="År"
name="model.year"
type="number"
onChange={(event) => handleFilterChange({ ...filterParams, year: +event.target.value })}
margin="normal"
/>
</FilterContainer>
<TableContainer component={Paper}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Namn</TableCell>
<TableCell align="right">Region</TableCell>
<TableCell align="right">År</TableCell>
<TableCell align="right"></TableCell>
</TableRow>
</TableHead>
<TableBody>
{competitions &&
competitions.map((row) => (
<TableRow key={row.name}>
<TableCell scope="row">
<Button color="primary" component={Link} to={`/editor/competition-id=${row.id}`}>
{row.name}
</Button>
</TableCell>
<TableCell align="right">{cities.find((city) => city.id === row.city_id)?.name || ''}</TableCell>
<TableCell align="right">{row.year}</TableCell>
<TableCell align="right">
<Button onClick={(event) => handleClick(event, row.id)} data-testid={row.name}>
<MoreHorizIcon />
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
{/** We can't find any competitions at all or with a specific filter */}
{(!competitions || competitions.length === 0) && (
<Typography>Inga tävlingar hittades med nuvarande filter</Typography>
)}
<TablePagination
component="div"
rowsPerPageOptions={[]}
rowsPerPage={filterParams.pageSize}
count={competitionTotal}
page={filterParams.page}
onChangePage={(event, newPage) => handleFilterChange({ ...filterParams, page: newPage })}
/>
<Menu id="simple-menu" anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleClose}>
<MenuItem onClick={handleStartCompetition}>Starta</MenuItem>
<MenuItem onClick={handleOpenDialog}>Visa koder</MenuItem>
<MenuItem onClick={handleDuplicateCompetition}>Duplicera</MenuItem>
<RemoveMenuItem onClick={handleVerifyDelete} data-testid="removeCompetitionButton">
Ta bort
</RemoveMenuItem>
<Dialog
fullScreen={fullScreen}
open={openAlert}
onClose={handleCloseVerify}
aria-labelledby="responsive-dialog-title"
>
<DialogTitle id="responsive-dialog-title">{'Ta bort tävlingen?'}</DialogTitle>
<DialogContent>
<DialogContentText>
Är du säker på att du vill ta bort tävlingen och all dess information från systemet?
</DialogContentText>
</DialogContent>
<DialogActions>
<Button autoFocus onClick={handleCloseVerify} color="primary">
Avbryt
</Button>
<Button data-testid="acceptRemoveCompetition" onClick={handleDeleteCompetition} color="primary" autoFocus>
Ta bort
</Button>
</DialogActions>
</Dialog>
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
<Dialog
open={dialogIsOpen}
onClose={handleCloseDialog}
aria-labelledby="max-width-dialog-title"
maxWidth="xl"
fullWidth={false}
fullScreen={false}
>
<DialogTitle id="max-width-dialog-title" className={classes.paper}>
Koder för {competitionName}
</DialogTitle>
<DialogContent>
{/* <DialogContentText>Här visas tävlingskoderna till den valda tävlingen.</DialogContentText> */}
{codes.map((code) => (
<ListItem key={code.id} style={{ display: 'flex' }}>
<ListItemText primary={`${getTypeName(code)}: `} />
<Typography component="div">
<ListItemText style={{ textAlign: 'right', marginLeft: '10px' }}>
<Box fontFamily="Monospace" fontWeight="fontWeightBold">
{code.code}
</Box>
</ListItemText>
</Typography>
<Tooltip title="Generera ny kod" arrow>
<Button
margin-right="0px"
onClick={() => {
refreshCode(code)
}}
>
<RefreshIcon fontSize="small" />
</Button>
</Tooltip>
<Tooltip title="Kopiera kod" arrow>
<Button
margin-right="0px"
onClick={() => {
navigator.clipboard.writeText(code.code)
}}
>
<FileCopyIcon fontSize="small" />
</Button>
</Tooltip>
<Tooltip title="Kopiera länk" arrow>
<Button
margin-right="0px"
onClick={() => {
navigator.clipboard.writeText(`${window.location.host}/${code.code}`)
}}
>
<LinkIcon fontSize="small" />
</Button>
</Tooltip>
</ListItem>
))}
</DialogContent>
<DialogActions>
<Button onClick={handleCloseDialog} color="primary">
Stäng
</Button>
</DialogActions>
</Dialog>
</div>
)
}
export default CompetitionManager