From 6be1d5d9cc2cb2af812bb47e8e557b0976542d8d Mon Sep 17 00:00:00 2001 From: lenisko <10072920+lenisko@users.noreply.github.com> Date: Wed, 4 Jun 2025 01:05:54 +0200 Subject: [PATCH 1/2] feat: add rsvps to gym popup --- packages/types/lib/scanner.d.ts | 7 +++ server/src/graphql/typeDefs/scanner.graphql | 1 + server/src/models/Gym.js | 4 ++ src/features/gym/GymPopup.jsx | 63 +++++++++++++++++++++ src/services/queries/gym.js | 1 + 5 files changed, 76 insertions(+) diff --git a/packages/types/lib/scanner.d.ts b/packages/types/lib/scanner.d.ts index a8ded4b95..82f145e1d 100644 --- a/packages/types/lib/scanner.d.ts +++ b/packages/types/lib/scanner.d.ts @@ -52,6 +52,12 @@ export interface Defender extends PokemonDisplay { cp_now: number } +export interface Rsvp { + timeslot: number + going_count: number + maybe_count: number +} + export interface Gym { id: string lat: number @@ -67,6 +73,7 @@ export interface Gym { guarding_pokemon_id: number guarding_pokemon_display: PokemonDisplay defenders: Defender[] + rsvps: Rsvp[] available_slots: number team_id: number raid_level: number diff --git a/server/src/graphql/typeDefs/scanner.graphql b/server/src/graphql/typeDefs/scanner.graphql index d2e0e607a..64ac0908b 100644 --- a/server/src/graphql/typeDefs/scanner.graphql +++ b/server/src/graphql/typeDefs/scanner.graphql @@ -24,6 +24,7 @@ type Gym { guarding_pokemon_id: Int guarding_pokemon_display: JSON defenders: JSON + rsvps: JSON available_slots: Int team_id: Int raid_level: Int diff --git a/server/src/models/Gym.js b/server/src/models/Gym.js index 0707ebe3a..7351d682d 100644 --- a/server/src/models/Gym.js +++ b/server/src/models/Gym.js @@ -28,6 +28,7 @@ const gymFields = [ 'guarding_pokemon_id', 'guarding_pokemon_display', 'defenders', + 'rsvps', 'total_cp', 'power_up_points', 'power_up_level', @@ -313,6 +314,9 @@ class Gym extends Model { if (typeof gym.defenders === 'string' && gym.defenders) { newGym.defenders = JSON.parse(gym.defenders) } + if (typeof gym.rsvps === 'string' && gym.rsvps) { + newGym.rsvps = JSON.parse(gym.rsvps) + } } if ( onlyRaids && diff --git a/src/features/gym/GymPopup.jsx b/src/features/gym/GymPopup.jsx index c6010bb26..831376ca5 100644 --- a/src/features/gym/GymPopup.jsx +++ b/src/features/gym/GymPopup.jsx @@ -69,6 +69,26 @@ export function GymPopup({ hasRaid, hasHatched, raidIconUrl, ...gym }) { ) } + const formatTime = (timestamp) => { + const locale = localStorage.getItem('i18nextLng') || 'en' + return new Date(timestamp).toLocaleTimeString(locale, { + hour: '2-digit', + minute: '2-digit', + }) + } + + const now = Date.now() + + const filteredRsvps = + gym.rsvps?.filter((entry) => { + const ets = entry.timeslot + return ( + ets > now && + ets / 1000 > gym.raid_spawn_timestamp && + ets / 1000 < gym.raid_end_timestamp + ) + }) || [] + return ( = ts, ) && } + {filteredRsvps?.length > 0 && ( + + + + RSVP (Going / Maybe) + + + {filteredRsvps.slice(0, 3).map((entry) => ( + +
{formatTime(entry.timeslot)}
+
+ {entry.going_count} / {entry.maybe_count} +
+
+ ))} +
+
+
+ )}
diff --git a/src/services/queries/gym.js b/src/services/queries/gym.js index 34835458a..be0c451df 100644 --- a/src/services/queries/gym.js +++ b/src/services/queries/gym.js @@ -24,6 +24,7 @@ const gym = gql` guarding_pokemon_id guarding_pokemon_display defenders + rsvps total_cp badge power_up_level From b69a5dcb9bad63d85c7999ebcacd68a435e08d6d Mon Sep 17 00:00:00 2001 From: lenisko <10072920+lenisko@users.noreply.github.com> Date: Wed, 4 Jun 2025 17:49:25 +0200 Subject: [PATCH 2/2] fix: filtering logic for rsvps --- src/features/gym/GymPopup.jsx | 63 +++++------------------------------ 1 file changed, 9 insertions(+), 54 deletions(-) diff --git a/src/features/gym/GymPopup.jsx b/src/features/gym/GymPopup.jsx index 831376ca5..2d44bcd72 100644 --- a/src/features/gym/GymPopup.jsx +++ b/src/features/gym/GymPopup.jsx @@ -20,14 +20,13 @@ import { useMemory } from '@store/useMemory' import { useLayoutStore } from '@store/useLayoutStore' import { setDeepStore, useStorage } from '@store/useStorage' import { ErrorBoundary } from '@components/ErrorBoundary' -import { Img, TextWithIcon } from '@components/Img' +import { Img } from '@components/Img' import { Title } from '@components/popups/Title' import { PowerUp } from '@components/popups/PowerUp' import { GenderIcon } from '@components/popups/GenderIcon' import { Navigation } from '@components/popups/Navigation' import { Coords } from '@components/popups/Coords' import { TimeStamp } from '@components/popups/TimeStamps' -import { ExtraInfo } from '@components/popups/ExtraInfo' import { useAnalytics } from '@hooks/useAnalytics' import { getTimeUntil } from '@utils/getTimeUntil' import { formatInterval } from '@utils/formatInterval' @@ -77,16 +76,14 @@ export function GymPopup({ hasRaid, hasHatched, raidIconUrl, ...gym }) { }) } - const now = Date.now() + const nowSec = Math.floor(Date.now() / 1000) + const raidStart = Number(gym.raid_spawn_timestamp ?? 0) + const raidEnd = Number(gym.raid_end_timestamp ?? 0) const filteredRsvps = gym.rsvps?.filter((entry) => { - const ets = entry.timeslot - return ( - ets > now && - ets / 1000 > gym.raid_spawn_timestamp && - ets / 1000 < gym.raid_end_timestamp - ) + const etsSec = entry.timeslot / 1000 + return etsSec >= nowSec && etsSec >= raidStart && etsSec <= raidEnd }) || [] return ( @@ -141,7 +138,7 @@ export function GymPopup({ hasRaid, hasHatched, raidIconUrl, ...gym }) { {Boolean( gym.raid_pokemon_id && gym.raid_battle_timestamp >= ts, ) && } - {filteredRsvps?.length > 0 && ( + {filteredRsvps.length > 0 && ( - RSVP (Going / Maybe) + RSVP {filteredRsvps.slice(0, 3).map((entry) => ( @@ -1010,55 +1007,13 @@ const GymFooter = ({ lat, lon, hasRaid, gym, setShowDefenders }) => { * @param {import('@rm/types').Gym} props * @returns */ -const ExtraGymInfo = ({ - last_modified_timestamp, - lat, - lon, - updated, - total_cp, - guarding_pokemon_id, - guarding_pokemon_display, -}) => { - const { t, i18n } = useTranslation() - const Icons = useMemory((s) => s.Icons) - const gymValidDataLimit = useMemory((s) => s.gymValidDataLimit) +const ExtraGymInfo = ({ last_modified_timestamp, lat, lon, updated }) => { const enableGymPopupCoords = useStorage( (s) => s.userSettings.gyms.enableGymPopupCoords, ) - const numFormatter = new Intl.NumberFormat(i18n.language) - /** @type {Partial} */ - const gpd = guarding_pokemon_display || {} - return ( - {!!guarding_pokemon_id && updated > gymValidDataLimit && ( - - - {gpd.badge === 1 && ( - <> - {t('best_buddy')} -   - - )} - {t(`poke_${guarding_pokemon_id}`)} - - - )} - {!!total_cp && updated > gymValidDataLimit && ( - {numFormatter.format(total_cp)} - )} - last_seen last_modified {enableGymPopupCoords && (