various ui improvements; card photo, row collapse support
This commit is contained in:
@@ -11,35 +11,38 @@ export default function Card({ data, state, setState }: CardProps) {
|
|||||||
if (!data) return <div className="card"></div>;
|
if (!data) return <div className="card"></div>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card" key={v4()} style={{backgroundImage: `url(${data.image})`}}>
|
<div className="card" key={v4()}>
|
||||||
<p>Counts as: {data.gemValue}</p>
|
<img src={data.image} loading="lazy" />
|
||||||
{ (data.points && data.points > 0) ? <p>{data.points} points</p> : null }
|
<div className="foreground">
|
||||||
<div className="total-card-cost">
|
<p>{data.gemValue.toUpperCase()}</p>
|
||||||
{
|
{ (data.points && data.points > 0) ? <p>{data.points} {data.points === 1 ? 'point' : 'points'}</p> : null }
|
||||||
Object.keys(data.resourceCost).map((key: keyof ResourceCost | string) => {
|
<div className="total-card-cost">
|
||||||
// @ts-ignore
|
{
|
||||||
return (data.resourceCost[key as keyof ResourceCost] > 0) && (
|
Object.keys(data.resourceCost).map((key: keyof ResourceCost | string) => {
|
||||||
<p key={v4()} className={`card-cost-${key}`}>
|
// @ts-ignore
|
||||||
{data.resourceCost[key as keyof ResourceCost]}
|
return (data.resourceCost[key as keyof ResourceCost] > 0) && (
|
||||||
</p>
|
<p key={v4()} className={`card-cost-${key}`}>
|
||||||
)
|
{data.resourceCost[key as keyof ResourceCost]}
|
||||||
})
|
</p>
|
||||||
}
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
{ state.actions.buyCard.active &&
|
||||||
|
<button
|
||||||
|
onClick={() => buyCard(state, setState, data)}
|
||||||
|
disabled={tooExpensive(data, state)}>
|
||||||
|
Buy This Card
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
{ state.actions.reserveCard.active &&
|
||||||
|
<button
|
||||||
|
onClick={() => reserveCard(state, setState, data)}
|
||||||
|
disabled={hasMaxReserved(currentPlayer)}>
|
||||||
|
Reserve This Card
|
||||||
|
</button>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
{ state.actions.buyCard.active &&
|
|
||||||
<button
|
|
||||||
onClick={() => buyCard(state, setState, data)}
|
|
||||||
disabled={tooExpensive(data, state)}>
|
|
||||||
Buy This Card
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
{ state.actions.reserveCard.active &&
|
|
||||||
<button
|
|
||||||
onClick={() => reserveCard(state, setState, data)}
|
|
||||||
disabled={hasMaxReserved(currentPlayer)}>
|
|
||||||
Reserve This Card
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,18 @@
|
|||||||
.card-row {
|
.card-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column nowrap;
|
flex-flow: column nowrap;
|
||||||
margin: 2rem;
|
margin: 1rem;
|
||||||
width: 80vw;
|
width: 80vw;
|
||||||
|
|
||||||
|
.card-row-top-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
> * {
|
||||||
|
margin: 8px 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.card-row-cards-visible {
|
.card-row-cards-visible {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row nowrap;
|
flex-flow: row nowrap;
|
||||||
@@ -15,25 +24,39 @@
|
|||||||
|
|
||||||
.card {
|
.card {
|
||||||
width: 25%;
|
width: 25%;
|
||||||
min-height: 24vh;
|
height: 40vh;
|
||||||
border: 2px solid black;
|
border: 2px solid black;
|
||||||
|
|
||||||
.total-card-cost {
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.foreground {
|
||||||
|
position: relative;
|
||||||
|
top: -100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 6;
|
||||||
|
|
||||||
@include map-gem-values(".card-cost");
|
> * {
|
||||||
|
margin: 1rem;
|
||||||
|
padding: 6px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background-color: rgb(39, 36, 36);
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-card-cost {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
justify-content: center;
|
||||||
|
@include map-gem-values(".card-cost");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> * {
|
|
||||||
margin: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
background-size: cover;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-count {
|
.card-count {
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
import cardTierToKey from '../../util/cardTierToKey';
|
||||||
import { CardRowProps } from '../../util/propTypes';
|
import { CardRowProps } from '../../util/propTypes';
|
||||||
import { CardData } from "../../util/types"
|
import { CardData } from "../../util/types"
|
||||||
import Card from "../Card/Card"
|
import Card from "../Card/Card"
|
||||||
import { v4 } from 'uuid';
|
|
||||||
import cardTierToKey from '../../util/cardTierToKey';
|
|
||||||
import "./CardRow.scss";
|
import "./CardRow.scss";
|
||||||
|
|
||||||
export default function CardRow({tier, state, setState}: CardRowProps) {
|
export default function CardRow({tier, state, setState}: CardRowProps) {
|
||||||
|
const [collapsed, setCollapsed] = useState(true);
|
||||||
const typedTier = cardTierToKey(tier);
|
const typedTier = cardTierToKey(tier);
|
||||||
|
|
||||||
let cards: Array<CardData>
|
let cards: Array<CardData>
|
||||||
@@ -26,8 +28,11 @@ export default function CardRow({tier, state, setState}: CardRowProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`card-row tier-${tier}`}>
|
<div className={`card-row tier-${tier}`}>
|
||||||
<p>Tier: {tier}</p>
|
<div className="card-row-top-bar">
|
||||||
<div className="card-row-cards-visible">
|
<p>Tier: {tier}</p>
|
||||||
|
<button onClick={() => setCollapsed(!collapsed)}>{collapsed ? "Show" : "Hide"}</button>
|
||||||
|
</div>
|
||||||
|
<div className={`card-row-cards-visible ${collapsed && 'hidden'}`}>
|
||||||
<div className="card-count">
|
<div className="card-count">
|
||||||
<p>Remaining: {state.gameboard.deck[typedTier].length}</p>
|
<p>Remaining: {state.gameboard.deck[typedTier].length}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ const { validateChips } = getChipsActions;
|
|||||||
export default function Gameboard({ state, setState }: StateProps) {
|
export default function Gameboard({ state, setState }: StateProps) {
|
||||||
const [view, setView] = useState(<p>Loading...</p>);
|
const [view, setView] = useState(<p>Loading...</p>);
|
||||||
const [endgame, setEndgame] = useState<PlayerData>();
|
const [endgame, setEndgame] = useState<PlayerData>();
|
||||||
|
const [winner, setWinner] = useState<PlayerData>();
|
||||||
|
|
||||||
// callbacks for lifting state
|
// callbacks for lifting state
|
||||||
const liftSelection = useCallback((value: keyof ResourceCost) => {
|
const liftSelection = useCallback((value: keyof ResourceCost) => {
|
||||||
@@ -63,12 +64,12 @@ export default function Gameboard({ state, setState }: StateProps) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (endgame) {
|
if (endgame) {
|
||||||
let winner: PlayerData;
|
let winner: PlayerData;
|
||||||
|
const winnerData = state.players;
|
||||||
const currentPlayer = useCurrentPlayer(state);
|
const currentPlayer = useCurrentPlayer(state);
|
||||||
if (!currentPlayer) return;
|
if (!currentPlayer) return;
|
||||||
|
|
||||||
if (currentPlayer.id <= endgame.id) {
|
if (currentPlayer.id <= endgame.id) {
|
||||||
const winnerData = state.players;
|
winner = winnerData.sort((x,y) => x.points + y.points)[0];
|
||||||
winner = winnerData.sort((x,y) => x.points - y.points)[0];
|
|
||||||
console.log(winner.name + ' wins!');
|
console.log(winner.name + ' wins!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,5 +20,15 @@
|
|||||||
@include map-gem-values(".player-chip");
|
@include map-gem-values(".player-chip");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reserved-card-view {
|
||||||
|
background-color: rgb(232, 224, 200);
|
||||||
|
.reserved-card-cost {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
justify-content: center;
|
||||||
|
@include map-gem-values(".reserve-cost");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,14 +27,21 @@ export default function Player({ player, state, setState }: PlayerProps) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
dynamic && setReservedView(
|
dynamic && setReservedView(
|
||||||
<>
|
<div className="reserved-card-view">
|
||||||
<p>Reserved cards:</p>
|
<p>Reserved cards:</p>
|
||||||
{
|
{
|
||||||
dynamic.reservedCards?.map((data: CardData) => {
|
dynamic.reservedCards?.map((data: CardData) => (
|
||||||
return <Card key={v4()} data={data} state={state} setState={setState} />
|
<div className="reserved-card">
|
||||||
})
|
<p className={`mini-card ${data.gemValue}`} key={v4()}>{data.gemValue} card: {data.points || 0} points</p>
|
||||||
|
<div className="reserved-card-cost">
|
||||||
|
{
|
||||||
|
Object.entries(data.resourceCost).map(([key, value]) => value > 0 && <p className={`reserve-cost-${key}`} key={v4()}>{value}</p>)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
}
|
}
|
||||||
</>
|
</div>
|
||||||
)
|
)
|
||||||
}, [dynamic, setState])
|
}, [dynamic, setState])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user