Battlegear mobile

This commit is contained in:
Daniel 2021-11-19 18:02:13 -05:00
parent 1f4bd44982
commit 4348e9f2a0
6 changed files with 211 additions and 82 deletions

View File

@ -1,68 +1,46 @@
import { Card, CardContent, CardHeader, CardMedia, Typography, Box } from '@mui/material';
import { Typography } from '@mui/material';
import React from 'react';
import { Attack } from "../../common/definitions";
import { AttackIcon, ElementIcon, Name, RarityIcon } from '../../Snippets';
import { abilityText } from '../../Snippets/abilityText';
import { uniqueText } from '../../Snippets/uniqueText';
import API from '../../SpreadsheetData';
import { ChaoticCard } from './ChaoticCard';
import { CardBase, CardComponent } from './CardBase';
const AttackCard: ChaoticCard<Attack> = ({ card, ext }) => {
const AttackCard: CardBase<Attack> = (props) => {
const { card } = props;
const ability = abilityText({ ability: card.gsx$ability });
const unique = uniqueText({ data: { unique: card.gsx$unique, loyal: card.gsx$loyal, legendary: card.gsx$legendary }});
const flavor = card.gsx$flavortext;
return (ext === false)
? (
<Card sx={{ display: 'flex' }}>
<CardMedia
component="img"
sx={{ height: "100px", width: "96px" }}
image={API.base_image + (card.gsx$thumb||API.thumb_missing)}
alt={`${card.gsx$name} thumb`}
/>
<Box sx={{ display: 'flex', flexDirection: 'column', marginLeft: 1, width: "30%" }}>
<Name name={card.gsx$name} />
<RarityIcon set={card.gsx$set} rarity={card.gsx$rarity} />
<Typography><AttackIcon bp={card.gsx$bp} /> Attack - {card.gsx$bp}</Typography>
<Typography>
{`${card.gsx$base} | `}
<ElementIcon element="fire" value={card.gsx$fire} />{`${card.gsx$fire} `}
<ElementIcon element="air" value={card.gsx$air} />{`${card.gsx$air} `}
<ElementIcon element="earth" value={card.gsx$earth} />{`${card.gsx$earth} `}
<ElementIcon element="water" value={card.gsx$water} />{`${card.gsx$water}`}
</Typography>
</Box>
<Box sx={{ display: 'flex' }}>
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
{unique && <Typography>{unique}</Typography>}
{flavor && <Typography>{flavor}</Typography>}
</Box>
</Card>
)
: (
<Card>
<CardHeader
title={<Name name={card.gsx$name} />}
/>
<Box sx={{ display: 'flex', flexWrap: 'wrap', alignItems: "flex-start" }}>
<CardMedia
component="img"
sx={{ width: "250px" }}
height="350"
image={API.cardImage(card)}
alt={`${card.gsx$name} card`}
/>
<CardContent sx={{ flex: '1 0 auto', minWidth: "310px" }}>
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
{unique && <Typography>{unique}</Typography>}
{flavor && <Typography>{flavor}</Typography>}
<Typography>Art By: {card.gsx$artist}</Typography>
</CardContent>
</Box>
</Card>
);
return (
<CardComponent {...props}
right={<>
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
{unique && <Typography>{unique}</Typography>}
{flavor && <Typography>{flavor}</Typography>}
</>}
left={<>
<Name name={card.gsx$name} />
<RarityIcon set={card.gsx$set} rarity={card.gsx$rarity} />
<Typography><AttackIcon bp={card.gsx$bp} /> Attack - {card.gsx$bp}</Typography>
<Typography>
{`${card.gsx$base} | `}
<ElementIcon element="fire" value={card.gsx$fire} />{`${card.gsx$fire} `}
<ElementIcon element="air" value={card.gsx$air} />{`${card.gsx$air} `}
<ElementIcon element="earth" value={card.gsx$earth} />{`${card.gsx$earth} `}
<ElementIcon element="water" value={card.gsx$water} />{`${card.gsx$water}`}
</Typography>
</>}
content={<>
<Name name={card.gsx$name} />
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
{unique && <Typography>{unique}</Typography>}
{flavor && <Typography>{flavor}</Typography>}
<Typography>Art By: {card.gsx$artist}</Typography>
</>}
/>
);
};
export default AttackCard;

View File

@ -0,0 +1,39 @@
import { Typography } from '@mui/material';
import React from 'react';
import { BattlegearIcon, Name, RarityIcon } from '../../Snippets';
import { Battlegear } from '../../common/definitions';
import { abilityText } from '../../Snippets/abilityText';
import { uniqueText } from '../../Snippets/uniqueText';
import { CardBase, CardComponent } from './CardBase';
const BattlegearCard: CardBase<Battlegear> = (props) => {
const { card } = props;
const ability = abilityText({ ability: card.gsx$ability });
const unique = uniqueText({ data: { unique: card.gsx$unique, loyal: card.gsx$loyal, legendary: card.gsx$legendary }});
const flavor = card.gsx$flavortext;
return (
<CardComponent {...props}
left={<>
<Name name={card.gsx$name} />
<RarityIcon set={card.gsx$set} rarity={card.gsx$rarity} />
<Typography><BattlegearIcon /> Battlegear{card.gsx$types.length > 0 ? ` - ${card.gsx$types}` : null}</Typography>
</>}
right={<>
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
{unique && <Typography>{unique}</Typography>}
{flavor && <Typography>{flavor}</Typography>}
</>}
content={<>
<Name name={card.gsx$name} />
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
{unique && <Typography>{unique}</Typography>}
{flavor && <Typography>{flavor}</Typography>}
<Typography>Art By: {card.gsx$artist}</Typography>
</>}
/>
);
};
export default BattlegearCard;

View File

@ -0,0 +1,65 @@
import { Box, Card, CardMedia, CardContent } from '@mui/material';
import React from 'react';
import { Card as ChaoticCard } from "../../common/definitions";
import API from '../../SpreadsheetData';
export type statsType = "avg" | "min" | "max";
export interface chaoticCardProps<T extends ChaoticCard> {
card: T
ext: boolean
stats: statsType
hideStats: boolean
extend: (name: string) => void
}
export interface CardBase<T extends ChaoticCard> {
(props: chaoticCardProps<T>): JSX.Element
}
type componentProps = chaoticCardProps<ChaoticCard> & {
left: JSX.Element
right: JSX.Element
content: JSX.Element
}
export const CardComponent = (
{ card, ext, extend, left, right, content }: componentProps
) => {
return (ext === false)
? (
<Card sx={{ display: 'flex' }}>
<CardMedia
component="img"
sx={{ height: "100px", width: "96px" }}
image={API.base_image + (card.gsx$thumb||API.thumb_missing)}
alt={`${card.gsx$name} thumb`}
onClick={() => extend(card.gsx$name)}
/>
<Box sx={{ display: 'flex', flexDirection: 'column', marginLeft: 1, width: "30%" }}>
{left}
</Box>
<Box sx={{ display: 'flex' }}>
{right}
</Box>
</Card>
) : (
<Card>
<Box sx={{ display: 'flex', flexWrap: 'wrap', alignItems: "flex-start" }}>
<CardMedia
component="img"
sx={{ width: "250px" }}
height="350"
image={API.cardImage(card)}
alt={`${card.gsx$name} card`}
onClick={() => extend("")}
/>
<CardContent sx={{ flex: '1 0', minWidth: "310px", width: "calc(100% - 250px)" }}>
{content}
</CardContent>
</Box>
</Card>
);
};

View File

@ -1,14 +0,0 @@
import { Card } from "../../common/definitions";
export type statsType = "avg" | "min" | "max";
export interface chaoticCardProps<T extends Card> {
card: T
ext: boolean
stats: statsType
hideStats: boolean
}
export interface ChaoticCard<T extends Card> {
(props: chaoticCardProps<T>): JSX.Element
}

View File

@ -15,6 +15,10 @@
height: 24px;
}
.bigger {
font-size: 1.15rem;
}
.name {
-webkit-user-select: all;
-moz-user-select: all;

View File

@ -1,10 +1,11 @@
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 React, { useEffect, useState } from 'react';
import { Attack, Battlegear, Card as ChaoticCard } from '../../common/definitions';
import AttackCard from './Attack';
import BattlegearCard from './Battlegear';
import { chaoticCardProps, statsType } from './CardBase';
import Search from './Search';
import './collection.scss';
@ -42,14 +43,47 @@ const CustomSelect = styled(Select)(() => ({
}
}));
interface storage {
extended?: string
stats?: statsType
hideStats?: string
}
export default function Collection (_props) {
const [p, sp] = useState(1);
const [n, sn] = useState(10);
const [ext, setExt] = useState(false);
const [ext, setExtended] = useState(false);
const [stats, setStats] = useState<statsType>("avg");
const [hideStats, setHideStats] = useState(false);
const [content, setContent] = useState<ChaoticCard[]>([]);
const [info, setInfo] = useState<{text?: string}>({});
const [selected, setSelected] = useState("");
useEffect(() => {
const load = localStorage.getItem("collection");
if (load) {
const { extended, stats, hideStats } = JSON.parse(load) as storage;
if (extended !== undefined) setExtended((/true/i).test(extended));
if (stats !== undefined) {
if (stats == "min") setStats("min");
if (stats == "max") setStats("max");
}
if (hideStats !== undefined) setHideStats(hideStats !== "false");
}
}, []);
const saveSettings = (setting: Partial<storage>) => {
const load = localStorage.getItem("collection");
let save: storage = {};
if (load) {
const rest = JSON.parse(load) as storage;
save = { ...rest, ...setting };
} else {
save = setting;
}
localStorage.setItem("collection", JSON.stringify(save));
};
const handlePerPage = (event: SelectChangeEvent<number>) => {
sn(event.target.value as number);
@ -59,17 +93,29 @@ export default function Collection (_props) {
sp(value);
};
const hanldeStats = (event: SelectChangeEvent<string>) => {
setStats(event.target.value as statsType);
const handleExt = (event: React.ChangeEvent<HTMLInputElement>) => {
setExtended(event.target.checked);
saveSettings({ extended: event.target.checked.toString() });
};
const handleExt = (event: React.ChangeEvent<HTMLInputElement>) => {
setExt(event.target.checked);
const hanldeStats = (event: SelectChangeEvent<statsType>) => {
setStats(event.target.value as statsType);
saveSettings({ stats: event.target.value as statsType });
};
const handleHideStats = (event: React.ChangeEvent<HTMLInputElement>) => {
setHideStats(event.target.checked);
saveSettings({ hideStats: event.target.checked.toString() });
};
const handleExtendSingle = (name: string) => {
setSelected(name);
};
useEffect(() => {
console.log("refresh list");
setSelected("");
}, [content]);
return (<ThemeProvider theme={theme}>
<Paper square sx={{ minHeight: "100vh", height: "100%", paddingLeft: theme.spacing(1), paddingRight: theme.spacing(1) }}>
@ -147,7 +193,8 @@ export default function Collection (_props) {
) : (
<CardList
cards={content.slice(n * (p-1), n * p)}
{...({ ext, stats, hideStats })}
extend={handleExtendSingle}
{...({ selected, ext, stats, hideStats })}
/>
)}
</Paper>
@ -156,15 +203,25 @@ export default function Collection (_props) {
type listProps = Omit<chaoticCardProps<ChaoticCard>, "card"> & {
cards: ChaoticCard[]
selected: string
}
const CardList = ({ cards, ...props }: listProps) => {
const CardList = ({ cards, selected, ext, ...props }: listProps) => {
const list = cards.map((card, i) => {
switch (card.gsx$type) {
case "Attacks":
return (<Attack card={card as AttackCard} key={card.gsx$name+card.gsx$set} {...props}/>);
// case "Battlegear":
// return (<Battlegear card={card} key={i} {...props}/>);
return (<AttackCard key={card.gsx$name+card.gsx$set}
card={card as Attack}
ext={(card.gsx$name === selected || ext)}
{...props}
/>);
case "Battlegear":
return (<BattlegearCard key={card.gsx$name+card.gsx$set}
card={card as Battlegear}
ext={(card.gsx$name === selected || ext)}
{...props}
/>);
// case "Creatures":
// return (<Creature card={card} key={i} {...props}/>);
// case "Locations":