import { Constants } from '@/constants/Constants' import { useAuth } from '@/hooks/useAuth' import { useChallengeActions, useDownloadChallengeActions } from '@/hooks/useChallengeActions' import { useDownloadChallenges } from '@/hooks/useChallenges' import { useGame, useUpdateActiveChallengeId, useUpdateGameState, useUpdateMoney, useUpdatePenalty } from '@/hooks/useGame' import { useDownloadMoneyUpdates } from '@/hooks/useMoneyUpdates' import { useDownloadTrains } from '@/hooks/useTrain' import { isAuthValid } from '@/utils/features/auth/authSlice' import { ChallengeAction, ChallengeActionPayload } from '@/utils/features/challengeActions/challengeActionsSlice' import { Challenge } from '@/utils/features/challenges/challengesSlice' import { useQuery } from '@tanstack/react-query' import { router } from 'expo-router' import { useShareIntentContext } from 'expo-share-intent' import React, { ReactNode, useEffect } from 'react' export default function GameProvider({ children }: { children: ReactNode }) { const auth = useAuth() const game = useGame() const challengeActions = useChallengeActions() const updateGameState = useUpdateGameState() const updatePenalty = useUpdatePenalty() const updateMoney = useUpdateMoney() const updateActiveChallengeId = useUpdateActiveChallengeId() const downloadTrains = useDownloadTrains() const downloadChallenges = useDownloadChallenges() const downloadChallengeActions = useDownloadChallengeActions() const downloadMoneyUpdates = useDownloadMoneyUpdates() const gameQuery = useQuery({ queryKey: ['get-game', auth.token], queryFn: () => fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/game/`, { headers: { "Authorization": `Bearer ${auth.token}` }} ).then(resp => resp.json()), enabled: isAuthValid(auth), refetchInterval: Constants.QUERY_REFETCH_INTERVAL * 1000, }) useEffect(() => { if (gameQuery.isSuccess && gameQuery.data) updateGameState(gameQuery.data) }, [gameQuery.status, gameQuery.dataUpdatedAt]) const playerQuery = useQuery({ queryKey: ['get-player', game.playerId, auth.token], queryFn: () => fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/players/${game.playerId}/`, { headers: { "Authorization": `Bearer ${auth.token}` }} ).then(resp => resp.json()), enabled: isAuthValid(auth) && !!game.playerId, refetchInterval: Constants.QUERY_REFETCH_INTERVAL * 1000, }) useEffect(() => { if (playerQuery.isSuccess && playerQuery.data) { updateMoney(playerQuery.data.money) updateActiveChallengeId(playerQuery.data.activeChallengeId) } }, [playerQuery.status, playerQuery.dataUpdatedAt]) const trainsQuery = useQuery({ queryKey: ['get-trains', game.playerId, auth.token], queryFn: () => fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/trains/?playerId=${game.playerId}&size=10000`, { headers: { "Authorization": `Bearer ${auth.token}` }} ).then(resp => resp.json()), enabled: isAuthValid(auth) && !!game.playerId, initialData: { data: [], meta: { currentPage: 0, lastPage: 0, nextPage: 0, prevPage: 0, total: 0, totalPerPage: 0 } }, refetchInterval: Constants.QUERY_REFETCH_INTERVAL * 1000, }) useEffect(() => { if (trainsQuery.isSuccess && trainsQuery.data) downloadTrains(trainsQuery.data) }, [trainsQuery.status, trainsQuery.dataUpdatedAt]) const challengesQuery = useQuery({ queryKey: ['get-challenges', auth.token], queryFn: () => fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/challenges/?size=10000`, { headers: { "Authorization": `Bearer ${auth.token}` }} ).then(resp => resp.json()), enabled: isAuthValid(auth), initialData: { data: [], meta: { currentPage: 0, lastPage: 0, nextPage: 0, prevPage: 0, total: 0, totalPerPage: 0 } }, refetchInterval: Constants.QUERY_REFETCH_INTERVAL * 1000, }) useEffect(() => { if (challengesQuery.isSuccess && challengesQuery.data) { downloadChallenges(challengesQuery.data) const dataWithPlayerActions = challengesQuery.data.data.filter( (challenge: (Challenge & {action: ChallengeActionPayload | null})) => challenge.action !== null && challenge.action.playerId === game.playerId) downloadChallengeActions({ data: dataWithPlayerActions }) } }, [challengesQuery.status, challengesQuery.dataUpdatedAt]) const moneyUpdatesQuery = useQuery({ queryKey: ['get-money-updates', game.playerId, auth.token], queryFn: () => fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/money-updates/?playerId=${game.playerId}&size=10000`, { headers: { "Authorization": `Bearer ${auth.token}` }} ).then(resp => resp.json()), enabled: isAuthValid(auth) && !!game.playerId, refetchInterval: Constants.QUERY_REFETCH_INTERVAL * 1000, }) useEffect(() => { if (moneyUpdatesQuery.isSuccess && moneyUpdatesQuery.data) downloadMoneyUpdates(moneyUpdatesQuery.data) }, [moneyUpdatesQuery.status, moneyUpdatesQuery.dataUpdatedAt]) useEffect(() => { const now = new Date().getTime() const activeChallenge: ChallengeAction | undefined = challengeActions .find(challengeAction => challengeAction.penaltyStart && challengeAction.penaltyEnd && challengeAction.penaltyStart <= now && now <= challengeAction.penaltyEnd) if (!activeChallenge || !game.currentRunner || game.runId !== activeChallenge.runId) updatePenalty({ penaltyStart: null, penaltyEnd: null }) else if (activeChallenge && (activeChallenge.penaltyStart !== game.penaltyStart || activeChallenge.penaltyEnd)) { updatePenalty({ penaltyStart: activeChallenge.penaltyStart, penaltyEnd: activeChallenge.penaltyEnd }) } }, [game.currentRunner, challengeActions]) const { hasShareIntent, shareIntent, resetShareIntent } = useShareIntentContext() useEffect(() => { if (hasShareIntent) { if (!shareIntent.text || !shareIntent.text.includes("eurailapp.com/share")) return resetShareIntent() router.replace('/train') } }, [hasShareIntent]) return <> {children} }