diff --git a/src/features/Common/Image/index.tsx b/src/features/Common/Image/index.tsx index b1e87936..21022153 100644 --- a/src/features/Common/Image/index.tsx +++ b/src/features/Common/Image/index.tsx @@ -1,11 +1,5 @@ import type { BaseSyntheticEvent } from 'react' -import { - RefObject, - useCallback, - useEffect, - useRef, - useState, -} from 'react' +import { useCallback } from 'react' import styled from 'styled-components/macro' @@ -16,8 +10,7 @@ type Props = { className?: string, dataSrc?: string, fallbackSrc?: string, - imagesList?: Array>, - setImagesList?: (imagesList: Array>) => void, + onLoad?: () => void, src: string, title?: string, } @@ -27,23 +20,10 @@ export const Image = ({ className, dataSrc, fallbackSrc, - imagesList = [], - setImagesList, + onLoad, src, title, }: Props) => { - const imgRef = useRef(null) - const [loaded, setLoaded] = useState(false) - - useEffect( - () => { - if (!setImagesList || !loaded) return - setImagesList([...imagesList, imgRef]) - }, - // eslint-disable-next-line - [loaded], - ) - const onError = useCallback((e: BaseSyntheticEvent) => { // eslint-disable-next-line no-param-reassign e.target.onError = '' @@ -58,8 +38,7 @@ export const Image = ({ data-src={dataSrc} className={className} onError={onError} - onLoad={() => setLoaded(true)} - ref={imgRef} + onLoad={() => onLoad?.()} title={title} /> ) diff --git a/src/features/MatchPage/types.tsx b/src/features/MatchPage/types.tsx index 8746de39..ebd1509b 100644 --- a/src/features/MatchPage/types.tsx +++ b/src/features/MatchPage/types.tsx @@ -18,6 +18,7 @@ export type PlayerPlaylistOption = { id: number, name_eng: string, name_rus: string, + start?: boolean, type: PlaylistTypes.PLAYER, } diff --git a/src/features/MatchPopup/components/GroupedPlayersList/index.tsx b/src/features/MatchPopup/components/GroupedPlayersList/index.tsx new file mode 100644 index 00000000..9e3438a5 --- /dev/null +++ b/src/features/MatchPopup/components/GroupedPlayersList/index.tsx @@ -0,0 +1,75 @@ +import { + useMemo, + useState, + useCallback, +} from 'react' + +import map from 'lodash/map' +import every from 'lodash/every' +import groupBy from 'lodash/groupBy' + +import type { PlayerPlaylistOptions } from 'features/MatchPage/types' +import { Loader } from 'features/Loader' + +import { Teams } from '../../types' +import { PlayersList } from '../PlayersList' +import { ListsWrapper, LoaderWrapper } from './styled' + +const useItemsLoadedState = (items: PlayerPlaylistOptions) => { + const [loadedIds, setLoadedIds] = useState>({}) + + const onLoad = useCallback((id: number) => { + setLoadedIds((state) => ({ ...state, [id]: id })) + }, []) + + const allLoaded = useMemo(() => { + const ids = map(items, ({ id }) => id) + return every(ids, (id) => Boolean(loadedIds[id])) + }, [items, loadedIds]) + + return { + allLoaded, + onLoad, + } +} + +type Props = { + players: PlayerPlaylistOptions, + team: Teams, +} + +export const GroupedPlayersList = ({ + players, + team, +}: Props) => { + const { allLoaded, onLoad } = useItemsLoadedState(players) + + const { benchedPlayers, startingPlayers } = groupBy( + players, + ({ start }) => (start ? 'startingPlayers' : 'benchedPlayers'), + ) + + return ( + + { + !allLoaded && ( + + + + ) + } + + + + ) +} diff --git a/src/features/MatchPopup/components/GroupedPlayersList/styled.tsx b/src/features/MatchPopup/components/GroupedPlayersList/styled.tsx new file mode 100644 index 00000000..1f07a97b --- /dev/null +++ b/src/features/MatchPopup/components/GroupedPlayersList/styled.tsx @@ -0,0 +1,29 @@ +import styled from 'styled-components/macro' + +import { devices } from 'config' + +import { List } from '../PlayersList/styled' + +export const LoaderWrapper = styled.div` + position: absolute; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +` + +export const ListsWrapper = styled.div` + position: relative; + width: 576px; + display: flex; + flex-direction: column; + + ${List}:last-child { + margin-top: 25px; + } + + @media ${devices.mobile} { + width: 100%; + } +` diff --git a/src/features/MatchPopup/components/PlayersList/index.tsx b/src/features/MatchPopup/components/PlayersList/index.tsx index 0f5e5245..c8142432 100644 --- a/src/features/MatchPopup/components/PlayersList/index.tsx +++ b/src/features/MatchPopup/components/PlayersList/index.tsx @@ -1,22 +1,13 @@ -import React, { - RefObject, - useEffect, - useState, -} from 'react' - import map from 'lodash/map' -import size from 'lodash/size' -import { ProfileTypes, SportTypes } from 'config' +import { ProfileTypes } from 'config' -import { PlayerPlaylistOptions, PlayerPlaylistOption } from 'features/MatchPage/types' +import { PlayerPlaylistOptions } from 'features/MatchPage/types' import { useMatchPopupStore } from 'features/MatchPopup/store' -import { Loader } from 'features/Loader' import { Teams } from '../../types' import { List, - LoaderWrapper, Item, Logo, PlayerName, @@ -24,52 +15,34 @@ import { } from './styled' type Props = { - onClick: (player: PlayerPlaylistOption) => void, + allLoaded: boolean, + onLoad: (id: number) => void, players: PlayerPlaylistOptions, - sportType: SportTypes, team: Teams, } export const PlayersList = ({ - onClick, + allLoaded, + onLoad, players, - sportType, team, }: Props) => { - const { match } = useMatchPopupStore() - const [imagesList, setImagesList] = useState< - Array> - >([]) - - const [allImagesReady, setAllImagesReady] = useState(false) - - useEffect(() => { - if (size(imagesList) === size(players)) { - setAllImagesReady(true) - } - }, [imagesList, players]) + const { handlePlayerClick, match } = useMatchPopupStore() if (!match) return null return ( - {!allImagesReady - && ( - - - - )} { map(players, (player) => ( - - diff --git a/src/features/MatchPopup/components/PlayersList/styled.tsx b/src/features/MatchPopup/components/PlayersList/styled.tsx index eb2617e6..40261ed4 100644 --- a/src/features/MatchPopup/components/PlayersList/styled.tsx +++ b/src/features/MatchPopup/components/PlayersList/styled.tsx @@ -15,23 +15,14 @@ type ItemProps = { isReady?: boolean, } -export const LoaderWrapper = styled.div` - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; -` - export const List = styled.ul` - width: calc((100% - 30px) / 2); display: flex; flex-wrap: wrap; align-content: flex-start; - flex-direction: ${({ team }) => ( + justify-content: ${({ team }) => ( team === Teams.TEAM1 - ? 'row-reverse' - : 'row' + ? 'flex-end' + : '' )}; @media ${devices.mobile} { @@ -66,6 +57,7 @@ export const Button = styled.button` border: none; background: none; cursor: pointer; + padding: 0; width: 100%; height: 100%; diff --git a/src/features/MatchPopup/components/PlayersListDesktop/index.tsx b/src/features/MatchPopup/components/PlayersListDesktop/index.tsx index dc25aafa..a59d61f3 100644 --- a/src/features/MatchPopup/components/PlayersListDesktop/index.tsx +++ b/src/features/MatchPopup/components/PlayersListDesktop/index.tsx @@ -1,11 +1,12 @@ import styled from 'styled-components/macro' import { T9n } from 'features/T9n' +import { customScrollbar } from 'features/Common' import { useMatchPopupStore } from 'features/MatchPopup' import { Teams } from '../../types' import { BlockTitle } from '../../styled' -import { PlayersList } from '../PlayersList' +import { GroupedPlayersList } from '../GroupedPlayersList' const Wrapper = styled.div` display: flex; @@ -16,15 +17,29 @@ const Wrapper = styled.div` const ListsWrapper = styled.div` width: 100%; + height: 325px; + overflow-y: auto; margin-top: 10px; display: flex; flex-direction: row; - justify-content: space-between; + justify-content: space-around; + + ${customScrollbar}; + + ::-webkit-scrollbar-thumb { + border-radius: 3px; + background: rgba(196, 196, 196, 0.3); + } + + ::-webkit-scrollbar-track, + ::-webkit-scrollbar-corner { + border-radius: 3px; + background: rgba(103, 103, 103, 0.3); + } ` export const PlayersListDesktop = () => { const { - handlePlayerClick, match, matchPlaylists, } = useMatchPopupStore() @@ -37,17 +52,13 @@ export const PlayersListDesktop = () => { - - diff --git a/src/features/MatchPopup/components/PlayersListMobile/index.tsx b/src/features/MatchPopup/components/PlayersListMobile/index.tsx index b3d0d17f..4ac02382 100644 --- a/src/features/MatchPopup/components/PlayersListMobile/index.tsx +++ b/src/features/MatchPopup/components/PlayersListMobile/index.tsx @@ -6,7 +6,7 @@ import { useMatchPopupStore } from 'features/MatchPopup' import { Teams } from '../../types' import { BlockTitle } from '../../styled' -import { PlayersList } from '../PlayersList' +import { GroupedPlayersList } from '../GroupedPlayersList' import { Wrapper, Tabs, @@ -15,7 +15,6 @@ import { export const PlayersListMobile = () => { const { - handlePlayerClick, match, matchPlaylists, } = useMatchPopupStore() @@ -46,11 +45,9 @@ export const PlayersListMobile = () => { - ) diff --git a/src/features/ProfileLogo/index.tsx b/src/features/ProfileLogo/index.tsx index 42952c20..c3eeedd1 100644 --- a/src/features/ProfileLogo/index.tsx +++ b/src/features/ProfileLogo/index.tsx @@ -1,5 +1,3 @@ -import { RefObject } from 'react' - import { ProfileTypes, SportTypes } from 'config' import { getProfileFallbackLogo, getProfileLogo } from 'helpers' @@ -12,12 +10,11 @@ type ProfileImageProps = { altNameObj?: ObjectWithName, className?: string, id: number, - imagesList?: Array>, lazy?: boolean, nameAsTitle?: boolean, + onLoad?: () => void, prefix?: string, profileType: ProfileTypes, - setImagesList?: (imagesList: Array>) => void, size?: number, sportType: SportTypes, title?: string, @@ -28,12 +25,11 @@ export const ProfileLogo = ({ altNameObj, className, id, - imagesList, lazy = false, nameAsTitle, + onLoad, prefix, profileType, - setImagesList, size, sportType, title, @@ -58,8 +54,7 @@ export const ProfileLogo = ({ dataSrc={lazy ? src : ''} fallbackSrc={fallbackSrc} className={className} - imagesList={imagesList} - setImagesList={setImagesList} + onLoad={onLoad} title={titleText} /> ) diff --git a/src/requests/getMatchPlaylists.tsx b/src/requests/getMatchPlaylists.tsx index f0c53773..a2ff0351 100644 --- a/src/requests/getMatchPlaylists.tsx +++ b/src/requests/getMatchPlaylists.tsx @@ -40,6 +40,7 @@ type Player = { name_eng: string, name_rus: string, num: string, + start?: boolean, } export type Players = Array