1
0
gonito-frontend/src/components/specific_challenge/Table.js

284 lines
8.4 KiB
JavaScript

import React from 'react';
import { Container, FlexColumn, FlexRow, Grid } from '../../utils/containers';
import Media from 'react-media';
import theme from '../../utils/theme';
import { ELEMENTS_PER_PAGE, IS_MOBILE } from '../../utils/globals';
import { Body, Medium } from '../../utils/fonts';
import styled from 'styled-components';
import ColumnFilterIcon from './ColumnFilterIcon';
const TableStyle = styled(FlexColumn)`
overflow-x: ${({metrics}) => metrics > 10 ? 'scroll' : 'auto'};
`;
const Line = styled(FlexRow)`
position: absolute;
top: ${({ top }) => (top ? top : 'auto')};
bottom: ${({ bottom }) => (bottom ? bottom : 'auto')};
left: 0;
width: 100%;
background-color: ${({ theme }) => theme.colors.dark04};
height: ${({ height }) => (height ? height : '1px')};
`;
const MobileTableStyle = styled(Container)`
width: 100%;
border-collapse: collapse;
margin: 32px 0;
tr:nth-of-type(odd) {
background: ${({ theme }) => theme.colors.dark03};
}
th {
background: ${({ theme }) => theme.colors.dark05};
color: ${({ theme }) => theme.colors.white};
}
td,
th {
padding: 6px;
border: 1px solid ${({ theme }) => theme.colors.white};
text-align: left;
}
display: block;
thead,
tbody,
th,
td {
display: block;
}
thead tr {
position: absolute;
top: -9999px;
left: -9999px;
}
td {
border: none;
border-bottom: 1px solid ${({ theme }) => theme.colors.dark01};
position: relative;
padding-left: 50%;
}
.mobile-table-header {
font-weight: 400;
position: absolute;
top: 6px;
left: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
}
`;
const Table = (props) => {
const [, updateState] = React.useState();
const forceUpdate = React.useCallback(() => updateState({}), []);
const [activeIcon, setActiveIcon] = React.useState(null);
const [rotateActiveIcon, setRotateActiveIcon] = React.useState(false);
const metricsRender = (elem) => {
if (!props.iterableColumnElement) return <></>;
if (Array.isArray(elem[props.iterableColumnElement.name]))
elem = elem[props.iterableColumnElement.name];
else {
let newElem = [];
for (let metric of props.possibleMetrics) {
if (Object.hasOwn(elem, props.iterableColumnElement.name)) {
if (elem[props.iterableColumnElement.name][metric] === '-1')
newElem.push('N/A');
else newElem.push(elem[props.iterableColumnElement.name][metric]);
} else {
newElem.push('N/A');
}
}
elem = newElem;
}
let indexModificator = 2;
if (props.tableType === 'leaderboard') indexModificator = 4;
if (props.tableType === 'allEntries') indexModificator = 3;
return elem.map((iterableElem, i) => {
return (
<Body
key={`metric-result-${i}`}
as="td"
order={props.iterableColumnElement.order}
textAlign={props.iterableColumnElement.align}
minWidth="88px"
margin="auto 0"
overflowWrap="anywhere"
>
{IS_MOBILE() && (
<Container className="mobile-table-header">
{props.headerElements[indexModificator + i]}
</Container>
)}
{props.iterableColumnElement.format
? props.iterableColumnElement.format(iterableElem)
: iterableElem}
</Body>
);
});
};
const rowRender = (elem) => {
let RowStyle = Body;
if (elem.submitter === props.user) RowStyle = Medium;
return props.staticColumnElements.map((elemName, i) => {
return (
<RowStyle
key={`leaderboard-static-elemName-${i}-${elem[elemName.name]}`}
as="td"
order={elemName.order}
textAlign={elemName.align}
margin="auto 0"
minWidth="88px"
overflowWrap="anywhere"
>
{IS_MOBILE() && (
<Container className="mobile-table-header">
{props.headerElements[i]}
</Container>
)}
{elemName.format
? elemName.format(elem[elemName.name])
: elem[elemName.name]}
</RowStyle>
);
});
};
const desktopRender = () => {
const n = (props.pageNr - 1) * (ELEMENTS_PER_PAGE * 2);
let elementsToMap = props.elements.slice(n, n + ELEMENTS_PER_PAGE * 2);
if (elementsToMap.length > 0) {
return (
<TableStyle as="table" margin="32px 0 72px 0" width="100%">
<FlexColumn as="tbody" width="100%">
<Grid
as="tr"
gridGap="20px"
position="relative"
width="100%"
padding="0 6px"
minHeight="44px"
margin="0 0 6px 0"
gridTemplateColumns={props.gridTemplateColumns}
>
{props.headerElements.map((elem, i) => {
return (
<FlexRow
key={`table-header-${i}`}
alignmentX="flex-start"
as="td"
cursor="pointer"
onClick={() => {
if (activeIcon === i) {
let newRotateActiveIcon = !rotateActiveIcon;
setRotateActiveIcon(newRotateActiveIcon);
} else {
setRotateActiveIcon(false);
}
setActiveIcon(i);
props.sortByUpdate(elem, i);
forceUpdate();
}}
>
<Medium
cursor={elem !== '#' ? 'pointer' : ''}
textAlign={elem === 'when' ? 'right' : 'left'}
width={elem === 'when' ? '100%' : 'auto'}
padding="0 4px 0 0"
overflowWrap="anywhere"
minWidth="72px"
// minWidth={elem === 'result' ? '72px' : 'none'}
>
{elem.replace('.', ' ')}
</Medium>
{elem !== '#' && (
<ColumnFilterIcon
cursor="pointer"
index={i}
active={activeIcon}
rotateIcon={rotateActiveIcon}
/>
)}
</FlexRow>
);
})}
<Line
height="2px"
top="calc(100% + 2px)"
as="td"
shadow={theme.shadow}
/>
</Grid>
{elementsToMap.map((elem, index) => {
return (
<Grid
as="tr"
key={`leaderboard-row-${index}`}
backgroundColor={
index % 2 === 1 ? theme.colors.dark01 : 'transparent'
}
gridTemplateColumns={props.gridTemplateColumns}
gridGap="20px"
position="relative"
width="100%"
padding="4px"
minHeight="48px"
>
{rowRender(elem)}
{props.headerElements ? metricsRender(elem) : ''}
</Grid>
);
})}
</FlexColumn>
</TableStyle>
);
}
return <Medium margin="72px 0">No results ;c</Medium>;
};
const mobileRender = () => {
const n = (props.pageNr - 1) * ELEMENTS_PER_PAGE;
let elementsToMap = props.elements.slice(n, n + ELEMENTS_PER_PAGE);
if (elementsToMap.length > 0) {
return (
<MobileTableStyle
as="table"
staticColumnElements={props.staticColumnElements}
headerElements={props.headerElements}
>
<Container as="tbody">
{elementsToMap.map((elem, index) => {
return (
<Grid as="tr" key={`leaderboard-row-${index}`}>
{rowRender(elem)}
{props.headerElements ? metricsRender(elem) : ''}
</Grid>
);
})}
</Container>
</MobileTableStyle>
);
}
return <Medium margin="72px 0">No results ;c</Medium>;
};
return (
<>
<Media query={theme.mobile}>{mobileRender()}</Media>
<Media query={theme.desktop}>{desktopRender()}</Media>
</>
);
};
export default Table;