diff --git a/src/config/procedures.tsx b/src/config/procedures.tsx index 5f571f51..4df235fa 100644 --- a/src/config/procedures.tsx +++ b/src/config/procedures.tsx @@ -5,6 +5,7 @@ export const PROCEDURES = { get_matches: 'get_matches', get_players_teams_tournaments: 'get_players_teams_tournaments', get_sport_list: 'get_sport_list', + get_tournament_list: 'get_tournament_list', get_user_favorites: 'get_user_favorites', logout_user: 'logout_user', lst_c_country: 'lst_c_country', diff --git a/src/features/HeaderFilters/components/SportTypeFilter/hooks.tsx b/src/features/HeaderFilters/components/SportTypeFilter/hooks.tsx index e9f804bd..599c18a4 100644 --- a/src/features/HeaderFilters/components/SportTypeFilter/hooks.tsx +++ b/src/features/HeaderFilters/components/SportTypeFilter/hooks.tsx @@ -12,7 +12,10 @@ import { CustomOption } from './styled' export const useSportTypeFilter = () => { const [sportList, setSportList] = useState([]) - const { setSelectedSportTypes } = useHeaderFiltersStore() + const { + setSelectedSportTypes, + setSelectedTournamentId, + } = useHeaderFiltersStore() const { translate, @@ -35,6 +38,7 @@ export const useSportTypeFilter = () => { const onSelect = (option: Option | null) => { if (option) { setSelectedSportTypes(option.id) + setSelectedTournamentId(null) } } diff --git a/src/features/HeaderFilters/components/TournamentFilter/helpers.tsx b/src/features/HeaderFilters/components/TournamentFilter/helpers.tsx new file mode 100644 index 00000000..8ac0b699 --- /dev/null +++ b/src/features/HeaderFilters/components/TournamentFilter/helpers.tsx @@ -0,0 +1,35 @@ +import map from 'lodash/map' + +import type { Tournaments } from 'requests' + +import { LOGOS_FALLBACKS } from 'config' +import { getLogo, SPORT_TYPES } from 'helpers' + +type Name = 'name_rus' | 'name_eng' +type ShortName = 'short_name_rus' | 'short_name_eng' + +export const normalizeTournaments = (tournaments: Tournaments, suffix: string) => ( + map(tournaments, (tournament) => { + const { c_sport, id } = tournament + const sportType = SPORT_TYPES[c_sport] + const name = tournament[`name_${suffix}` as Name] + const shortName = tournament[`short_name_${suffix}` as ShortName] || name + const country = tournament.country?.[`name_${suffix}` as Name] + + const logo = getLogo({ + id, + sportType, + type: 'tournaments', + }) + + return { + country, + fallbackImage: LOGOS_FALLBACKS[sportType].tournaments, + id, + logo, + name, + shortName, + sportType, + } + }) +) diff --git a/src/features/HeaderFilters/components/TournamentFilter/hooks.tsx b/src/features/HeaderFilters/components/TournamentFilter/hooks.tsx new file mode 100644 index 00000000..f1695862 --- /dev/null +++ b/src/features/HeaderFilters/components/TournamentFilter/hooks.tsx @@ -0,0 +1,58 @@ +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' +import { useLexicsStore } from 'features/LexicsStore' + +import { normalizeTournaments } from './helpers' + +const useTournamentsList = () => { + const { selectedSportType } = useHeaderFiltersStore() + const [list, setList] = useState([]) + + useEffect(() => { + setList([]) + getSportTournaments(selectedSportType).then(setList) + }, [selectedSportType]) + + return list +} + +export const useTournamentFilter = () => { + const { suffix } = useLexicsStore() + const { + selectedTournamentId, + setSelectedTournamentId, + } = useHeaderFiltersStore() + const { + close, + isOpen, + open, + } = useToggle() + const tournamentList = useTournamentsList() + const tournaments = normalizeTournaments(tournamentList, suffix) + const selectedTournament = find( + tournaments, + (tournament) => tournament.id === selectedTournamentId, + ) + + const onTournamentSelect = (tournamentId: number) => { + setSelectedTournamentId(tournamentId) + close() + } + + return { + close, + isOpen, + onTournamentSelect, + open, + selectedTournament, + tournaments, + } +} diff --git a/src/features/HeaderFilters/components/TournamentFilter/index.tsx b/src/features/HeaderFilters/components/TournamentFilter/index.tsx index 5fb26473..1ff1a31f 100644 --- a/src/features/HeaderFilters/components/TournamentFilter/index.tsx +++ b/src/features/HeaderFilters/components/TournamentFilter/index.tsx @@ -1,5 +1,51 @@ import React from 'react' -import { Wrapper } from './styled' +import { T9n } from 'features/T9n' +import { OutsideClick } from 'features/OutsideClick' -export const TournamentFilter = () => +import { TournamentList } from '../TournamentList' +import { useTournamentFilter } from './hooks' +import { + Wrapper, + ListWrapper, + DropdownButton, + ButtonTitle, + Arrows, +} from './styled' + +export const TournamentFilter = () => { + const { + close, + isOpen, + onTournamentSelect, + open, + selectedTournament, + tournaments, + } = useTournamentFilter() + return ( + + + + { + selectedTournament + ? selectedTournament.shortName + : + } + + + + { + isOpen && ( + + + + + + ) + } + + ) +} diff --git a/src/features/HeaderFilters/components/TournamentFilter/styled.tsx b/src/features/HeaderFilters/components/TournamentFilter/styled.tsx index 8646cd0a..a2d41a4b 100644 --- a/src/features/HeaderFilters/components/TournamentFilter/styled.tsx +++ b/src/features/HeaderFilters/components/TournamentFilter/styled.tsx @@ -1,3 +1,84 @@ import styled from 'styled-components/macro' -export const Wrapper = styled.div`` +import { сustomScrollbar } from 'features/Common' + +export const Wrapper = styled.div` + height: 100%; + width: 50%; + position: relative; +` + +export const ListWrapper = styled.div` + position: absolute; + left: -100%; + top: calc(100% + 8px); + width: 448px; + height: 456px; + overflow-y: scroll; + + ${сustomScrollbar} +` + +type Props = { + active?: boolean, +} + +export const DropdownButton = styled.button` + position: relative; + height: 100%; + width: 100%; + outline: none; + border: none; + display: flex; + align-items: center; + background-color: #3F3F3F; + font-weight: 600; + font-size: 18px; + cursor: pointer; + border-left: 1px solid #222222; + border-top-right-radius: 2px; + border-bottom-right-radius: 2px; + background-size: 12px 12px; + background-repeat: no-repeat; + background-position: 113px; + + ${({ active }) => ( + active + ? ` + background-color: #666666; + color: #fff; + ` + : ` + color: #999999; + + :hover { + background-color: #484848; + } + ` + )} +` + +export const ButtonTitle = styled.span` + display: inline-block; + width: 80%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + line-height: normal; +` + +export const Arrows = styled.span` + position: absolute; + right: 19px; + display: inline-block; + width: 12px; + height: 12px; + background-repeat: no-repeat; + background-position: center; + + ${({ active }) => ( + active + ? 'background-image: url(/images/arrowUp.svg);' + : 'background-image: url(/images/arrowDown.svg);' + )} +` diff --git a/src/features/HeaderFilters/components/TournamentList/index.tsx b/src/features/HeaderFilters/components/TournamentList/index.tsx new file mode 100644 index 00000000..0e31c466 --- /dev/null +++ b/src/features/HeaderFilters/components/TournamentList/index.tsx @@ -0,0 +1,71 @@ +import React from 'react' + +import map from 'lodash/map' + +import { SPORT_COLORS } from 'config' +import type { SportType } from 'features/Search/config' + +import { useItemsList } from 'features/ItemsList/hooks' +import { + Logo, + LogoWrapper, + ItemInfo, + Name, + SportName, + TeamOrCountry, + Wrapper, +} from 'features/ItemsList/styled' + +import { ListItem } from './styled' + +type Tournament = { + country?: string, + fallbackImage: string, + id: number, + logo: string, + name: string, + sportType: SportType, +} + +type TournamentListProps = { + onSelect: (id: number) => void, + tournaments: Array, +} + +export const TournamentList = ({ onSelect, tournaments }: TournamentListProps) => { + const { + onError, + ref, + } = useItemsList() + + return ( + + {map(tournaments, ({ + country, + fallbackImage, + id, + logo, + name, + sportType, + }) => ( + onSelect(id)}> + + + + + {name} + + {country} + + + ))} + + ) +} diff --git a/src/features/HeaderFilters/components/TournamentList/styled.tsx b/src/features/HeaderFilters/components/TournamentList/styled.tsx new file mode 100644 index 00000000..eaa39e8f --- /dev/null +++ b/src/features/HeaderFilters/components/TournamentList/styled.tsx @@ -0,0 +1,22 @@ +import styled from 'styled-components/macro' + +import { Item } from 'features/ItemsList/styled' + +export const ListItem = styled(Item)` + display: flex; + align-items: center; + width: 100%; + height: 56px; + background-color: #666; + cursor: pointer; + + :focus-within, + :hover { + background-color: #999; + outline: none; + } + + :focus { + background-color: #999; + } +` diff --git a/src/features/HeaderFilters/store/hooks/index.tsx b/src/features/HeaderFilters/store/hooks/index.tsx index ee900041..013f8f13 100644 --- a/src/features/HeaderFilters/store/hooks/index.tsx +++ b/src/features/HeaderFilters/store/hooks/index.tsx @@ -11,8 +11,6 @@ import startOfDay from 'date-fns/startOfDay' import { getMatches } from 'requests' -import { useTournaments } from './useTournaments' - export enum MatchStatuses { Live = 1, Finished = 2, @@ -31,23 +29,26 @@ export const useFilters = () => { const [selectedDate, setSelectedDate] = useState(new Date()) const [selectedMatchStatus, setSelectedMatchStatus] = useState(MatchStatuses.Live) const [selectedSportType, setSelectedSportTypes] = useState(SportTypes.Football) - const tournaments = useTournaments() + const [selectedTournamentId, setSelectedTournamentId] = useState(null) const fetchMatches = useCallback(debounce(getMatches, 300), []) // временно здесь запрашиваются матчи при изменении фильтров, // можно эту логику вырезать и вставить в компонент матчей useEffect(() => { + if (!selectedTournamentId) return + const formattedDate = format(startOfDay(selectedDate), dateFormat) fetchMatches({ date: formattedDate, matchStatus: selectedMatchStatus, sportType: selectedSportType, - tournamentId: 8, + tournamentId: selectedTournamentId, }) }, [ selectedDate, selectedMatchStatus, selectedSportType, + selectedTournamentId, fetchMatches, ]) @@ -55,15 +56,18 @@ export const useFilters = () => { selectedDate, selectedMatchStatus, selectedSportType, + selectedTournamentId, setSelectedDate, setSelectedMatchStatus, setSelectedSportTypes, - tournaments, + setSelectedTournamentId, }), [ selectedDate, selectedMatchStatus, selectedSportType, - tournaments, + selectedTournamentId, + setSelectedTournamentId, ]) + return store } diff --git a/src/features/HeaderFilters/store/hooks/useTournaments.tsx b/src/features/HeaderFilters/store/hooks/useTournaments.tsx deleted file mode 100644 index f485bd3b..00000000 --- a/src/features/HeaderFilters/store/hooks/useTournaments.tsx +++ /dev/null @@ -1,14 +0,0 @@ -type TournamentOption = {} - -type Tournaments = { - options: Array, - selected: TournamentOption | null, -} - -const initialState: Tournaments = { - options: [], - selected: null, -} - -// доделаем на таске по турнирам -export const useTournaments = () => initialState diff --git a/src/features/HomePage/styled.tsx b/src/features/HomePage/styled.tsx index 1ab3db47..8996f49b 100644 --- a/src/features/HomePage/styled.tsx +++ b/src/features/HomePage/styled.tsx @@ -4,4 +4,5 @@ export const FilterWrapper = styled.div` width: 288px; height: 48px; margin-right: 16px; + display: flex; ` diff --git a/src/requests/getSportTournaments.tsx b/src/requests/getSportTournaments.tsx new file mode 100644 index 00000000..8856307f --- /dev/null +++ b/src/requests/getSportTournaments.tsx @@ -0,0 +1,41 @@ +import { DATA_URL, PROCEDURES } from 'config' +import { callApi, getResponseData } from 'helpers' +import { SportTypes } from 'features/HeaderFilters' + +const proc = PROCEDURES.get_tournament_list + +type Country = { + id: number, + name_eng: string, + name_rus: string, +} + +export type Tournament = { + c_gender: number | null, + c_sport: SportTypes, + c_tournament_type: number, + country: Country, + id: number, + name_eng: string, + name_rus: string, + short_name_eng: string | null, + short_name_rus: string | null, +} + +export type Tournaments = Array + +export const getSportTournaments = (sportId: number): Promise => { + const config = { + body: { + params: { + _p_sport: sportId, + }, + proc, + }, + } + + return callApi({ + config, + url: DATA_URL, + }).then(getResponseData(proc)) +} diff --git a/src/requests/index.tsx b/src/requests/index.tsx index 7e65e875..316661af 100644 --- a/src/requests/index.tsx +++ b/src/requests/index.tsx @@ -8,3 +8,4 @@ export * from './getSearchItems' export * from './getMatches' export * from './getUserSportFavs' export * from './modifyUserSportFavs' +export * from './getSportTournaments'