fix(#720): fix timeline scroll

pull/297/head
Rakov 2 years ago
parent 8dce04b35d
commit 2dba409aa7
  1. 12
      src/features/MatchesSlider/hooks.tsx
  2. 40
      src/features/MatchesSlider/index.tsx
  3. 2
      src/features/MatchesSlider/styled.tsx
  4. 65
      src/features/MatchesTimeline/hooks.tsx
  5. 7
      src/features/MatchesTimeline/index.tsx
  6. 4
      src/features/MatchesTimeline/styled.tsx

@ -71,11 +71,19 @@ export const useMatchesSlider = (matches: Array<Match>) => {
} }
const slideLeft = useMemo(() => throttle(() => { const slideLeft = useMemo(() => throttle(() => {
slidesRef.current!.scrollBy(-((MATCH_CARD_WIDTH + MATCH_CARD_GAP) * MATCHES_TO_SCROLL), 0) slidesRef.current!.scrollBy({
behavior: 'smooth',
left: -((MATCH_CARD_WIDTH + MATCH_CARD_GAP) * MATCHES_TO_SCROLL),
top: 0,
})
}, SCROLLING_DELAY), []) }, SCROLLING_DELAY), [])
const slideRight = useMemo(() => throttle(() => { const slideRight = useMemo(() => throttle(() => {
slidesRef.current!.scrollBy((MATCH_CARD_WIDTH + MATCH_CARD_GAP) * MATCHES_TO_SCROLL, 0) slidesRef.current!.scrollBy({
behavior: 'smooth',
left: (MATCH_CARD_WIDTH + MATCH_CARD_GAP) * MATCHES_TO_SCROLL,
top: 0,
})
}, SCROLLING_DELAY), []) }, SCROLLING_DELAY), [])
return { return {

@ -1,18 +1,11 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import { useQuery } from 'react-query'
import map from 'lodash/map' import map from 'lodash/map'
import isEmpty from 'lodash/isEmpty' import isEmpty from 'lodash/isEmpty'
import type { Match } from 'helpers' import type { Match } from 'helpers'
import { querieKeys } from 'config'
import { MatchCard } from 'features/MatchCard' import { MatchCard } from 'features/MatchCard'
import { useMatchSwitchesStore } from 'features/MatchSwitches'
import { LiveScore, getLiveScores } from 'requests'
import { useMatchesSlider } from './hooks' import { useMatchesSlider } from './hooks'
import { import {
@ -40,27 +33,18 @@ export const MatchesSlider = ({ matches }: MatchesSliderProps) => {
slidesRef, slidesRef,
} = useMatchesSlider(matches) } = useMatchesSlider(matches)
const { isScoreHidden } = useMatchSwitchesStore()
const { data: liveMatchScores } = useQuery({
queryFn: async () => {
if (!isScoreHidden && matches.filter(({ live }) => live)?.length > 0) {
const scores = await getLiveScores()
return scores
}
return []
},
queryKey: querieKeys.liveMatchScores,
refetchInterval: 5000,
})
const scrollToMatchByIndex = (index: number) => { const scrollToMatchByIndex = (index: number) => {
const offsetLeftCount = slidesRef.current!.querySelectorAll('li')[index].offsetLeft const match = slidesRef.current!.querySelectorAll('li')[index]
const offsetLeftCount = match.offsetLeft
const PADDING_PARENT = 10 const PADDING_PARENT = 10
const offsetLeft = offsetLeftCount - PADDING_PARENT const offsetLeft = offsetLeftCount - PADDING_PARENT
slidesRef.current!.scrollBy(offsetLeft, 0) slidesRef.current!.scrollBy({
// @ts-ignore
behavior: 'instant',
left: offsetLeft,
})
} }
// скролл к лайв матчам или сегодняшней дате // скролл к лайв матчам или сегодняшней дате
@ -79,7 +63,11 @@ export const MatchesSlider = ({ matches }: MatchesSliderProps) => {
const slidesRefClientWidth = slidesRef.current!.clientWidth const slidesRefClientWidth = slidesRef.current!.clientWidth
const slidesRefScrollWidth = slidesRef.current!.scrollWidth const slidesRefScrollWidth = slidesRef.current!.scrollWidth
slidesRef.current!.scrollBy(slidesRefScrollWidth - slidesRefClientWidth, 0) slidesRef.current!.scrollBy({
// @ts-ignore
behavior: 'instant',
left: slidesRefScrollWidth - slidesRefClientWidth,
})
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []) }, [])
@ -107,10 +95,6 @@ export const MatchesSlider = ({ matches }: MatchesSliderProps) => {
<MatchCard <MatchCard
match={match} match={match}
key={match.id} key={match.id}
score={liveMatchScores?.find(
({ match_id, sport_id }: LiveScore) => match_id === match.id
&& sport_id === match.sportType,
)}
/> />
))} ))}
</Slides> </Slides>

