Skip to content

Commit f5dc0f9

Browse files
committed
Re ordering components on game page
1 parent 3e397b6 commit f5dc0f9

File tree

12 files changed

+430
-389
lines changed

12 files changed

+430
-389
lines changed

src/caches/GameSlice.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,10 @@ export const getIsDoublesGame = createSelector(
9090
players => players.length === 6,
9191
)
9292

93+
export const getMaxCall = createSelector(getGame, game => game.maxCall || 0)
9394
export const getIsMyGo = createSelector(getGame, game => game.isMyGo)
9495
export const getIamGoer = createSelector(getGame, game => game.iamGoer)
96+
export const getIamDealer = createSelector(getGame, game => game.iamDealer)
9597
export const getIHavePlayed = createSelector(getGame, game => {
9698
const myPosition = game.players.findIndex(p => p.id === game.me?.id)
9799
const currentPlayerPosition = game.players.findIndex(
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { ButtonGroup, CardBody } from "reactstrap"
2+
import {
3+
getIsRoundBuying,
4+
getIsRoundCalled,
5+
getIsRoundCalling,
6+
getIsRoundPlaying,
7+
} from "../../../caches/GameSlice"
8+
import { useAppSelector } from "../../../caches/hooks"
9+
import Buying from "./Buying"
10+
import Calling from "./Calling"
11+
import PlayCard from "./PlayCard"
12+
import SelectSuit from "./SelectSuit"
13+
14+
const ActionsWrapper = () => {
15+
const isBuying = useAppSelector(getIsRoundBuying)
16+
const isCalling = useAppSelector(getIsRoundCalling)
17+
const isPlaying = useAppSelector(getIsRoundPlaying)
18+
const isCalled = useAppSelector(getIsRoundCalled)
19+
20+
return (
21+
<CardBody className="buttonArea">
22+
<ButtonGroup size="lg">
23+
{isCalling && <Calling />}
24+
{isBuying && <Buying />}
25+
{isCalled && <SelectSuit />}
26+
{isPlaying && <PlayCard />}
27+
</ButtonGroup>
28+
</CardBody>
29+
)
30+
}
31+
32+
export default ActionsWrapper

src/components/Game/Buying.tsx renamed to src/components/Game/Actions/Buying.tsx

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,32 @@
1-
import { Button, ButtonGroup, CardBody } from "reactstrap"
1+
import { Button } from "reactstrap"
22

33
import { useCallback, useEffect, useState } from "react"
44

5-
import GameService from "../../services/GameService"
6-
import { useAppDispatch, useAppSelector } from "../../caches/hooks"
5+
import GameService from "../../..//services/GameService"
6+
import { useAppDispatch, useAppSelector } from "../../..//caches/hooks"
77
import { useSnackbar } from "notistack"
88
import {
99
getMyCardsWithoutBlanks,
1010
getSelectedCards,
1111
selectAll,
12-
} from "../../caches/MyCardsSlice"
12+
} from "../../..//caches/MyCardsSlice"
1313
import {
1414
getGameId,
1515
getIamGoer,
1616
getIHavePlayed,
1717
getIsMyGo,
1818
getSuit,
19-
} from "../../caches/GameSlice"
20-
import { riskOfMistakeBuyingCards } from "../../utils/GameUtils"
19+
} from "../../..//caches/GameSlice"
20+
import { riskOfMistakeBuyingCards } from "../../../utils/GameUtils"
2121
import ThrowCardsWarningModal from "./ThrowCardsWarningModal"
22-
import { SelectableCard } from "../../model/Cards"
23-
import parseError from "../../utils/ErrorUtils"
22+
import { SelectableCard } from "../../../model/Cards"
23+
import parseError from "../../../utils/ErrorUtils"
24+
25+
const WaitingForRoundToStart = () => (
26+
<Button disabled type="button" color="info">
27+
<b>Waiting for round to start...</b>
28+
</Button>
29+
)
2430

2531
const Buying = () => {
2632
const dispatch = useAppDispatch()
@@ -69,32 +75,27 @@ const Buying = () => {
6975
}
7076
}, [gameId, suit, selectedCards, myCards, isMyGo, readyToBuy])
7177

