showing adjacent timezones for players

This commit is contained in:
dan13ram
2021-07-12 21:14:10 +05:30
committed by dan13ram
parent 90267583c5
commit c41246bb4e
5 changed files with 146 additions and 23 deletions

View File

@@ -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<Props> = ({
queryVariables: defaultQueryVariables,
}) => {
const moreRef = useRef<HTMLDivElement>(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 ? <Text>{`Error: ${error.message}`}</Text> : null}
{!error && players.length && (fetchingMore || !fetching) ? (
<>
<Flex
justify="space-between"
w="100%"
maxW="80rem"
px="4"
align="center"
>
<Text fontWeight="bold" fontSize="xl" w="100%" maxW="79rem" mb="8">
{totalCount} player{totalCount === 1 ? '' : 's'} in adjacent time
zones
</Text>
</Flex>
<PlayerList players={players} />
</>
) : null}
<VStack w="100%" ref={moreRef}>
{fetching || fetchingMore || moreAvailable ? (
<LoadingState color="white" />
) : (
<Text color="white">No more players available</Text>
)}
</VStack>
</>
);
};

View File

@@ -150,7 +150,8 @@ export const DesktopFilters: React.FC<Props> = ({
styles={styles}
value={timezones}
onChange={(value) => {
setTimezones(value as ValueType[]);
const values = value as ValueType[];
setTimezones(values.slice(-1));
}}
options={TimezoneOptions}
showSearch

View File

@@ -231,10 +231,12 @@ export const MobileFilters: React.FC<Props> = ({
<FilterContent
value={timezones}
onChange={(value) => {
setTimezones(value as ValueType[]);
const values = value as ValueType[];
setTimezones(values.slice(-1));
}}
options={TimezoneOptions}
onBack={onBack}
isMulti={false}
showSearch
isTimezone
/>

View File

@@ -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<GetPlayersQueryVariables>(defaultQueryVariables);
] = useState<GetPlayersQueryVariables>(defaultVariables);
useEffect(() => {
setQueryVariables(defaultVariables);
}, [defaultVariables]);
const aggregates = usePlayerAggregates();

View File

@@ -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<typeof getStaticProps>;
@@ -46,15 +48,15 @@ const Players: React.FC<Props> = () => {
moreAvailable,
} = usePlayerFilter();
const loaderRef = useRef<HTMLDivElement>(null);
const moreRef = useRef<HTMLDivElement>(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<Props> = () => {
resetFilter={resetFilter}
totalCount={totalCount}
/>
{error && <Text>{`Error: ${error.message}`}</Text>}
{!error && players.length && (fetchingMore || !fetching) && (
{error ? <Text>{`Error: ${error.message}`}</Text> : null}
{!error && players.length && (fetchingMore || !fetching) ? (
<PlayerList players={players} />
)}
<VStack ref={loaderRef} w="100%">
{fetching || fetchingMore || moreAvailable ? (
<LoadingState color="white" />
) : (
<Text color="white">
{totalCount > 0
? 'No more players available'
: 'There were no matches'}
</Text>
)}
</VStack>
) : null}
<MorePlayers
ref={moreRef}
fetching={fetching || fetchingMore || moreAvailable}
totalCount={totalCount}
queryVariables={queryVariables}
/>
</VStack>
</PageContainer>
);
};
export default Players;
type MorePlayersProps = {
fetching: boolean;
totalCount: number;
queryVariables: GetPlayersQueryVariables;
};
const MorePlayers = React.forwardRef<HTMLDivElement, MorePlayersProps>(
({ fetching, totalCount, queryVariables }, ref) => {
const isTimezoneSelected = useMemo(
() => queryVariables.timezones && queryVariables.timezones.length > 0,
[queryVariables],
);
return (
<VStack w="100%" ref={ref}>
{fetching ? <LoadingState color="white" /> : null}
{!fetching && !isTimezoneSelected ? (
<Text color="white">
{totalCount > 0
? 'No more players available'
: 'There were no matches'}
</Text>
) : null}
{!fetching && isTimezoneSelected ? (
<AdjascentTimezonePlayers queryVariables={queryVariables} />
) : null}
</VStack>
);
},
);