Creature mobile

This commit is contained in:
Daniel 2021-11-22 19:34:15 -05:00
parent 8891024ef6
commit 0e0aa1d341
9 changed files with 306 additions and 108 deletions

View File

@ -14,7 +14,7 @@ export function abilityText(props) {
};
const elements = {
regex: new RegExp(/(\b((fire)|(air)|(earth)|(water)))/i),
regex: new RegExp(/(\b((fire)|(air)|(earth)|(water))\b)/i),
fn: (key, result) => {
return (<span key={key}><ElementIcon element={result[0].replace(/\b/, '')} value="true" size={props.size || "icon14"} />{result[0]}</span>);
}

View File

@ -23,10 +23,12 @@ type componentProps = chaoticCardProps<ChaoticCard> & {
left: JSX.Element
right: JSX.Element
content: JSX.Element
right2?: JSX.Element
imageCover?: JSX.Element
}
export const CardComponent = (
{ card, ext, extend, left, right, content }: componentProps
{ card, ext, extend, imageCover, left, right, content, right2 }: componentProps
) => {
const loc = card.gsx$type === "Locations";
@ -46,6 +48,9 @@ export const CardComponent = (
<Box>
{right}
</Box>
{right2 && <Box>
{right2}
</Box>}
</Card>
) : (
<Card>
@ -58,6 +63,9 @@ export const CardComponent = (
alt={`${card.gsx$name} card`}
onClick={() => extend(null)}
/>
{imageCover &&
<div className="image-cover" onClick={() => extend(null)}>{imageCover}</div>
}
<CardContent sx={{
flex: '1 0', minWidth: "310px",
width: `calc(100% - ${loc ? " 350px" : "250px"})`

View File

@ -0,0 +1,132 @@
import { Typography, styled } from '@mui/material';
import React from 'react';
import { Creature } from "../../common/definitions";
import { Name, RarityIcon, TribeIcon, MugicIcon, ElementIcon, DisciplineIcon } from '../../Snippets';
import { abilityText } from '../../Snippets/abilityText';
import { uniqueText } from '../../Snippets/uniqueText';
import { CardBase, CardComponent, Unique, Flavor } from "./CardBase";
const TribeLine = ({ card }: {card: Creature}) => {
let types = card.gsx$types;
// Moves "Past" in front of tribe due to db entry order
let past = false;
if (types.toLowerCase().includes("past")) {
past = true;
types = types.replace(/past /i, '');
}
const line = ` ${ past ? "Past " : "" }${types}`;
return <Typography><TribeIcon tribe={card.gsx$tribe} />{line}</Typography>;
};
const MugicCounter = ({ card }: { card: Creature }) => {
const mugic = [] as JSX.Element[];
for (let i = 0; i < Number(card.gsx$mugicability); i++) {
mugic.push(<MugicIcon key={i} tribe={card.gsx$tribe} />);
}
return <>{mugic}</>;
};
const Brainwashed = styled(Typography)(() => ({
borderRadius: "3px",
backgroundColor: "#dcdddf",
color: "black"
}));
const Stat = styled(Typography)(() => ({
width: "40px",
lineHeight: "normal"
}));
const CreatureCard: CardBase<Creature> = (props) => {
const { card, stats, hideStats } = props;
const ability = abilityText({ ability: card.gsx$ability, tribe: card.gsx$tribe, size: "icon16" });
const brainwashed = abilityText({ ability: card.gsx$brainwashed, tribe: card.gsx$tribe, size: "icon16" });
const unique = uniqueText({ data: { unique: card.gsx$unique, loyal: card.gsx$loyal, legendary: card.gsx$legendary }});
const flavor = card.gsx$flavortext;
const stat_range = (stat: string) => {
const name = card.gsx$name;
if (name && name == "Aa'une the Oligarch, Avatar") return Number(stat);
if (stats == "min") return Number(stat) - 10;
if (stats == "max") return Number(stat) + 10;
return Number(stat);
};
const energy_range = (energy: string) => {
const name = card.gsx$name;
if (name && name == "Aa'une the Oligarch, Avatar") return Number(energy);
if (stats == "min") return Number(energy) - 5;
if (stats == "max") return Number(energy) + 5;
return Number(energy);
};
const courage = stat_range(card.gsx$courage);
const power = stat_range(card.gsx$power);
const wisdom = stat_range(card.gsx$wisdom);
const speed = stat_range(card.gsx$speed);
const energy = energy_range(card.gsx$energy);
return (
<CardComponent {...props}
left={<>
<Name name={card.gsx$name} />
<RarityIcon size="icon20" set={card.gsx$set} rarity={card.gsx$rarity} />
<TribeLine card={card} />
<Typography>
<ElementIcon element="fire" value={card.gsx$elements.toLowerCase().indexOf("fire") >=0} />&nbsp;
<ElementIcon element="air" value={card.gsx$elements.toLowerCase().indexOf("air") >=0} />&nbsp;
<ElementIcon element="earth" value={card.gsx$elements.toLowerCase().indexOf("earth") >=0} />&nbsp;
<ElementIcon element="water" value={card.gsx$elements.toLowerCase().indexOf("water") >=0} />
</Typography>
<MugicCounter card={card} />
</>}
right={<>
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
{brainwashed && <Brainwashed>{brainwashed}</Brainwashed>}
{unique && <Unique>{unique}</Unique>}
{card.gsx$types.includes("Chieftain") &&
<Flavor>(Minions use Brainwashed text. Minions may only play Generic Mugic.)</Flavor>
}
{flavor && <Flavor>{flavor}</Flavor>}
</>}
right2={<>
<Stat>{courage}<DisciplineIcon discipline="courage" /></Stat>
<Stat>{power}<DisciplineIcon discipline="power" /></Stat>
<Stat>{wisdom}<DisciplineIcon discipline="wisdom" /></Stat>
<Stat>{speed}<DisciplineIcon discipline="speed" /></Stat>
<Stat sx={{ fontWeight: "bold" }}>{energy}</Stat>
</>}
{...((!hideStats) ? { imageCover: (
<div>
<span key="courage" {...(courage >= 100 ? { className: "long" } : null)}>{courage}</span>
<span key="power" {...(power >= 100 ? { className: "long" } : null)}>{power}</span>
<span key="wisdom" {...(wisdom >= 100 ? { className: "long" } : null)}>{wisdom}</span>
<span key="speed" {...(speed >= 100 ? { className: "long" } : null)}>{speed}</span>
<span key="energy" {...(energy >= 100 ? { className: "long" } : null)}>{energy}</span>
</div>
) }
: undefined)}
content={<>
<Name name={card.gsx$name} />
<span>{stat_range(card.gsx$courage)}&nbsp;<DisciplineIcon discipline="courage" /></span>&nbsp;
<span>{stat_range(card.gsx$power)}&nbsp;<DisciplineIcon discipline="power" /></span>&nbsp;
<span>{stat_range(card.gsx$wisdom)}&nbsp;<DisciplineIcon discipline="wisdom" /></span>&nbsp;
<span>{stat_range(card.gsx$speed)}&nbsp;<DisciplineIcon discipline="speed" /></span>&nbsp;
<span style={{ fontWeight: 'bold' }}>{energy_range(card.gsx$energy)}</span>
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
{brainwashed && <Brainwashed>{brainwashed}</Brainwashed>}
{unique && <Unique>{unique}</Unique>}
{card.gsx$types.includes("Chieftain") &&
<Flavor>(Minions use Brainwashed text. Minions may only play Generic Mugic.)</Flavor>
}
{flavor && <Flavor>{flavor}</Flavor>}
<Typography>Art By: {card.gsx$artist}</Typography>
</>}
/>
);
};
export default CreatureCard;

View File

@ -7,7 +7,7 @@ import { uniqueText } from "../../Snippets/uniqueText";
import { CardBase, CardComponent, Unique, Flavor } from "./CardBase";
const MugicCounter = ({ card }: {card:Mugic}) => {
const MugicCounter = ({ card }: { card: Mugic }) => {
const mugicCounters = [] as JSX.Element[];
if (Number(card.gsx$cost) === 0) {
mugicCounters.push(<MugicIcon tribe={card.gsx$tribe} key={0} amount={"0"}/>);
@ -31,7 +31,7 @@ const MugicCounter = ({ card }: {card:Mugic}) => {
const MugicCard: CardBase<Mugic> = (props) => {
const { card } = props;
const ability = abilityText({ ability: card.gsx$ability, size: "icon16" });
const ability = abilityText({ ability: card.gsx$ability, tribe: card.gsx$tribe, size: "icon16" });
const unique = uniqueText({ data: { unique: card.gsx$unique, loyal: card.gsx$loyal, legendary: card.gsx$legendary }});
const flavor = card.gsx$flavortext;

View File

@ -139,7 +139,7 @@ export default function Search ({ setContent, setInfo }) {
.catch(() => {});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (location != prevLocation.current) {
prevLocation.current = location;
@ -179,11 +179,7 @@ export default function Search ({ setContent, setInfo }) {
});
};
if (loaded == false) {
return (<></>);
}
const form = (<>
const form = ((loaded == false) ? <></> : <>
</>);
@ -207,7 +203,6 @@ export default function Search ({ setContent, setInfo }) {
>
{form}
</Modal>
{!open && form}
<Zoom
in={!open}
timeout={transitionDuration}

View File

@ -39,3 +39,53 @@
padding-bottom: 4px;
display: inherit;
}
.image-cover {
width: 250px;
height: 350px;
background-size: cover;
box-sizing: content-box;
position: absolute;
& > div {
height: 100%;
width: 100%;
text-align: left;
span {
position: relative;
color: black;
display: block;
left: 28px;
font-size: 12px;
font-weight: bold;
&.long {
left: 22px;
}
}
span:nth-of-type(1) {
top: 222px;
}
span:nth-of-type(2) {
top: 232px;
}
span:nth-of-type(3) {
top: 242px;
}
span:nth-of-type(4) {
top: 252px;
}
span:nth-of-type(5) {
text-align: right;
top: 260px;
left: -17px;
font-size: 21px;
&.long {
left: -12px;
}
}
}
}

View File

@ -1,13 +1,15 @@
import {
Box, Card, Checkbox, createTheme, FormControl, FormControlLabel, InputLabel, MenuItem, Pagination, Paper, Select, SelectChangeEvent, styled, ThemeProvider, Typography
import {
AppBar, Box, Card, Checkbox, createTheme, FormControl, FormControlLabel, InputLabel, MenuItem,
Pagination, Paper, Select, SelectChangeEvent, styled, ThemeProvider, Toolbar, Typography
} from '@mui/material';
import React, { useEffect, useState } from 'react';
import { Attack, Battlegear, Location, Card as ChaoticCard, Mugic } from '../../common/definitions';
import { Attack, Battlegear, Card as ChaoticCard, Location, Mugic, Creature } from '../../common/definitions';
import AttackCard from './Attack';
import BattlegearCard from './Battlegear';
import { chaoticCardProps, statsType } from './CardBase';
import CreatureCard from './Creature';
import LocationCard from './Location';
import MugicCard from './Mugic';
import { chaoticCardProps, statsType } from './CardBase';
import Search from './Search';
import './collection.scss';
@ -122,74 +124,76 @@ export default function Collection (_props) {
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>
<AppBar color="inherit" sx={{ paddingLeft: theme.spacing(1) }} >
<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={{
margin: "auto 0",
'& > .MuiCheckbox-root': {
padding: 0
}
}}
/>
<FormControlLabel label="Hide Stats"
labelPlacement="start"
control={<Checkbox checked={hideStats} onChange={handleHideStats} />}
sx={{
margin: "auto 0",
'& > .MuiCheckbox-root': {
padding: 0
}
}}
/>
</Box>
</AppBar>
<Toolbar />
{info.text ? (
<Typography style={{ textAlign: 'left' }}>{info.text}</Typography>
) : (
@ -227,8 +231,12 @@ const CardList = ({ cards, selected, ext, ...props }: listProps) => {
ext={(isSelected(card) || ext)}
{...props}
/>);
// case "Creatures":
// return (<Creature card={card} key={i} {...props}/>);
case "Creatures":
return (<CreatureCard key={card.gsx$name+card.gsx$set}
card={card as Creature}
ext={(isSelected(card) || ext)}
{...props}
/>);
case "Locations":
return (<LocationCard key={card.gsx$name+card.gsx$set}
card={card as Location}

View File

@ -1,5 +1,5 @@
import React, { useEffect } from 'react';
import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-dom';
import { Route, Switch, Redirect } from 'react-router-dom';
import loadable from '@loadable/component';
import useCheckMobileScreen from './_hooks/useCheckMobileScreen';
@ -43,26 +43,28 @@ export default function App() {
}
}, [isMobile]);
useEffect(() => {
console.log("render");
}, []);
return (
<Router>
<Switch>
<Route path="/beta/collection" component={Collection} />
<Route path="/beta">
{({ location }) => <Redirect to={location.pathname.replace("/beta", "")} /> }
</Route>
{isMobile && <Route path="/collection" component={MobileCollection} />}
{/* Normal Routes */}
<Base>
<Route exact path="/" component={Home} />
<Route path="/PageNotFound" component={PageNotFound} />
<Route path="/UnderConstruction" component={UnderConstruction} />
<Route path="/EnterTheCode" component={EnterTheCode} />
<Route path="/create" component={Create} />
<Route path="/collection" component={Collection} />
<Route path="/portal" component={Portal} />
</Base>
</Switch>
</Router>
<Switch>
<Route path="/beta/collection" component={Collection} />
<Route path="/beta">
{({ location }) => <Redirect to={location.pathname.replace("/beta", "")} /> }
</Route>
{isMobile && <Route path="/collection" component={MobileCollection} />}
{/* Normal Routes */}
<Base>
<Route exact path="/" component={Home} />
<Route path="/PageNotFound" component={PageNotFound} />
<Route path="/UnderConstruction" component={UnderConstruction} />
<Route path="/EnterTheCode" component={EnterTheCode} />
<Route path="/create" component={Create} />
<Route path="/collection" component={Collection} />
<Route path="/portal" component={Portal} />
</Base>
</Switch>
);
}

View File

@ -1,10 +1,13 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './components/app';
const rootElement = document.getElementById('root');
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</React.StrictMode>,
document.getElementById('root')
</BrowserRouter>,
rootElement
);