78+
if (iHavePlayed) return <WaitingForRoundToStart />
7279
return (
73-
<div>
74-
<CardBody className="buttonArea">
75-
<ButtonGroup size="lg">
76-
{!iHavePlayed ? (
77-
<Button
78-
type="button"
79-
onClick={toggleReadyToBuy}
80-
color={isMyGo || !readyToBuy ? "primary" : "info"}>
81-
<b>
82-
{isMyGo || !readyToBuy
83-
? "Keep Cards"
84-
: "Waiting to buy cards..."}
85-
</b>
86-
</Button>
87-
) : null}
88-
</ButtonGroup>
80+
<>
81+
<Button
82+
type="button"
83+
onClick={toggleReadyToBuy}
84+
color={isMyGo || !readyToBuy ? "primary" : "info"}>
85+
<b>
86+
{isMyGo || !readyToBuy
87+
? "Keep Cards"
88+
: "Waiting to buy cards..."}
89+
</b>
90+
</Button>
8991

90-
<ThrowCardsWarningModal
91-
modalVisible={deleteCardsDialog}
92-
cancelCallback={hideCancelDeleteCardsDialog}
93-
continueCallback={buyCards}
94-
suit={suit!}
95-
/>
96-
</CardBody>
97-
</div>
92+
<ThrowCardsWarningModal
93+
modalVisible={deleteCardsDialog}
94+
cancelCallback={hideCancelDeleteCardsDialog}
95+
continueCallback={buyCards}
96+
suit={suit!}
97+
/>
98+
</>
9899
)
99100
}
100101

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import { Button } from "reactstrap"
2+
3+
import GameService from "../../../services/GameService"
4+
import { useAppDispatch, useAppSelector } from "../../../caches/hooks"
5+
import {
6+
getCards,
7+
getGameId,
8+
getGamePlayers,
9+
getIamDealer,
10+
getIsMyGo,
11+
getMaxCall,
12+
getRound,
13+
} from "../../../caches/GameSlice"
14+
import { useCallback, useMemo } from "react"
15+
import { useSnackbar } from "notistack"
16+
import parseError from "../../../utils/ErrorUtils"
17+
18+
const Calling = () => {
19+
const dispatch = useAppDispatch()
20+
const { enqueueSnackbar } = useSnackbar()
21+
const gameId = useAppSelector(getGameId)
22+
const cards = useAppSelector(getCards)
23+
const round = useAppSelector(getRound)
24+
const players = useAppSelector(getGamePlayers)
25+
const isMyGo = useAppSelector(getIsMyGo)
26+
const iamDealer = useAppSelector(getIamDealer)
27+
const maxCall = useAppSelector(getMaxCall)
28+
29+
const call = useCallback(
30+
(callAmount: number) => {
31+
if (gameId)
32+
dispatch(GameService.call(gameId, callAmount)).catch(
33+
(e: Error) =>
34+
enqueueSnackbar(parseError(e), { variant: "error" }),
35+
)
36+
},
37+
[gameId],
38+
)
39+
40+
const buttonsEnabled = useMemo(
41+
() => round && round.currentHand && cards.length > 0 && isMyGo,
42+
[round, cards, isMyGo],
43+
)
44+
45+
const canCall10 = useMemo(
46+
() =>
47+
players.length === 6 &&
48+
((iamDealer && maxCall <= 10) || maxCall < 10),
49+
[players, iamDealer, maxCall],
50+
)
51+
52+
const canCall15 = useMemo(
53+
() => (iamDealer && maxCall <= 15) || maxCall < 15,
54+
[iamDealer, maxCall],
55+
)
56+
57+
const canCall20 = useMemo(
58+
() => (iamDealer && maxCall <= 20) || maxCall < 20,
59+
[iamDealer, maxCall],
60+
)
61+
62+
const canCall25 = useMemo(
63+
() => (iamDealer && maxCall <= 25) || maxCall < 25,
64+
[iamDealer, maxCall],
65+
)
66+
67+
const canCallJink = useMemo(() => players.length > 2, [players])
68+
69+
return (
70+
<>
71+
<Button
72+
disabled={!buttonsEnabled}
73+
type="button"
74+
color="secondary"
75+
onClick={() => call(0)}>
76+
Pass
77+
</Button>
78+
{canCall10 ? (
79+
<Button
80+
disabled={!buttonsEnabled}
81+
type="button"
82+
color="primary"
83+
onClick={() => call(10)}>
84+
10
85+
</Button>
86+
) : null}
87+
{canCall15 ? (
88+
<Button
89+
disabled={!buttonsEnabled}
90+
type="button"
91+
color="warning"
92+
onClick={() => call(15)}>
93+
15
94+
</Button>
95+
) : null}
96+
{canCall20 ? (
97+
<Button
98+
disabled={!buttonsEnabled}
99+
type="button"
100+
color="warning"
101+
onClick={() => call(20)}>
102+
20
103+
</Button>
104+
) : null}
105+
{canCall25 ? (
106+
<Button
107+
disabled={!buttonsEnabled}
108+
type="button"
109+
color="warning"
110+
onClick={() => call(25)}>
111+
25
112+
</Button>
113+
) : null}
114+
<Button
115+
disabled={!buttonsEnabled}
116+
type="button"
117+
color="danger"
118+
onClick={() => call(30)}>
119+
{canCallJink ? "Jink" : "30"}
120+
</Button>
121+
</>
122+
)
123+
}
124+
125+
export default Calling
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { Button } from "reactstrap"
2+
3+
import { useCallback, useMemo } from "react"
4+
5+
import GameService from "../../../services/GameService"
6+
import { useAppDispatch, useAppSelector } from "../../../caches/hooks"
7+
import { useSnackbar } from "notistack"
8+
import {
9+
getMyCardsWithoutBlanks,
10+
getSelectedCards,
11+
} from "../../../caches/MyCardsSlice"
12+
import { getGameId, getIsMyGo, getRound } from "../../../caches/GameSlice"
13+
import { BLANK_CARD } from "../../../model/Cards"
14+
import parseError from "../../../utils/ErrorUtils"
15+
import { RoundStatus } from "../../../model/Round"
16+
17+
const WaitingForYourGo = () => (
18+
<Button disabled type="button" color="info">
19+
<b>Waiting for your go...</b>
20+
</Button>
21+
)
22+
23+
const PlayCard = () => {
24+
const dispatch = useAppDispatch()
25+
const round = useAppSelector(getRound)
26+
const { enqueueSnackbar } = useSnackbar()
27+
const gameId = useAppSelector(getGameId)
28+
const myCards = useAppSelector(getMyCardsWithoutBlanks)
29+
const isMyGo = useAppSelector(getIsMyGo)
30+
const selectedCards = useAppSelector(getSelectedCards)
31+
32+
const playButtonEnabled = useMemo(
33+
() =>
34+
isMyGo &&
35+
round &&
36+
round.status === RoundStatus.PLAYING &&
37+
round.completedHands.length +
38+
myCards.filter(c => c.name !== BLANK_CARD.name).length ===
39+
5,
40+
41+
[isMyGo, round, myCards],
42+
)
43+
44+
const playCard = useCallback(() => {
45+
if (selectedCards.length !== 1) {
46+
enqueueSnackbar("Please select exactly one card to play", {
47+
variant: "warning",
48+
})
49+
} else {
50+
dispatch(
51+
GameService.playCard(gameId!, selectedCards[0].name),
52+
).catch(e => enqueueSnackbar(parseError(e), { variant: "error" }))
53+
}
54+
}, [gameId, selectedCards])
55+
56+
if (!playButtonEnabled) return <WaitingForYourGo />
57+
return (
58+
<Button
59+
id="playCardButton"
60+
type="button"
61+
onClick={playCard}
62+
color="primary">
63+
<b>Play Card</b>
64+
</Button>
65+
)
66+
}
67+
68+
export default PlayCard

0 commit comments

Comments
 (0)