add pagination + view toggles

This commit is contained in:
Daniel 2021-11-09 18:11:49 -05:00
parent da3e0c0249
commit 1f4bd44982
5 changed files with 208 additions and 28 deletions

View File

@ -47,6 +47,7 @@
}],
"keyword-spacing": ["error"],
"linebreak-style": "off",
"no-console": ["warn", { "allow": [ "info", "warn", "error" ] }],
"no-plusplus": "off",
"no-prototype-builtins": "off",
"no-undef": "error",

View File

@ -1,8 +1,10 @@
import React, { ChangeEventHandler, FormEvent, useEffect, useRef, useState } from 'react';
import React, { FormEvent, useEffect, useRef, useState } from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import API, { sets } from '../../SpreadsheetData/API';
import search_api from '../../collection/search/search';
import { Loading, UnderConstruction } from '../../Snippets';
import { Loading } from '../../Snippets';
import { Modal, Fab, Zoom, useTheme } from '@mui/material';
import SearchIcon from '@mui/icons-material/Search';
const initInput = () => {
/* @ts-ignore */
@ -115,11 +117,13 @@ const updateQuery = (input, history) => {
};
export default function Search ({ setContent, setInfo }) {
const theme = useTheme();
const history = useHistory();
const location = useLocation();
const prevLocation = useRef<any>(undefined);
const [input, setInput] = useState(initInput());
const [loaded, setLoaded] = useState(false);
const [open, setOpen] = useState(false);
useEffect(() => {
setInfo({ 'text': 'Loading..' });
@ -176,5 +180,45 @@ export default function Search ({ setContent, setInfo }) {
return (<Loading />);
}
return <UnderConstruction />;
const form = (<>
</>);
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const transitionDuration = {
enter: theme.transitions.duration.enteringScreen,
exit: theme.transitions.duration.leavingScreen,
};
return (<>
<Modal
open={open}
onClose={handleClose}
>
{form}
</Modal>
{!open && form}
<Zoom
in={!open}
timeout={transitionDuration}
style={{
transitionDelay: `${!open ? transitionDuration.exit : 0}ms`,
}}
unmountOnExit
>
<Fab aria-label="search"
sx={{ position: 'fixed', bottom: 16, right: 16 }}
onClick={handleOpen}
>
<SearchIcon />
</Fab>
</Zoom>
</>);
}

View File

@ -14,3 +14,21 @@
.icon24 {
height: 24px;
}
.name {
-webkit-user-select: all;
-moz-user-select: all;
-ms-user-select: all;
user-select: all;
}
.name .subname::before {
content: "\a ";
white-space: pre;
}
.name .subname {
font-size: 13px;
padding-bottom: 4px;
display: inherit;
}

View File

@ -1,15 +1,48 @@
import { Card, Typography } from '@mui/material';
import {
Box, Card, Checkbox, createTheme, FormControl, FormControlLabel, InputLabel, MenuItem, Pagination, Paper, Select, SelectChangeEvent, styled, ThemeProvider, Typography
} from '@mui/material';
import React, { useState } from 'react';
import { Attack as AttackCard, Card as ChaoticCard } from '../../common/definitions';
import Attack from './Attack';
import { chaoticCardProps, statsType } from './ChaoticCard';
import Search from './Search';
import { Card as ChaoticCard, Attack as AttackCard } from '../../common/definitions';
import './collection.scss';
type statsType = "avg" | "min" | "max";
let theme = createTheme({
breakpoints: {
values: {
xs: 0,
sm: 600,
md: 900,
lg: 1200,
xl: 1536,
}
}
});
export default function Collection (props) {
const [loaded, setLoaded] = useState(false);
theme = createTheme(theme, createTheme({
components: {
MuiCard: {
styleOverrides: {
root: {
backgroundColor: "#1F1F1F",
color: "gray",
paddingLeft: theme.spacing(.5)
}
}
}
}
}));
const CustomSelect = styled(Select)(() => ({
'& > .MuiSelect-outlined': {
paddingTop: "5px",
paddingBottom: "5px"
}
}));
export default function Collection (_props) {
const [p, sp] = useState(1);
const [n, sn] = useState(10);
const [ext, setExt] = useState(false);
@ -17,34 +50,119 @@ export default function Collection (props) {
const [hideStats, setHideStats] = useState(false);
const [content, setContent] = useState<ChaoticCard[]>([]);
const [info, setInfo] = useState<{text?: string}>({});
const handlePerPage = (event: SelectChangeEvent<number>) => {
sn(event.target.value as number);
};
const handlePage = (event: React.ChangeEvent<unknown>, value: number) => {
sp(value);
};
const hanldeStats = (event: SelectChangeEvent<string>) => {
setStats(event.target.value as statsType);
};
const handleExt = (event: React.ChangeEvent<HTMLInputElement>) => {
setExt(event.target.checked);
};
const handleHideStats = (event: React.ChangeEvent<HTMLInputElement>) => {
setHideStats(event.target.checked);
};
return (<>
<Search {...({ setContent, setInfo })} />
{info.text ? (
<Typography style={{ textAlign: 'left' }}>{info.text}</Typography>
) : (
<CardList
cards={content.slice(n * (p-1), n * p)}
{...({ ext, stats, hideStats })}
/>
)}
</>);
return (<ThemeProvider theme={theme}>
<Paper square sx={{ minHeight: "100vh", height: "100%", paddingLeft: theme.spacing(1), paddingRight: theme.spacing(1) }}>
<Search {...({ setContent, setInfo })} />
<Box sx={{
display: 'flex',
width: 'fit-content',
flexWrap: 'wrap',
alignItems: "flex-start",
rowGap: theme.spacing(1),
columnGap: theme.spacing(1),
paddingTop: theme.spacing(2),
paddingBottom: theme.spacing(1)
}}>
<Typography>{content.length} results</Typography>
<FormControl>
<InputLabel htmlFor="per-page">Per Page</InputLabel>
<CustomSelect
id="per-page"
value={n}
/* @ts-ignore */
onChange={handlePerPage}
sx={{ marginLeft: "2px", width: "70px" }}
>
<MenuItem value={5}>5</MenuItem>
<MenuItem value={10}>10</MenuItem>
<MenuItem value={25}>25</MenuItem>
<MenuItem value={50}>50</MenuItem>
</CustomSelect>
</FormControl>
<Pagination variant="outlined" shape="rounded"
count={Math.ceil(content.length / n)}
page={p}
onChange={handlePage}
/>
<FormControl>
<InputLabel htmlFor="stats-drop">Stats</InputLabel>
<CustomSelect
id="stats-drop"
value={stats}
/* @ts-ignore */
onChange={hanldeStats}
sx={{ width: "106px" }}
>
<MenuItem value="min">Min</MenuItem>
<MenuItem value="avg">Average</MenuItem>
<MenuItem value="max">Max</MenuItem>
</CustomSelect>
</FormControl>
<FormControlLabel label="Extended"
labelPlacement="start"
control={<Checkbox checked={ext} onChange={handleExt} />}
sx={{
marginLeft: 0,
marginRight: 0,
'& > .MuiCheckbox-root': {
padding: 0
}
}}
/>
<FormControlLabel label="Hide Stats"
labelPlacement="start"
control={<Checkbox checked={hideStats} onChange={handleHideStats} />}
sx={{
marginLeft: 0,
marginRight: 0,
'& > .MuiCheckbox-root': {
padding: 0
}
}}
/>
</Box>
{info.text ? (
<Typography style={{ textAlign: 'left' }}>{info.text}</Typography>
) : (
<CardList
cards={content.slice(n * (p-1), n * p)}
{...({ ext, stats, hideStats })}
/>
)}
</Paper>
</ThemeProvider>);
}
interface listProps {
type listProps = Omit<chaoticCardProps<ChaoticCard>, "card"> & {
cards: ChaoticCard[]
info?: string
ext: boolean
stats: statsType
hideStats: boolean
}
const CardList = ({ cards, info, ...props }: listProps) => {
const CardList = ({ cards, ...props }: listProps) => {
const list = cards.map((card, i) => {
switch (card.gsx$type) {
case "Attacks":
return (<Attack card={card as AttackCard} key={card.gsx$name} {...props}/>);
return (<Attack card={card as AttackCard} key={card.gsx$name+card.gsx$set} {...props}/>);
// case "Battlegear":
// return (<Battlegear card={card} key={i} {...props}/>);
// case "Creatures":

View File

@ -36,7 +36,6 @@ export default function App() {
const isMobile = useCheckMobileScreen();
useEffect(() => {
console.log(document.styleSheets);
if (isMobile) {
document.styleSheets[0].disabled = true;
} else {