Skip to content

Commit 25b0856

Browse files
committed
feat: Highlight winner cards
Fixes #18
1 parent 483aebe commit 25b0856

File tree

5 files changed

+81
-11
lines changed

5 files changed

+81
-11
lines changed

src/components/Card/Card.module.scss

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,18 @@
2020
justify-content: center;
2121
container-type: inline-size;
2222
}
23+
24+
.CardHighlight {
25+
// border: 5px solid white;
26+
-webkit-animation: glow 1s ease-in-out infinite alternate;
27+
-moz-animation: glow 1s ease-in-out infinite alternate;
28+
animation: glow 1s ease-in-out infinite alternate;
29+
}
30+
31+
.CardDim {
32+
opacity: 0.7;
33+
}
34+
2335
.CardContent {
2436
text-align: center;
2537
overflow-wrap: break-word;
@@ -40,3 +52,14 @@
4052
transform: translateX(0);
4153
}
4254
}
55+
56+
@keyframes glow {
57+
from {
58+
box-shadow: 0 0 2px #fff, 0 0 4px #fff, 0 0 6px #84b893, 0 0 8px #84b893, 0 0 10px #84b893, 0 0 12px #84b893,
59+
0 0 14px #84b893;
60+
}
61+
to {
62+
box-shadow: 0 0 2px #fff, 0 0 4px #fff, 0 0 6px #1e5e31, 0 0 8px #1e5e31, 0 0 10px #1e5e31, 0 0 12px #1e5e31,
63+
0 0 14px #1e5e31;
64+
}
65+
}

src/components/Card/Card.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ import {
66

77
import styles from "./Card.module.scss";
88

9-
export interface CardProps extends CardObject {}
9+
export type CardEffect = "highlight" | "dim" | "none";
10+
export interface CardProps extends CardObject {
11+
effect: CardEffect;
12+
}
1013

11-
function Card({ rank, suit, facing }: CardProps) {
14+
function Card({ rank, suit, facing, effect }: CardProps) {
1215
const suitData = CardSuitMetadataMap[suit];
1316
const rankData = CardRankMetadataMap[rank];
1417

@@ -20,9 +23,15 @@ function Card({ rank, suit, facing }: CardProps) {
2023
content = ["?"];
2124
}
2225

26+
const cardClasses = [
27+
styles.Card,
28+
effect === "dim" && styles.CardDim,
29+
effect === "highlight" && styles.CardHighlight,
30+
].join(" ");
31+
2332
return (
2433
<div className={styles.CardWrapper}>
25-
<div className={styles.Card} style={{ backgroundColor: color }}>
34+
<div className={cardClasses} style={{ backgroundColor: color }}>
2635
<div className={styles.CardContent}>{content}</div>
2736
</div>
2837
</div>

src/components/CardRow/CardRow.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,35 @@ import { CardObject } from "../Card";
44

55
import styles from "./CardRow.module.scss";
66
import React from "react";
7+
import { CardEffect } from "../Card/Card";
78

89
export interface CardRowProps {
910
cardOwner: Participant;
1011
cards: CardObject[];
12+
effect: CardEffect;
1113
children?: React.ReactNode;
1214
}
1315

14-
const CardRow = (props: CardRowProps) => {
16+
const CardRow = ({ cardOwner, cards, effect, children }: CardRowProps) => {
1517
return (
1618
<div className={styles.CardRow}>
1719
<div className={styles.CardOwner}>
18-
<span>{props.cardOwner} Cards</span>
20+
<span>{cardOwner} Cards</span>
1921
{/*
2022
Pretty hacky, but the settings icon is passed
2123
into this row as a child element
2224
*/}
23-
{props.children}
25+
{children}
2426
</div>
2527
<div className={styles.Cards}>
26-
{props.cards.map(({ facing, rank, suit }, i) => (
27-
<Card facing={facing} rank={rank} suit={suit} key={i}></Card>
28+
{cards.map(({ facing, rank, suit }, i) => (
29+
<Card
30+
facing={facing}
31+
rank={rank}
32+
suit={suit}
33+
key={i}
34+
effect={effect}
35+
/>
2836
))}
2937
</div>
3038
</div>

src/components/Table/Table.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import { useState } from "react";
22
import CardRow from "../CardRow";
33
import InfoHud from "../InfoHud";
44
import YesNoPopUp from "../YesNoPopUp";
5-
import { useGame } from ".";
5+
import { Participant, useGame } from ".";
66
import { ScoreBoardRow } from "../ScoreBoard";
77
import { useGameSettingsStore } from "../../stores/gameSettingsStore";
88

99
import styles from "./Table.module.scss";
1010
import SettingsButton from "../SettingsButton";
11+
import { CardEffect } from "../Card/Card";
1112

1213
const Table = ({ hide = false }: { hide?: boolean }) => {
1314
const game = useGame();
@@ -93,14 +94,27 @@ const Table = ({ hide = false }: { hide?: boolean }) => {
9394
];
9495
}
9596

97+
function getCardEffect(cardOwner: Participant): CardEffect {
98+
if (game.winner === "none") return "none";
99+
return cardOwner === game.winner ? "highlight" : "dim";
100+
}
101+
96102
return (
97103
<div className={styles.Table} style={{ display: hide ? "none" : "" }}>
98104
{showHitWarning && getHitWarning()}
99105
{showStickWarning && getStickWarning()}
100-
<CardRow cardOwner={"Dealer"} cards={game.dealer.cards}>
106+
<CardRow
107+
cardOwner={"Dealer"}
108+
cards={game.dealer.cards}
109+
effect={getCardEffect("Dealer")}
110+
>
101111
<SettingsButton />
102112
</CardRow>
103-
<CardRow cardOwner={"Player"} cards={game.player.cards} />
113+
<CardRow
114+
cardOwner={"Player"}
115+
cards={game.player.cards}
116+
effect={getCardEffect("Player")}
117+
/>
104118
<InfoHud
105119
gameState={game.state}
106120
outcome={game.outcome}

src/components/Table/hooks/useGame.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,19 @@ export type GameState =
1313
| "GameOver";
1414

1515
export type Participant = "Player" | "Dealer";
16+
export type Winner = Participant | "none";
17+
export type WinType =
18+
| "opponent-bust"
19+
| "five-card-trick"
20+
| "high-score"
21+
| "most-cards"
22+
| "high-card"
23+
| "draw";
1624

1725
export function useGame() {
1826
const [state, setState] = useState<GameState>("WaitingForStart");
1927
const [outcome, setOutcome] = useState<string | null>(null);
28+
const [winner, setWinner] = useState<Winner>("none");
2029

2130
const deck = useDeck();
2231
const player = useCardPile();
@@ -133,6 +142,7 @@ export function useGame() {
133142
*/
134143
function setup() {
135144
setOutcome(null);
145+
setWinner("none");
136146
deck.init();
137147

138148
player.setCards([]);
@@ -196,6 +206,7 @@ export function useGame() {
196206
function setResult(outcomeText: string, winner?: Participant | null): void {
197207
setState("GameOver");
198208
setOutcome(outcomeText);
209+
setWinner(winner ?? "none");
199210

200211
winner && stats.updateWinnerStats(winner);
201212
}
@@ -223,6 +234,11 @@ export function useGame() {
223234
* Statistics about the games played during this session.
224235
*/
225236
stats,
237+
238+
/**
239+
* The participant who won the round, if any.
240+
*/
241+
winner,
226242
setup,
227243
startDealerRound,
228244
getParticipantScore,

0 commit comments

Comments
 (0)