From c41246bb4e7adc7eb3b106d9de1efc9b68768926 Mon Sep 17 00:00:00 2001 From: dan13ram Date: Mon, 12 Jul 2021 21:14:10 +0530 Subject: [PATCH] showing adjacent timezones for players --- .../Filter/AdjascentTimezonePlayers.tsx | 87 +++++++++++++++++++ .../Player/Filter/DesktopFilters.tsx | 3 +- .../Player/Filter/MobileFilters.tsx | 4 +- packages/web/lib/hooks/players.ts | 10 ++- packages/web/pages/players.tsx | 65 ++++++++++---- 5 files changed, 146 insertions(+), 23 deletions(-) create mode 100644 packages/web/components/Player/Filter/AdjascentTimezonePlayers.tsx diff --git a/packages/web/components/Player/Filter/AdjascentTimezonePlayers.tsx b/packages/web/components/Player/Filter/AdjascentTimezonePlayers.tsx new file mode 100644 index 00000000..a3237ca7 --- /dev/null +++ b/packages/web/components/Player/Filter/AdjascentTimezonePlayers.tsx @@ -0,0 +1,87 @@ +import { Flex, LoadingState, Text, TimezoneOptions, VStack } from '@metafam/ds'; +import { PlayerList } from 'components/Player/PlayerList'; +import { GetPlayersQueryVariables } from 'graphql/autogen/types'; +import { usePlayerFilter } from 'lib/hooks/players'; +import { useOnScreen } from 'lib/hooks/useOnScreen'; +import React, { useCallback, useEffect, useMemo, useRef } from 'react'; + +type Props = { + queryVariables: GetPlayersQueryVariables; +}; + +export const AdjascentTimezonePlayers: React.FC = ({ + queryVariables: defaultQueryVariables, +}) => { + const moreRef = useRef(null); + + const queryVariables = useMemo(() => { + const timezoneValue = defaultQueryVariables.timezones + ? defaultQueryVariables.timezones[0] + : undefined; + const timezone = TimezoneOptions.find((t) => t.value === timezoneValue); + const adjascentTimezones = timezone + ? TimezoneOptions.filter( + (t) => + Math.abs(t.offset - timezone.offset) <= 4 && + t.value !== timezoneValue, + ).sort((a, b) => (a.offset < b.offset ? -1 : 1)) + : []; + return { + ...defaultQueryVariables, + offset: 0, + timezones: adjascentTimezones.map((t) => t.value), + }; + }, [defaultQueryVariables]); + + const onScreen = useOnScreen(moreRef); + + const { + players, + totalCount, + fetching, + fetchingMore, + error, + nextPage, + moreAvailable, + } = usePlayerFilter(queryVariables); + + const loadMore = useCallback(() => { + if (onScreen && !fetching && !fetchingMore && moreAvailable) { + nextPage(); + } + }, [nextPage, fetching, fetchingMore, onScreen, moreAvailable]); + + useEffect(() => { + loadMore(); + }, [loadMore]); + + return ( + <> + {error ? {`Error: ${error.message}`} : null} + {!error && players.length && (fetchingMore || !fetching) ? ( + <> + + + {totalCount} player{totalCount === 1 ? '' : 's'} in adjacent time + zones + + + + + ) : null} + + {fetching || fetchingMore || moreAvailable ? ( + + ) : ( + No more players available + )} + + + ); +}; diff --git a/packages/web/components/Player/Filter/DesktopFilters.tsx b/packages/web/components/Player/Filter/DesktopFilters.tsx index cdec1284..3f8deafd 100644 --- a/packages/web/components/Player/Filter/DesktopFilters.tsx +++ b/packages/web/components/Player/Filter/DesktopFilters.tsx @@ -150,7 +150,8 @@ export const DesktopFilters: React.FC = ({ styles={styles} value={timezones} onChange={(value) => { - setTimezones(value as ValueType[]); + const values = value as ValueType[]; + setTimezones(values.slice(-1)); }} options={TimezoneOptions} showSearch diff --git a/packages/web/components/Player/Filter/MobileFilters.tsx b/packages/web/components/Player/Filter/MobileFilters.tsx index 1a3341b4..c721efd5 100644 --- a/packages/web/components/Player/Filter/MobileFilters.tsx +++ b/packages/web/components/Player/Filter/MobileFilters.tsx @@ -231,10 +231,12 @@ export const MobileFilters: React.FC = ({ { - setTimezones(value as ValueType[]); + const values = value as ValueType[]; + setTimezones(values.slice(-1)); }} options={TimezoneOptions} onBack={onBack} + isMulti={false} showSearch isTimezone /> diff --git a/packages/web/lib/hooks/players.ts b/packages/web/lib/hooks/players.ts index 1b94b515..6162256e 100644 --- a/packages/web/lib/hooks/players.ts +++ b/packages/web/lib/hooks/players.ts @@ -53,11 +53,17 @@ const useFilteredPlayers = (variables: GetPlayersQueryVariables) => { return { fetching, players, totalCount, error }; }; -export const usePlayerFilter = (): PlayerFilter => { +export const usePlayerFilter = ( + defaultVariables: GetPlayersQueryVariables = defaultQueryVariables, +): PlayerFilter => { const [ queryVariables, setQueryVariables, - ] = useState(defaultQueryVariables); + ] = useState(defaultVariables); + + useEffect(() => { + setQueryVariables(defaultVariables); + }, [defaultVariables]); const aggregates = usePlayerAggregates(); diff --git a/packages/web/pages/players.tsx b/packages/web/pages/players.tsx index 6fab1c01..a5c361a1 100644 --- a/packages/web/pages/players.tsx +++ b/packages/web/pages/players.tsx @@ -1,14 +1,16 @@ import { LoadingState, Text, VStack } from '@metafam/ds'; import { PageContainer } from 'components/Container'; +import { AdjascentTimezonePlayers } from 'components/Player/Filter/AdjascentTimezonePlayers'; import { PlayerFilter } from 'components/Player/Filter/PlayerFilter'; import { PlayerList } from 'components/Player/PlayerList'; import { HeadComponent } from 'components/Seo'; +import { GetPlayersQueryVariables } from 'graphql/autogen/types'; import { getSsrClient } from 'graphql/client'; import { getPlayerFilters, getPlayersWithCount } from 'graphql/getPlayers'; import { usePlayerFilter } from 'lib/hooks/players'; import { useOnScreen } from 'lib/hooks/useOnScreen'; import { InferGetStaticPropsType } from 'next'; -import React, { useCallback, useEffect, useRef } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef } from 'react'; type Props = InferGetStaticPropsType; @@ -46,15 +48,15 @@ const Players: React.FC = () => { moreAvailable, } = usePlayerFilter(); - const loaderRef = useRef(null); + const moreRef = useRef(null); - const onScreen = useOnScreen(loaderRef); + const onScreen = useOnScreen(moreRef); const loadMore = useCallback(() => { - if (onScreen && !fetching) { + if (onScreen && !fetching && !fetchingMore && moreAvailable) { nextPage(); } - }, [nextPage, fetching, onScreen]); + }, [nextPage, fetching, fetchingMore, moreAvailable, onScreen]); useEffect(() => { loadMore(); @@ -77,24 +79,49 @@ const Players: React.FC = () => { resetFilter={resetFilter} totalCount={totalCount} /> - {error && {`Error: ${error.message}`}} - {!error && players.length && (fetchingMore || !fetching) && ( + {error ? {`Error: ${error.message}`} : null} + {!error && players.length && (fetchingMore || !fetching) ? ( - )} - - {fetching || fetchingMore || moreAvailable ? ( - - ) : ( - - {totalCount > 0 - ? 'No more players available' - : 'There were no matches'} - - )} - + ) : null} + ); }; export default Players; + +type MorePlayersProps = { + fetching: boolean; + totalCount: number; + queryVariables: GetPlayersQueryVariables; +}; + +const MorePlayers = React.forwardRef( + ({ fetching, totalCount, queryVariables }, ref) => { + const isTimezoneSelected = useMemo( + () => queryVariables.timezones && queryVariables.timezones.length > 0, + [queryVariables], + ); + return ( + + {fetching ? : null} + {!fetching && !isTimezoneSelected ? ( + + {totalCount > 0 + ? 'No more players available' + : 'There were no matches'} + + ) : null} + {!fetching && isTimezoneSelected ? ( + + ) : null} + + ); + }, +);