Skip to content

Commit

Permalink
Merge pull request #201 from daithihearn/go-migration
Browse files Browse the repository at this point in the history
Go migration
  • Loading branch information
daithihearn authored Jan 28, 2024
2 parents 1a82899 + fa1c33c commit 4405a59
Show file tree
Hide file tree
Showing 71 changed files with 2,220 additions and 1,583 deletions.
209 changes: 0 additions & 209 deletions junit.xml

This file was deleted.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "frontend",
"version": "7.4.7",
"version": "8.0.0",
"description": "React frontend for the Cards 110",
"author": "Daithi Hearn",
"license": "MIT",
Expand All @@ -18,6 +18,7 @@
"@mui/x-data-grid": "6.18.7",
"@popperjs/core": "2.11.8",
"@reduxjs/toolkit": "2.0.1",
"@tanstack/react-query": "^5.17.19",
"@types/jest": "29.5.11",
"@types/node": "20.10.8",
"@types/react": "18.2.47",
Expand Down Expand Up @@ -54,6 +55,7 @@
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@tanstack/eslint-plugin-query": "^5.17.20",
"@types/crypto-js": "4.2.1",
"@types/enzyme": "3.10.18",
"@types/enzyme-adapter-react-16": "1.0.9",
Expand Down
2 changes: 1 addition & 1 deletion public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"short_name": "Cards 110",
"name": "Cards 110",
"version": "7.4.7",
"version": "8.0.0",
"icons": [
{
"src": "./assets/favicon.png",
Expand Down
33 changes: 19 additions & 14 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
ThemeProvider,
useMediaQuery,
} from "@mui/material"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"

const AUTHO_DOMAIN = process.env.REACT_APP_AUTH0_DOMAIN as string
const AUTH0_CLIENT_ID = process.env.REACT_APP_AUTH0_CLIENT_ID as string
Expand All @@ -55,6 +56,8 @@ const router = createBrowserRouter(
const App = () => {
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)")

const queryClient = new QueryClient()

const theme = React.useMemo(
() =>
createTheme({
Expand All @@ -64,20 +67,22 @@ const App = () => {
)

return (
<ThemeProvider theme={theme}>
<Provider store={store}>
<SnackbarProvider maxSnack={3}>
<Auth0Provider
domain={AUTHO_DOMAIN}
clientId={AUTH0_CLIENT_ID}
useRefreshTokens={true}>
<CssBaseline />
<MyProfileSync />
<RouterProvider router={router} />
</Auth0Provider>
</SnackbarProvider>
</Provider>
</ThemeProvider>
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
<Provider store={store}>
<SnackbarProvider maxSnack={3}>
<Auth0Provider
domain={AUTHO_DOMAIN}
clientId={AUTH0_CLIENT_ID}
useRefreshTokens={true}>
<CssBaseline />
<MyProfileSync />
<RouterProvider router={router} />
</Auth0Provider>
</SnackbarProvider>
</Provider>
</ThemeProvider>
</QueryClientProvider>
)
}
export default App
49 changes: 49 additions & 0 deletions src/auth/accessToken.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { useAuth0 } from "@auth0/auth0-react"
import { useEffect, useMemo, useState } from "react"
import jwt_decode from "jwt-decode"

const AUTH0_AUDIENCE = process.env.REACT_APP_AUTH0_AUDIENCE as string
const AUTH0_SCOPE = process.env.REACT_APP_AUTH0_SCOPE as string

interface JWTToken {
permissions: string[]
}

const useAccessToken = () => {
const [accessToken, setAccessToken] = useState<string | undefined>()
const { user, isAuthenticated, getAccessTokenSilently } = useAuth0()

useEffect(() => {
if (isAuthenticated && user) {
getAccessTokenSilently({
authorizationParams: {
audience: AUTH0_AUDIENCE,
redirect_uri: window.location.origin,
scope: AUTH0_SCOPE,
},
}).then(token => {
setAccessToken(token)
})
}
}, [user, isAuthenticated, getAccessTokenSilently])

const isPlayer = useMemo(() => {
if (!accessToken) {
return false
}
const decodedAccessToken = jwt_decode<JWTToken>(accessToken)
return decodedAccessToken.permissions.indexOf("read:game") !== -1
}, [accessToken])

const isAdmin = useMemo(() => {
if (!accessToken) {
return false
}
const decodedAccessToken = jwt_decode<JWTToken>(accessToken)
return decodedAccessToken.permissions.indexOf("write:admin") !== -1
}, [accessToken])

return { isPlayer, isAdmin, accessToken: accessToken }
}

export default useAccessToken
91 changes: 73 additions & 18 deletions src/caches/GameSlice.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,91 @@
import { createSelector, createSlice, PayloadAction } from "@reduxjs/toolkit"

import { GameState, GameStatus, PlayedCard } from "model/Game"
import { Player } from "model/Player"
import { GameState, GameStateResponse, GameStatus } from "model/Game"
import { RoundStatus } from "model/Round"
import { RootState } from "./caches"
import { processOrderedCardsAfterGameUpdate } from "utils/GameUtils"
import { Card, EMPTY } from "model/Cards"
import { determineEvent } from "utils/EventUtils"

const initialState: GameState = {
export const initialGameState: GameState = {
revision: -1,
iamSpectator: true,
isMyGo: false,
iamGoer: false,
iamDealer: false,
iamAdmin: false,
cards: [],
cardsFull: [],
status: GameStatus.NONE,
players: [],
}

export const gameSlice = createSlice({
name: "game",
initialState: initialState,
initialState: initialGameState,
reducers: {
updateGame: (_, action: PayloadAction<GameState>) => action.payload,
updatePlayers: (state, action: PayloadAction<Player[]>) => {
state.players = action.payload
updateGame: (state, action: PayloadAction<GameStateResponse>) => {
const updatedGame: GameState = {
...action.payload,
cardsFull: processOrderedCardsAfterGameUpdate(
state.cardsFull,
action.payload.cards,
),
}

const event = determineEvent(state, updatedGame)

console.log("event", event)

return updatedGame
},
selectCard: (state, action: PayloadAction<Card>) => {
state.cardsFull.forEach(c => {
if (c.name === action.payload.name) c.selected = true
})
},
selectCards: (state, action: PayloadAction<Card[]>) => {
state.cardsFull.forEach(c => {
if (action.payload.some(a => a.name === c.name))
c.selected = true
})
},
updatePlayedCards: (state, action: PayloadAction<PlayedCard[]>) => {
if (state.round)
state.round.currentHand.playedCards = action.payload
toggleSelect: (state, action: PayloadAction<Card>) =>
state.cardsFull.forEach(c => {
if (c.name === action.payload.name) c.selected = !c.selected
}),
toggleUniqueSelect: (state, action: PayloadAction<Card>) =>
state.cardsFull.forEach(c => {
if (c.name === action.payload.name) c.selected = !c.selected
else c.selected = false
}),
selectAll: state => {
state.cardsFull.forEach(c => {
if (c.name !== EMPTY.name) c.selected = true
})
},
disableActions: state => {
state.isMyGo = false
clearSelectedCards: state => {
state.cardsFull.forEach(c => {
c.selected = false
})
},
resetGame: () => initialState,
replaceMyCards: (state, action: PayloadAction<Card[]>) => {
state.cardsFull = action.payload
},
resetGame: () => initialGameState,
},
})

export const {
updateGame,
disableActions,
updatePlayedCards,
updatePlayers,
resetGame,
toggleSelect,
toggleUniqueSelect,
selectCard,
selectCards,
selectAll,
clearSelectedCards,
replaceMyCards,
} = gameSlice.actions

export const getGame = (state: RootState) => state.game
Expand All @@ -53,6 +98,14 @@ export const getMe = createSelector(getGame, game => game.me)

export const getRound = createSelector(getGame, game => game.round)
export const getCards = createSelector(getGame, game => game.cards)
export const getCardsFull = createSelector(getGame, game => game.cardsFull)
export const getCardsWithoutBlanks = createSelector(getCardsFull, cards =>
cards.filter(c => c.name !== EMPTY.name),
)
export const getSelectedCards = createSelector(getCardsFull, cards =>
cards.filter(c => c.selected),
)

export const getSuit = createSelector(getRound, round => round?.suit)
export const getGameId = createSelector(getGame, game => game.id)

Expand All @@ -67,9 +120,9 @@ export const getIsGameActive = createSelector(
status => status === GameStatus.ACTIVE,
)

export const getIsGameFinished = createSelector(
export const getIsGameCompleted = createSelector(
getGameStatus,
status => status === GameStatus.FINISHED,
status => status === GameStatus.COMPLETED,
)

export const getRoundStatus = createSelector(getRound, round => round?.status)
Expand Down Expand Up @@ -124,3 +177,5 @@ export const getIsInBunker = createSelector(
(isMyGo, isRoundCalling, me) =>
isMyGo && isRoundCalling && me && me?.score < -30,
)

export const getRevision = createSelector(getGame, game => game.revision)
90 changes: 0 additions & 90 deletions src/caches/MyCardsSlice.ts

This file was deleted.

Loading

0 comments on commit 4405a59

Please sign in to comment.