From 61b0cd51ae47ed057ee50b3e351b3a81b1fee80e Mon Sep 17 00:00:00 2001 From: Emmy D'Anello Date: Wed, 11 Dec 2024 21:33:51 +0100 Subject: [PATCH] =?UTF-8?q?Boutons=20de=20d=C3=A9marrage=20du=20jeu=20fonc?= =?UTF-8?q?tionnels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/app/(tabs)/settings.tsx | 35 ++++++++++++++----- client/app/_layout.tsx | 23 ++++++------ client/components/GameProvider.tsx | 26 ++++++++++++++ client/hooks/mutations/useGameMutation.ts | 18 ++++++---- .../hooks/mutations/useGeolocationMutation.ts | 5 --- client/hooks/useGame.ts | 6 +++- .../challengeActions/challengeActionsSlice.ts | 8 ++--- client/utils/features/game/gameSlice.ts | 32 ++++++++++++++--- client/utils/features/train/trainSlice.ts | 4 +-- 9 files changed, 116 insertions(+), 41 deletions(-) create mode 100644 client/components/GameProvider.tsx diff --git a/client/app/(tabs)/settings.tsx b/client/app/(tabs)/settings.tsx index fd5ba1f..1f49527 100644 --- a/client/app/(tabs)/settings.tsx +++ b/client/app/(tabs)/settings.tsx @@ -1,35 +1,39 @@ import { useGameRepairMutation, useGameResetMutation, useGameStartMutation, useGameStopMutation, useGameSwitchPlayerMutation } from '@/hooks/mutations/useGameMutation' import { useAuth } from '@/hooks/useAuth' -import { useGame } from '@/hooks/useGame' +import { useGame, useUpdateGameState } from '@/hooks/useGame' import { useRouter } from 'expo-router' -import { FAB, List, Surface } from 'react-native-paper' +import { useState } from 'react' +import { Button, Dialog, FAB, List, Portal, Surface, Text } from 'react-native-paper' export default function HistoryScreen() { const router = useRouter() const auth = useAuth() const game = useGame() + const updateGameState = useUpdateGameState() const gameStartMutation = useGameStartMutation({ auth, - game, + updateGameState, }) const gameStopMutation = useGameStopMutation({ auth, - game, + updateGameState, }) const gameSwitchMutation = useGameSwitchPlayerMutation({ auth, - game, + updateGameState, }) const gameRepairMutation = useGameRepairMutation({ auth, - game, + updateGameState, }) const gameResetMutation = useGameResetMutation({ auth, - game, + updateGameState, }) + const [resetConfirmVisible, setResetConfirmVisible] = useState(false) + return ( @@ -74,8 +78,23 @@ export default function HistoryScreen() { title="Réinitialiser les données de jeu" description="Permet de détruire toutes les données. À manipuler avec précaution." right={() => } - onPress={() => gameResetMutation.mutate()} /> + onPress={() => setResetConfirmVisible(true)} /> + + setResetConfirmVisible(false)}> + Confirmer + + + Cette action va réinitialiser TOUTES les données de jeu : l'historique des positions, les défis réalisés et les trains empruntés. + Êtes-vous réellement sûr⋅e de vouloir tout supprimer ? + + + + + + + + ) } diff --git a/client/app/_layout.tsx b/client/app/_layout.tsx index 87d2877..9e6eb09 100644 --- a/client/app/_layout.tsx +++ b/client/app/_layout.tsx @@ -14,6 +14,7 @@ import store from '@/utils/store' import { useStartBackgroundFetchServiceEffect } from '@/utils/background' import LoginProvider from '@/components/LoginProvider' import GeolocationProvider from '@/components/GeolocationProvider' +import GameProvider from '@/components/GameProvider' const queryClient = new QueryClient({ defaultOptions: { @@ -45,16 +46,18 @@ export default function RootLayout() { onSuccess={() => queryClient.resumePausedMutations().then(() => queryClient.invalidateQueries())}> - - - - - - - - - - + + + + + + + + + + + + diff --git a/client/components/GameProvider.tsx b/client/components/GameProvider.tsx new file mode 100644 index 0000000..d64a85e --- /dev/null +++ b/client/components/GameProvider.tsx @@ -0,0 +1,26 @@ +import { useAuth } from '@/hooks/useAuth' +import { useUpdateGameState } from '@/hooks/useGame' +import { useQuery } from '@tanstack/react-query' +import { ReactNode, useEffect } from 'react' + +export default function GameProvider({ children }: { children: ReactNode }) { + const auth = useAuth() + const updateGameState = useUpdateGameState() + const gameQuery = useQuery({ + queryKey: ['update-game'], + queryFn: () => fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/game/`, { + headers: { "Authorization": `Bearer ${auth.token}` }} + ).then(resp => resp.json()), + enabled: auth.loggedIn, + refetchInterval: 5000, + }) + const game = gameQuery.data + useEffect(() => { + if (game) + updateGameState(game) + }, [game]) + + return <> + {children} + +} \ No newline at end of file diff --git a/client/hooks/mutations/useGameMutation.ts b/client/hooks/mutations/useGameMutation.ts index be8fb69..e423f1a 100644 --- a/client/hooks/mutations/useGameMutation.ts +++ b/client/hooks/mutations/useGameMutation.ts @@ -1,5 +1,5 @@ import { AuthState } from "@/utils/features/auth/authSlice" -import { GameState } from "@/utils/features/game/gameSlice" +import { GamePayload, GameState } from "@/utils/features/game/gameSlice" import { useMutation } from "@tanstack/react-query" type ErrorResponse = { @@ -13,13 +13,13 @@ type ErrorFuncProps = { response?: ErrorResponse, error?: Error } type onErrorFunc = (props: ErrorFuncProps) => void type GameProps = { - game: GameState + updateGameState: (payload: GamePayload) => { payload: GamePayload, type: "game/updateGameState" } auth: AuthState onPostSuccess?: onPostSuccessFunc onError?: onErrorFunc } -export const useGameStartMutation = ({ game, auth, onPostSuccess, onError }: GameProps) => { +export const useGameStartMutation = ({ auth, updateGameState, onPostSuccess, onError }: GameProps) => { return useMutation({ mutationFn: async () => { return fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/game/start/`, { @@ -36,6 +36,7 @@ export const useGameStartMutation = ({ game, auth, onPostSuccess, onError }: Gam onError({ response: data }) return } + updateGameState(data) if (onPostSuccess) onPostSuccess() }, @@ -46,7 +47,7 @@ export const useGameStartMutation = ({ game, auth, onPostSuccess, onError }: Gam }) } -export const useGameStopMutation = ({ auth, game, onPostSuccess, onError }: GameProps) => { +export const useGameStopMutation = ({ auth, updateGameState, onPostSuccess, onError }: GameProps) => { return useMutation({ mutationFn: async () => { return fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/game/stop/`, { @@ -63,6 +64,7 @@ export const useGameStopMutation = ({ auth, game, onPostSuccess, onError }: Game onError({ response: data }) return } + updateGameState(data) if (onPostSuccess) onPostSuccess() }, @@ -73,7 +75,7 @@ export const useGameStopMutation = ({ auth, game, onPostSuccess, onError }: Game }) } -export const useGameSwitchPlayerMutation = ({ auth, game, onPostSuccess, onError }: GameProps) => { +export const useGameSwitchPlayerMutation = ({ auth, updateGameState, onPostSuccess, onError }: GameProps) => { return useMutation({ mutationFn: async () => { return fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/game/switch-running-player/`, { @@ -90,6 +92,7 @@ export const useGameSwitchPlayerMutation = ({ auth, game, onPostSuccess, onError onError({ response: data }) return } + updateGameState(data) if (onPostSuccess) onPostSuccess() }, @@ -100,7 +103,7 @@ export const useGameSwitchPlayerMutation = ({ auth, game, onPostSuccess, onError }) } -export const useGameRepairMutation = ({ auth, game, onPostSuccess, onError }: GameProps) => { +export const useGameRepairMutation = ({ auth, onPostSuccess, onError }: GameProps) => { return useMutation({ mutationFn: async () => { return fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/game/repair/`, { @@ -127,7 +130,7 @@ export const useGameRepairMutation = ({ auth, game, onPostSuccess, onError }: Ga }) } -export const useGameResetMutation = ({ auth, game, onPostSuccess, onError }: GameProps) => { +export const useGameResetMutation = ({ auth, updateGameState, onPostSuccess, onError }: GameProps) => { return useMutation({ mutationFn: async () => { return fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/game/reset/`, { @@ -144,6 +147,7 @@ export const useGameResetMutation = ({ auth, game, onPostSuccess, onError }: Gam onError({ response: data }) return } + updateGameState(data) if (onPostSuccess) onPostSuccess() }, diff --git a/client/hooks/mutations/useGeolocationMutation.ts b/client/hooks/mutations/useGeolocationMutation.ts index 33f92ce..b8aa25f 100644 --- a/client/hooks/mutations/useGeolocationMutation.ts +++ b/client/hooks/mutations/useGeolocationMutation.ts @@ -8,11 +8,6 @@ type ErrorResponse = { statusCode: number } -type LoginForm = { - name: string - password: string -} - type onPostSuccessFunc = (data: any, variables: LocationObject, context: unknown) => void type ErrorFuncProps = { response?: ErrorResponse, error?: Error } type onErrorFunc = (props: ErrorFuncProps) => void diff --git a/client/hooks/useGame.ts b/client/hooks/useGame.ts index b7443b9..8b2799f 100644 --- a/client/hooks/useGame.ts +++ b/client/hooks/useGame.ts @@ -1,5 +1,5 @@ import { useAppDispatch, useAppSelector } from "./useStore" -import { setPlayerId, updateMoney } from "@/utils/features/game/gameSlice" +import { GamePayload, setPlayerId, updateGameState, updateMoney } from "@/utils/features/game/gameSlice" export const useGame = () => useAppSelector((state) => state.game) export const useSetPlayerId = () => { @@ -10,3 +10,7 @@ export const useUpdateMoney = () => { const dispatch = useAppDispatch() return (money: number) => dispatch(updateMoney(money)) } +export const useUpdateGameState = () => { + const dispatch = useAppDispatch() + return (game: GamePayload) => dispatch(updateGameState(game)) +} diff --git a/client/utils/features/challengeActions/challengeActionsSlice.ts b/client/utils/features/challengeActions/challengeActionsSlice.ts index 9eed4f7..35fa4c8 100644 --- a/client/utils/features/challengeActions/challengeActionsSlice.ts +++ b/client/utils/features/challengeActions/challengeActionsSlice.ts @@ -7,10 +7,10 @@ export interface ChallengeAction { description: string, reward: number, success: boolean, - start: Date, - end: Date | null, - penaltyStart: Date | null, - penaltyEnd: Date | null, + start: number, // date + end: number | null, // date + penaltyStart: number | null, // date + penaltyEnd: number | null, // date } export interface ActionsState { diff --git a/client/utils/features/game/gameSlice.ts b/client/utils/features/game/gameSlice.ts index 22ee376..f24684d 100644 --- a/client/utils/features/game/gameSlice.ts +++ b/client/utils/features/game/gameSlice.ts @@ -1,13 +1,28 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' +export interface RunPayload { + id: number + gameId: number + runnerId: number + start: string + end: string | null +} + +export interface GamePayload { + id: number + started: boolean + currentRunId: number | null + currentRun: RunPayload | null +} + export interface GameState { playerId: number | null gameStarted: boolean money: number currentRunner: boolean - chaseFreeTime: Date | null - penaltyStart: Date | null - penaltyEnd: Date | null + chaseFreeTime: number | null // date + penaltyStart: number | null // date + penaltyEnd: number | null // date } const initialState: GameState = { @@ -30,9 +45,18 @@ export const gameSlice = createSlice({ updateMoney: (state, action: PayloadAction) => { state.money = action.payload }, + updateGameState: (state, action: PayloadAction) => { + const game: GamePayload = action.payload + state.gameStarted = game.started + state.currentRunner = state.playerId === game.currentRun?.runnerId + if (state.currentRunner) + state.chaseFreeTime = null + else if (game.currentRun) + state.chaseFreeTime = new Date(game.currentRun?.start).getTime() + 45 * 60 * 1000 + } }, }) -export const { setPlayerId, updateMoney } = gameSlice.actions +export const { setPlayerId, updateMoney, updateGameState } = gameSlice.actions export default gameSlice.reducer diff --git a/client/utils/features/train/trainSlice.ts b/client/utils/features/train/trainSlice.ts index 2ff066f..36dc477 100644 --- a/client/utils/features/train/trainSlice.ts +++ b/client/utils/features/train/trainSlice.ts @@ -83,8 +83,8 @@ export interface TrainTrip { distance: number, from: string, to: string, - departureTime: Date, - arrivalTime: Date, + departureTime: number, + arrivalTime: number, } export interface TrainsState {