From 2534688392936c4375a3b809cc0e3894db2fd25b Mon Sep 17 00:00:00 2001 From: Armen <35077035+Armen9393@users.noreply.github.com> Date: Thu, 20 Aug 2020 16:13:21 +0300 Subject: [PATCH] Ott 299 team page (#90) * fix(ott-287): changed default football to null * fix(ott-287): minor bug * fix(ott-287): temp * feat(ott-287): created infinite scroll * feat(ott-287): added infinite scroll * fix(ott-299): changed imports position * fix(ott-299): comment bug fix * fix(ott-299): minor bug fix * fix(ott-299): some minor css bugs * fix(ott-299): fixed width styles * fix(ott-299): fixed menu right margin * fix(ott-299): fixed comments, added team type * fix(ott-299): conflict resolved * fix(ott-299): conflict consequences are resolved * fix(ott-299): some minor bugs fix --- .gitignore | 1 - src/config/procedures.tsx | 2 + src/features/Header/index.tsx | 14 +++-- src/features/Header/styled.tsx | 19 +++++-- .../components/TournamentFilter/hooks.tsx | 44 +++++++++----- .../components/TournamentFilter/index.tsx | 3 +- .../components/TournamentList/index.tsx | 2 +- .../MatchPage/MatchProfileCard/index.tsx | 57 +++++++++++++++++++ .../MatchPage/MatchProfileCard/styled.tsx | 38 +++++++++++++ src/features/MatchPage/hooks.tsx | 53 +++++++++++++++++ src/features/MatchPage/index.tsx | 20 ++++--- src/features/MatchPage/styled.tsx | 6 ++ src/features/Menu/index.tsx | 1 + src/features/OutsideClick/index.tsx | 8 +-- src/features/ProfileCard/styled.tsx | 2 +- src/features/Search/index.tsx | 2 +- src/features/Search/styled.tsx | 2 +- src/features/TeamPage/hooks.tsx | 35 ++++++++++-- src/features/TeamPage/index.tsx | 15 ++++- src/features/TournamentPage/hooks.tsx | 11 ++-- src/requests/getMatchInfo.tsx | 47 +++++++++++++++ src/requests/getSportTournaments.tsx | 7 ++- src/requests/getTeamInfo.tsx | 40 +++++++++++++ src/requests/index.tsx | 2 + 24 files changed, 377 insertions(+), 54 deletions(-) create mode 100644 src/features/MatchPage/MatchProfileCard/index.tsx create mode 100644 src/features/MatchPage/MatchProfileCard/styled.tsx create mode 100644 src/features/MatchPage/hooks.tsx create mode 100644 src/features/MatchPage/styled.tsx create mode 100644 src/requests/getMatchInfo.tsx create mode 100644 src/requests/getTeamInfo.tsx diff --git a/.gitignore b/.gitignore index c8f29b44..38ec3277 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,5 @@ yarn-error.log* yarn.lock package-lock.json - # IntelliJ IDEA products .idea diff --git a/src/config/procedures.tsx b/src/config/procedures.tsx index 310ca339..16b79274 100644 --- a/src/config/procedures.tsx +++ b/src/config/procedures.tsx @@ -2,10 +2,12 @@ export const PROCEDURES = { auth_user: 'auth_user', create_user: 'create_user', get_cities: 'get_cities', + get_match_info: 'get_match_info', get_matches: 'get_matches', get_player_info: 'get_player_info', get_players_teams_tournaments: 'get_players_teams_tournaments', get_sport_list: 'get_sport_list', + get_team_info: 'get_team_info', get_tournament_info: 'get_tournament_info', get_tournament_list: 'get_tournament_list', get_user_favorites: 'get_user_favorites', diff --git a/src/features/Header/index.tsx b/src/features/Header/index.tsx index 3e4f17df..1f506cc3 100644 --- a/src/features/Header/index.tsx +++ b/src/features/Header/index.tsx @@ -18,6 +18,8 @@ import { FilterWrapper, HomeButtonLink, SearchWrapper, + SportFilterWrapper, + MenuWrapper, } from './styled' export const Header = () => { @@ -25,11 +27,13 @@ export const Header = () => { const isMatch = useRouteMatch(`/:sportName${PAGES.match}/:pageId`)?.isExact return ( - - {!isOnHome && } + + + {!isOnHome && } + {isMatch ? ( - + ) @@ -48,10 +52,10 @@ export const Header = () => { {isOnHome && ( - + - + )} )} diff --git a/src/features/Header/styled.tsx b/src/features/Header/styled.tsx index 6eebaa59..55060f51 100644 --- a/src/features/Header/styled.tsx +++ b/src/features/Header/styled.tsx @@ -12,21 +12,32 @@ export const HomeButtonLink = styled(Link)` cursor:pointer; } ` + export const Wrapper = styled.header` display: flex; padding-top: 16px; margin-bottom: 30px; ` -export const FilterWrapper = styled.div<{ size?: string }>` - width: ${({ size }) => size || '288px'}; + +export const FilterWrapper = styled.div` + width: 288px; height: 48px; margin-right: 16px; display: flex; ` + export const SearchWrapper = styled(FilterWrapper)` - width: ${({ size }) => size || '288px'}; + width: 288px; height: 48px; margin-right: 16px; - margin-left: 57px; display: flex; ` + +export const SportFilterWrapper = styled(FilterWrapper)` + width: 400px; +` + +export const MenuWrapper = styled.div` + display: flex; + margin-right: 57px; +` diff --git a/src/features/HeaderFilters/components/TournamentFilter/hooks.tsx b/src/features/HeaderFilters/components/TournamentFilter/hooks.tsx index 9182211e..741002bb 100644 --- a/src/features/HeaderFilters/components/TournamentFilter/hooks.tsx +++ b/src/features/HeaderFilters/components/TournamentFilter/hooks.tsx @@ -1,10 +1,9 @@ +import type { BaseSyntheticEvent } from 'react' import { useEffect, useState } from 'react' import find from 'lodash/find' - import type { Tournaments } from 'requests' import { getSportTournaments } from 'requests' - import { useToggle } from 'hooks' import { useHeaderFiltersStore } from 'features/HeaderFilters' @@ -12,21 +11,13 @@ import { useLexicsStore } from 'features/LexicsStore' import { normalizeTournaments } from './helpers' -const useTournamentsList = () => { - const { selectedSportTypeId } = useHeaderFiltersStore() +export const useTournamentFilter = () => { const [list, setList] = useState([]) - useEffect(() => { - setList([]) - getSportTournaments(selectedSportTypeId).then(setList) - }, [selectedSportTypeId]) - - return list -} - -export const useTournamentFilter = () => { const { suffix } = useLexicsStore() + const { + selectedSportTypeId, selectedTournamentId, setSelectedTournamentId, } = useHeaderFiltersStore() @@ -35,8 +26,30 @@ export const useTournamentFilter = () => { isOpen, open, } = useToggle() - const tournamentList = useTournamentsList() - const tournaments = normalizeTournaments(tournamentList, suffix) + + useEffect(() => { + setList([]) + getSportTournaments(selectedSportTypeId).then(setList) + }, [selectedSportTypeId]) + + const [offset, setOffset] = useState(0) + const [requestSent, setRequestSent] = useState(false) + + const handleScroll = (e: BaseSyntheticEvent) => { + const scrollPositionBottom = e.target.scrollHeight - e.target.scrollTop + - e.target.clientHeight - 400 <= 0 + + if (scrollPositionBottom && !requestSent) { + setRequestSent(true) + setOffset(offset + 1) + getSportTournaments(selectedSportTypeId).then((res) => { + setList([...list, ...res]) + setRequestSent(false) + }) + } + } + + const tournaments = normalizeTournaments(list, suffix) const selectedTournament = find( tournaments, (tournament) => tournament.id === selectedTournamentId, @@ -49,6 +62,7 @@ export const useTournamentFilter = () => { return { close, + handleScroll, isOpen, onTournamentSelect, open, diff --git a/src/features/HeaderFilters/components/TournamentFilter/index.tsx b/src/features/HeaderFilters/components/TournamentFilter/index.tsx index caf23e69..8a2724a2 100644 --- a/src/features/HeaderFilters/components/TournamentFilter/index.tsx +++ b/src/features/HeaderFilters/components/TournamentFilter/index.tsx @@ -16,6 +16,7 @@ import { export const TournamentFilter = () => { const { close, + handleScroll, isOpen, onTournamentSelect, open, @@ -42,7 +43,7 @@ export const TournamentFilter = () => { { isOpen && ( - + ( onSelect(id)} role='option' > diff --git a/src/features/MatchPage/MatchProfileCard/index.tsx b/src/features/MatchPage/MatchProfileCard/index.tsx new file mode 100644 index 00000000..f2df0bb2 --- /dev/null +++ b/src/features/MatchPage/MatchProfileCard/index.tsx @@ -0,0 +1,57 @@ +import React, { Fragment } from 'react' + +import isEmpty from 'lodash/isEmpty' + +import { getSportColor } from 'helpers/getSportColor' + +import { SportName } from 'features/Common/SportName' + +import { useSportNameParam } from 'hooks/useSportNameParam' +import { useMatchPage } from '../hooks' + +import { + Wrapper, + Teams, + Score, + Tournament, + Dash, +} from './styled' + +export const MatchProfileCard = () => { + const { + matchProfile, + matchProfileNames: { + team1Name, + team2Name, + tournament, + }, + } = useMatchPage() + + const { sportName, sportType } = useSportNameParam() + + const { team1, team2 } = matchProfile || {} + + const color = getSportColor(sportType) + + return ( + + {!isEmpty(matchProfile) + && ( + + + {team1Name} {team2Name} + + + {team1?.score} : {team2?.score} + + + {tournament} + + + )} + + ) +} diff --git a/src/features/MatchPage/MatchProfileCard/styled.tsx b/src/features/MatchPage/MatchProfileCard/styled.tsx new file mode 100644 index 00000000..0740411f --- /dev/null +++ b/src/features/MatchPage/MatchProfileCard/styled.tsx @@ -0,0 +1,38 @@ +import styled from 'styled-components/macro' + +export const Wrapper = styled.div` + display: flex; + font-weight: bold; + font-size: 36px; + line-height: 24px; + color: white; + min-height: 28px; +` + +export const Teams = styled.div` + display: flex; +` + +export const Dash = styled.span` + position: relative; + width: 40px; + border-bottom: 3px solid white; + margin: 0 15px; + height: fit-content; + align-self: center; +` + +export const Score = styled.div` + display: flex; + margin-left: 48px; +` + +export const Tournament = styled.div` + display: flex; + font-weight: 500; + font-size: 12px; + line-height: 16px; + align-self: flex-end; + margin-left: 48px; + color: #666666; +` diff --git a/src/features/MatchPage/hooks.tsx b/src/features/MatchPage/hooks.tsx new file mode 100644 index 00000000..14f9efe9 --- /dev/null +++ b/src/features/MatchPage/hooks.tsx @@ -0,0 +1,53 @@ +import { useEffect, useState } from 'react' + +import type { MatchInfo } from 'requests' +import { getMatchInfo } from 'requests' + +import { useHeaderFiltersStore } from 'features/HeaderFilters' +import { useLexicsStore } from 'features/LexicsStore' + +import { useSportNameParam, usePageId } from 'hooks' + +type Name = 'name_rus' | 'name_eng' + +export const useMatchPage = () => { + const [matchProfile, setMatchProfile] = useState(null) + const { sportType } = useSportNameParam() + const pageId = usePageId() + const { suffix } = useLexicsStore() + + const { + setSelectedSportTypeId, + setSelectedTournamentId, + } = useHeaderFiltersStore() + + const matchProfileNames = { + team1Name: matchProfile?.team1[`name_${suffix}` as Name], + team2Name: matchProfile?.team2[`name_${suffix}` as Name], + tournament: matchProfile?.tournament[`name_${suffix}` as Name], + } + + useEffect(() => { + setSelectedSportTypeId(sportType) + setSelectedTournamentId(pageId) + + getMatchInfo(sportType, pageId) + .then(setMatchProfile) + + return () => { + setSelectedSportTypeId(null) + setSelectedTournamentId(null) + } + }, + [ + sportType, + pageId, + setSelectedSportTypeId, + setSelectedTournamentId, + ]) + + return { + matchProfile, + matchProfileNames, + } +} diff --git a/src/features/MatchPage/index.tsx b/src/features/MatchPage/index.tsx index 8892f025..f3f9b1a2 100644 --- a/src/features/MatchPage/index.tsx +++ b/src/features/MatchPage/index.tsx @@ -1,11 +1,17 @@ import React from 'react' -import styled from 'styled-components' -const TempPageTitle = styled.span` - padding: 20px; - font-size: 20px; - color: white; -` +import { UserFavoritesStore } from 'features/UserFavorites/store' + +import { MatchProfileCard } from './MatchProfileCard' + +import { + MainWrapper, +} from './styled' + export const MatchPage = () => ( - MATCH PAGE! + + + + + ) diff --git a/src/features/MatchPage/styled.tsx b/src/features/MatchPage/styled.tsx new file mode 100644 index 00000000..75cdf835 --- /dev/null +++ b/src/features/MatchPage/styled.tsx @@ -0,0 +1,6 @@ +import styled from 'styled-components/macro' + +export const MainWrapper = styled.div` + margin-left: 18px; + margin-top: 63px; +` diff --git a/src/features/Menu/index.tsx b/src/features/Menu/index.tsx index ab93a73d..15c6b1cc 100644 --- a/src/features/Menu/index.tsx +++ b/src/features/Menu/index.tsx @@ -2,6 +2,7 @@ import React from 'react' import { PAGES } from 'config' import { useToggle } from 'hooks' + import { useAuthStore } from 'features/AuthStore' import { T9n } from 'features/T9n' import { OutsideClick } from 'features/OutsideClick' diff --git a/src/features/OutsideClick/index.tsx b/src/features/OutsideClick/index.tsx index 030bba15..822cb023 100644 --- a/src/features/OutsideClick/index.tsx +++ b/src/features/OutsideClick/index.tsx @@ -8,24 +8,20 @@ import { useOutsideClickEffect } from './hooks' type Props = { /** элемент, которому необходим функционал `OutsideClick` */ children: ReactNode, - fullSize?: boolean, /** функция-коллбек, отрабатывающая по клику вне области элемента */ onClick: () => void, } -const OutsideClickWrapper = styled.div<{fullSize?:boolean}>` - width: ${({ fullSize }) => (fullSize ? '100%' : 'auto')} -` +const OutsideClickWrapper = styled.div`` export const OutsideClick = ({ children, - fullSize, onClick, }: Props) => { const wrapperRef = useOutsideClickEffect({ onClick }) return ( - + {children} ) diff --git a/src/features/ProfileCard/styled.tsx b/src/features/ProfileCard/styled.tsx index 3be8c045..d08205a9 100644 --- a/src/features/ProfileCard/styled.tsx +++ b/src/features/ProfileCard/styled.tsx @@ -22,7 +22,7 @@ export const Logo = styled.img<{ profileType: number }>` height: 88px; margin-right: 15px; border-radius: ${({ profileType }) => ( - profileType === ProfileTypes.TOURNAMENTS ? '0' : '50%' + profileType === ProfileTypes.PLAYERS ? '50%' : '0' )}; ` diff --git a/src/features/Search/index.tsx b/src/features/Search/index.tsx index b412f739..caabb9f1 100644 --- a/src/features/Search/index.tsx +++ b/src/features/Search/index.tsx @@ -29,7 +29,7 @@ export const Search = () => { } = useSearch() return ( - +
{ + const [teamProfile, setTeamProfile] = useState(null) const { sportType } = useSportNameParam() const teamId = usePageId() + const { suffix } = useLexicsStore() const { setSelectedSportTypeId, setTeamId, } = useHeaderFiltersStore() + const { + [`name_${suffix}` as Name]: name = '', + } = teamProfile || {} + + const { + [`name_${suffix}` as Name]: country = '', + } = teamProfile?.country || {} + useEffect(() => { setSelectedSportTypeId(sportType) setTeamId(teamId) + getTeamInfo(sportType, teamId) + .then(setTeamProfile) + return () => { setSelectedSportTypeId(null) setTeamId(null) } - }, [ - setSelectedSportTypeId, - setTeamId, + }, + [ sportType, teamId, + setSelectedSportTypeId, + setTeamId, ]) + + return { + infoItems: [country], + name, + sportType, + } } diff --git a/src/features/TeamPage/index.tsx b/src/features/TeamPage/index.tsx index a0c6bb7a..2dd31553 100644 --- a/src/features/TeamPage/index.tsx +++ b/src/features/TeamPage/index.tsx @@ -1,19 +1,30 @@ import React from 'react' +import { ProfileTypes } from 'config' + import { UserFavorites } from 'features/UserFavorites' -import { Matches } from 'features/Matches' +import { ProfileCard } from 'features/ProfileCard' import { UserFavoritesStore } from 'features/UserFavorites/store' +import { Matches } from 'features/Matches' import { useTeamPage } from './hooks' import { Content } from './styled' export const TeamPage = () => { - useTeamPage() + const { + infoItems, + name, + } = useTeamPage() return ( + diff --git a/src/features/TournamentPage/hooks.tsx b/src/features/TournamentPage/hooks.tsx index 6be5caab..550343e5 100644 --- a/src/features/TournamentPage/hooks.tsx +++ b/src/features/TournamentPage/hooks.tsx @@ -31,19 +31,22 @@ export const useTournamentPage = () => { } = tournamentProfile?.country || {} useEffect(() => { - getTournamentInfo(sportType, pageId) - .then(setTournamentProfile) setSelectedSportTypeId(sportType) setSelectedTournamentId(pageId) + getTournamentInfo(sportType, pageId) + .then(setTournamentProfile) + return () => { setSelectedSportTypeId(null) setSelectedTournamentId(null) } - }, [pageId, + }, + [ + sportType, + pageId, setSelectedSportTypeId, setSelectedTournamentId, - sportType, ]) return { diff --git a/src/requests/getMatchInfo.tsx b/src/requests/getMatchInfo.tsx new file mode 100644 index 00000000..ca845319 --- /dev/null +++ b/src/requests/getMatchInfo.tsx @@ -0,0 +1,47 @@ +import { + DATA_URL, + PROCEDURES, +} from 'config' + +import { callApi, getResponseData } from 'helpers' + +import { MatchStatuses } from 'features/HeaderFilters' + +const proc = PROCEDURES.get_match_info + +type Team = { + id: number, + name_eng: string, + name_rus: string, + score: number, +} + +export type MatchInfo = { + date: Date, + stream_status: MatchStatuses, + team1: Team, + team2: Team, + tournament: { + id: number, + name_eng: string, + name_rus: string, + }, +} | null + +export const getMatchInfo = (sportId: number, matchId: number) +: Promise => { + const config = { + body: { + params: { + _p_match_id: matchId, + _p_sport: sportId, + }, + proc, + }, + } + + return callApi({ + config, + url: DATA_URL, + }).then(getResponseData(proc)) +} diff --git a/src/requests/getSportTournaments.tsx b/src/requests/getSportTournaments.tsx index 21fb41c8..1e411c91 100644 --- a/src/requests/getSportTournaments.tsx +++ b/src/requests/getSportTournaments.tsx @@ -27,10 +27,15 @@ export type Tournament = { export type Tournaments = Array -export const getSportTournaments = (sportId: number | null): Promise => { +export const getSportTournaments = ( + sportId?: number | null, + offset: number = 0, +): Promise => { const config = { body: { params: { + _p_limit: 20, + _p_offset: offset, _p_sport: sportId, }, proc, diff --git a/src/requests/getTeamInfo.tsx b/src/requests/getTeamInfo.tsx new file mode 100644 index 00000000..4744d5b6 --- /dev/null +++ b/src/requests/getTeamInfo.tsx @@ -0,0 +1,40 @@ +import { + DATA_URL, + PROCEDURES, +} from 'config' + +import { callApi, getResponseData } from 'helpers' + +const proc = PROCEDURES.get_team_info + +export type TeamInfo = { + country: { + id: number, + name_eng: string, + name_rus: string, + }, + id: number, + is_favorite: boolean, + name_eng: string, + name_rus: string, + short_name_eng: string, + short_name_rus: string, +} | null + +export const getTeamInfo = (sportId: number, teamId: number) +: Promise => { + const config = { + body: { + params: { + _p_sport: sportId, + _p_team_id: teamId, + }, + proc, + }, + } + + return callApi({ + config, + url: DATA_URL, + }).then(getResponseData(proc)) +} diff --git a/src/requests/index.tsx b/src/requests/index.tsx index 9775005a..a9cf5472 100644 --- a/src/requests/index.tsx +++ b/src/requests/index.tsx @@ -10,3 +10,5 @@ export * from './getUserSportFavs' export * from './modifyUserSportFavs' export * from './getSportTournaments' export * from './getTournamentInfo' +export * from './getTeamInfo' +export * from './getMatchInfo'