@ -14,7 +14,7 @@ export const Slides = styled.ul`
overflow-x: auto; overflow-x: auto;
gap: 0.9rem; gap: 0.9rem;
padding: 10px 10px 10px 7px; padding: 10px 10px 10px 7px;
&::-webkit-scrollbar { &::-webkit-scrollbar {
display: none; display: none;
} }

@ -1,3 +1,4 @@
/* eslint-disable no-param-reassign */
import { import {
useCallback, useCallback,
useEffect, useEffect,
@ -5,11 +6,16 @@ import {
useState, useState,
} from 'react' } from 'react'
import { useQuery } from 'react-query'
import { querieKeys, PAGES } from 'config'
import { useRouteMatch } from 'react-router-dom' import { useRouteMatch } from 'react-router-dom'
import { import {
MatchDto, MatchDto,
MatchesTimeline,
TimelineTournamentDto, TimelineTournamentDto,
getLiveScores,
getTimelineMatches, getTimelineMatches,
} from 'requests' } from 'requests'
@ -17,8 +23,7 @@ import { Match, prepareMatches } from 'helpers'
import { useAuthStore } from 'features/AuthStore' import { useAuthStore } from 'features/AuthStore'
import { useHeaderFiltersStore } from 'features/HeaderFilters' import { useHeaderFiltersStore } from 'features/HeaderFilters'
import { useMatchSwitchesStore } from 'features/MatchSwitches'
import { PAGES } from 'config'
export type TimelineTournamentList = Array<Omit<TimelineTournamentDto, 'matches'> & { export type TimelineTournamentList = Array<Omit<TimelineTournamentDto, 'matches'> & {
matches: Array<Match>, matches: Array<Match>,
@ -35,10 +40,12 @@ export const useTimeline = () => {
selectedSport, selectedSport,
setSportIds, setSportIds,
} = useHeaderFiltersStore() } = useHeaderFiltersStore()
const { isScoreHidden } = useMatchSwitchesStore()
const [isTimelineFetching, setIsTimelineFetching] = useState(true) const [isTimelineFetching, setIsTimelineFetching] = useState(true)
const [onlineUpcomingMatches, setOnlineUpcomingMatches] = useState<Array<Match>>([]) const [onlineUpcomingMatches, setOnlineUpcomingMatches] = useState<Array<Match>>([])
const [tournamentList, setTournamentList] = useState<TimelineTournamentList>([]) const [tournamentList, setTournamentList] = useState<TimelineTournamentList>([])
const [timeline, setTimeline] = useState<MatchesTimeline>()
const prepareMatchesDto = useCallback((matches: Array<MatchDto>) => prepareMatches( const prepareMatchesDto = useCallback((matches: Array<MatchDto>) => prepareMatches(
matches, matches,
@ -50,21 +57,22 @@ export const useTimeline = () => {
(async () => { (async () => {
setIsTimelineFetching(true) setIsTimelineFetching(true)
try { try {
const timeline = await getTimelineMatches() const timelineFetched = await getTimelineMatches()
const convertedMatches = timeline.online_upcoming[0].matches setTimeline(timelineFetched)
const convertedMatches = timelineFetched.online_upcoming[0].matches
const preparedMatches = prepareMatchesDto(convertedMatches) const preparedMatches = prepareMatchesDto(convertedMatches)
setOnlineUpcomingMatches(preparedMatches) setOnlineUpcomingMatches(preparedMatches)
setTournamentList([ setTournamentList([
...timeline.favorite.map((item) => ({ ...timelineFetched.favorite.map((item) => ({
...item, ...item,
matches: prepareMatchesDto(item.matches), matches: prepareMatchesDto(item.matches),
})), })),
...timeline.promo.map((item) => ({ ...timelineFetched.promo.map((item) => ({
...item, ...item,
matches: prepareMatchesDto(item.matches), matches: prepareMatchesDto(item.matches),
})), })),
...timeline.others.map((item) => ({ ...timelineFetched.others.map((item) => ({
...item, ...item,
matches: prepareMatchesDto(item.matches), matches: prepareMatchesDto(item.matches),
})), })),
@ -76,6 +84,49 @@ export const useTimeline = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []) }, [])
useQuery({
queryFn: async () => {
let isLiveMatch = false
if (timeline) {
for (const [, value] of Object.entries(timeline)) {
if (isLiveMatch) break
// eslint-disable-next-line no-loop-func
value.forEach((t) => {
const liveMatch = t.matches.find((match) => match.live)
if (liveMatch) {
isLiveMatch = true
}
})
}
}
if (!isScoreHidden && isLiveMatch) {
const scores = await getLiveScores()
tournamentList.forEach((tournament) => {
tournament.matches.forEach((match) => {
const score = scores.find((s) => (
s.match_id === match.id && s.sport_id === match.sportType
))
if (score) {
match.team1.score = score?.team1.score ?? match.team1.score
match.team2.score = score?.team2.score ?? match.team2.score
}
})
})
onlineUpcomingMatches.forEach((upcomingMatch) => {
const score = scores.find((s) => (
s.match_id === upcomingMatch.id && s.sport_id === upcomingMatch.sportType
))
if (score) {
upcomingMatch.team1.score = score?.team1.score ?? upcomingMatch.team1.score
upcomingMatch.team2.score = score?.team2.score ?? upcomingMatch.team2.score
}
})
}
},
queryKey: querieKeys.liveMatchScores,
refetchInterval: 30000,
})
const filteredTournamentsBySport = useMemo(() => { const filteredTournamentsBySport = useMemo(() => {
if (isHomePage && selectedSport) { if (isHomePage && selectedSport) {
return tournamentList.filter((t) => compareSport(t.sport_id, selectedSport)) return tournamentList.filter((t) => compareSport(t.sport_id, selectedSport))

@ -23,7 +23,7 @@ import {
TournamentSubtitleWrapper, TournamentSubtitleWrapper,
} from './styled' } from './styled'
const TOURNAMENT_LIMIT = 6 const TOURNAMENT_LIMIT = 10
export const MatchesTimeline = () => { export const MatchesTimeline = () => {
const { const {
@ -60,7 +60,8 @@ export const MatchesTimeline = () => {
useEffect(() => { useEffect(() => {
if (tournamentList.length) { if (tournamentList.length) {
pageRef.current = 0 pageRef.current = 0
tournamentList.length && setTournaments(getTournaments()) isLastPageRef.current = false
tournamentList.length > 0 && setTournaments(getTournaments())
pageRef.current = 1 pageRef.current = 1
} }
}, [getTournaments, tournamentList]) }, [getTournaments, tournamentList])
@ -88,7 +89,7 @@ export const MatchesTimeline = () => {
tournament, tournament,
tournament_id, tournament_id,
}) => ( }) => (
<RowWrapper key={tournament_id}> <RowWrapper key={`${tournament_id}_${sport_id}`}>
<TournamentSubtitleWrapper> <TournamentSubtitleWrapper>
<TournamentSubtitle <TournamentSubtitle
sportInfo={matches[0].sportInfo} sportInfo={matches[0].sportInfo}

@ -71,8 +71,10 @@ export const Tournament = styled.div<{
export const TournamentLogo = styled(ProfileLogo)` export const TournamentLogo = styled(ProfileLogo)`
position: absolute; position: absolute;
max-height: 100%;
padding: 20px; padding: 20px;
width: 100%;
height: 100%;
object-fit: scale-down;
` `
export const Loading = styled.div` export const Loading = styled.div`

Loading…
Cancel
Save