diff --git a/src/components/SelectFilter/index.tsx b/src/components/SelectFilter/index.tsx index 435a53d3..8f24c661 100644 --- a/src/components/SelectFilter/index.tsx +++ b/src/components/SelectFilter/index.tsx @@ -11,7 +11,7 @@ import { type SportsFilterProps = { onModalOpen?: () => void, open: boolean, - selectItem: TournamentType | undefined, + selectItem: TournamentType | null, withArrow?: boolean, } diff --git a/src/components/SelectFilter/styled.tsx b/src/components/SelectFilter/styled.tsx index c926476d..981ebf5d 100644 --- a/src/components/SelectFilter/styled.tsx +++ b/src/components/SelectFilter/styled.tsx @@ -4,14 +4,12 @@ import { isMobileDevice } from 'config/userAgent' import { Icon } from 'features/Icon' export const ScSelectFilter = styled.div` - display: flex; color: white; - font-size: 14px; - width: auto; text-transform: uppercase; font-weight: 700; - align-items: center; - cursor: pointer; + font-size: 18px; + line-height: 22px; + white-space: nowrap; ${isMobileDevice ? css` diff --git a/src/features/HeaderFilters/components/DateFilter/hooks/index.tsx b/src/features/HeaderFilters/components/DateFilter/hooks/index.tsx index e462d1a2..8ef7b9a2 100644 --- a/src/features/HeaderFilters/components/DateFilter/hooks/index.tsx +++ b/src/features/HeaderFilters/components/DateFilter/hooks/index.tsx @@ -24,7 +24,7 @@ export const useDateFilter = () => { setSelectedDate, setSelectedFilters, setSelectedLeague, - setSelectTournament, + setSelectedTournament, } = useHeaderFiltersStore() const { lang } = useLexicsStore() @@ -52,10 +52,11 @@ export const useDateFilter = () => { && parseFilters.selectedLeague[0] !== 'all_competitions') { setIsShowTournament(false) setSelectedLeague(parseFilters.selectedLeague) - setSelectTournament(parseFilters.selectTournament) + setSelectedTournament(parseFilters.selectedTournament) } else { setIsShowTournament(true) setSelectedFilters([]) + setSelectedTournament(null) setSelectedLeague(['all_competitions']) } // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/src/features/HeaderFilters/store/hooks/index.tsx b/src/features/HeaderFilters/store/hooks/index.tsx index 27f7b4c9..87ac6009 100644 --- a/src/features/HeaderFilters/store/hooks/index.tsx +++ b/src/features/HeaderFilters/store/hooks/index.tsx @@ -23,6 +23,14 @@ export const useFilters = () => { key: filterKeys.DATE, validator: isValidDate, }) + const [selectedSport, setSelectedSport] = useState(['all_sports']) + const [selectedLeague, setSelectedLeague] = useState>(['all_competitions']) + const [selectedFilters, setSelectedFilters] = useState>([]) + const [isShowTournament, setIsShowTournament] = useState(true) + const [selectedTournament, setSelectedTournament] = useState(null) + const [sportIds, setSportIds] = useState() + const isTodaySelected = isToday(selectedDate) + const { activeFilters, changeInput, @@ -33,24 +41,22 @@ export const useFilters = () => { closeDropdownList, confirmClear, currentFilters, - filtersList, + filtersListName, filtersSize, + getDropdownList, handleSetFilters, inputValue, isEmptyFilters, - isOpenList, - openDropdownList, + isFiltersShown, + matchesList, openPopup, queryParams, - setFilters, - } = useMatchFilters(selectedDate) - const [selectedSport, setSelectedSport] = useState(['all_sports']) - const [selectedLeague, setSelectedLeague] = useState>(['all_competitions']) - const [selectedFilters, setSelectedFilters] = useState>([]) - const [isShowTournament, setIsShowTournament] = useState(true) - const [selectTournament, setSelectTournament] = useState() - const [sportIds, setSportIds] = useState() - const isTodaySelected = isToday(selectedDate) + setTournamentMatches, + toggleDropdownList, + } = useMatchFilters({ + selectedDate, + selectedTournament, + }) const resetFilters = useCallback(() => { setIsShowTournament(true) @@ -64,9 +70,9 @@ export const useFilters = () => { useEffect(() => { localStorage.setItem('filters', JSON.stringify({ - selectTournament, selectedDate: selectedDate.getDate(), selectedLeague, + selectedTournament, })) // eslint-disable-next-line }, [selectedLeague]) @@ -81,6 +87,20 @@ export const useFilters = () => { search, ]) + const handleClickBack = useCallback(() => { + setTournamentMatches([]) + clearAllFilters() + setIsShowTournament(true) + setSelectedTournament(null) + setSelectedLeague(['all_competitions']) + }, [ + clearAllFilters, + setTournamentMatches, + setIsShowTournament, + setSelectedTournament, + setSelectedLeague, + ]) + const store = useMemo(() => ({ activeFilters, changeInput, @@ -91,69 +111,73 @@ export const useFilters = () => { closeDropdownList, confirmClear, currentFilters, - filtersList, + filtersListName, filtersSize, + getDropdownList, + handleClickBack, handleSetFilters, inputValue, isEmptyFilters, - isOpenList, + isFiltersShown, isShowTournament, isTodaySelected, - openDropdownList, + matchesList, openPopup, queryParams, resetFilters, - selectTournament, selectedDate, selectedFilters, selectedLeague, selectedSport, - setFilters, + selectedTournament, setIsShowTournament, - setSelectTournament, setSelectedDate, setSelectedFilters, setSelectedLeague, setSelectedSport, + setSelectedTournament, setSportIds, sportIds, + toggleDropdownList, updateDate, }), [ activeFilters, - clickCancel, - clickClearAll, - confirmClear, changeInput, clearAllFilters, clearFilters, + clickCancel, + clickClearAll, closeDropdownList, + confirmClear, currentFilters, - filtersList, + filtersListName, filtersSize, + getDropdownList, + handleClickBack, handleSetFilters, inputValue, isEmptyFilters, - isOpenList, + isFiltersShown, isShowTournament, isTodaySelected, + matchesList, openPopup, - openDropdownList, queryParams, resetFilters, - selectTournament, selectedDate, selectedFilters, selectedLeague, selectedSport, - setFilters, + selectedTournament, setIsShowTournament, - setSelectTournament, setSelectedDate, setSelectedFilters, setSelectedLeague, setSelectedSport, + setSelectedTournament, setSportIds, sportIds, + toggleDropdownList, updateDate, ]) diff --git a/src/features/HeaderFilters/store/hooks/useMatchFilters.tsx b/src/features/HeaderFilters/store/hooks/useMatchFilters.tsx index 3455c590..27add7eb 100644 --- a/src/features/HeaderFilters/store/hooks/useMatchFilters.tsx +++ b/src/features/HeaderFilters/store/hooks/useMatchFilters.tsx @@ -6,22 +6,37 @@ import { MouseEvent, ChangeEvent, } from 'react' + +import every from 'lodash/every' import some from 'lodash/some' import isNil from 'lodash/isNil' import includes from 'lodash/includes' import filter from 'lodash/filter' import isEmpty from 'lodash/isEmpty' -import map from 'lodash/map' import reduce from 'lodash/reduce' import size from 'lodash/size' import { format } from 'date-fns' +import { + getAge, + getArena, + getDivision, + getGender, + getMainTeam, + getRound, + getSport, +} from 'features/HomePage/components/Dropdown/helpers' + import { getHomeMatches, Match, TQueryParams, } from 'requests' +import type { TournamentType } from 'requests/getMatches/types' + +const MATCHES_LIMIT = 1000 +const OFFSET = 0 const getTimezoneOffset = (date: Date) => { const offset = date.getTimezoneOffset() @@ -31,37 +46,52 @@ const getTimezoneOffset = (date: Date) => { const getDate = (date: Date) => format(date, 'yyyy-MM-dd') export type TActiveFilters = { - arena?: Array, - division?: Array, - gender?: Array, - main_team?: Array, - round?: Array, - youth_age?: Array, + [key: string]: Array, } + export type TDefaultType = { id: number, name_eng: string, name_rus: string, } -export const useMatchFilters = (selectedDate: Date) => { - const [filtersList, setFiltersList] = useState>() - const [isOpenList, setOpenList] = useState('') - const [activeFilters, setActiveFilters] = useState({}) +type TUseMatchFilters = { + selectedDate: Date, + selectedTournament: TournamentType | null, +} + +const DEFAULT_FILTERS = {} + +export const useMatchFilters = ({ + selectedDate, + selectedTournament, +}: TUseMatchFilters) => { + const [matchesList, setMatchesList] = useState>([]) + const [tournamentMatches, setTournamentMatches] = useState>([]) + const [filtersListName, setFiltersListName] = useState('') + const [activeFilters, setActiveFilters] = useState(DEFAULT_FILTERS) const [inputValue, setInputValue] = useState('') const [openPopup, setOpenPopup] = useState(false) - const setFilters = (filters: Array) => { - setFiltersList(filters) + const toggleDropdownList = (title: string) => () => { + if (title === filtersListName) { + setFiltersListName('') + setInputValue('') + } else { + setFiltersListName(title) + } } - const openDropdownList = (title: string) => () => { - setOpenList(title === isOpenList ? '' : title) + const closeDropdownList = () => { + setFiltersListName('') + setInputValue('') } - const closeDropdownList = () => { - setOpenList('') + const clearAllFilters = () => { + setInputValue('') + setActiveFilters(DEFAULT_FILTERS) } + const fetchMatches = useCallback( (limit: number, offset: number) => getHomeMatches({ date: getDate(selectedDate), @@ -73,36 +103,101 @@ export const useMatchFilters = (selectedDate: Date) => { ) useEffect(() => { - fetchMatches(1000, 0).then((resp) => setFiltersList(resp.broadcast)) - // eslint-disable-next-line react-hooks/exhaustive-deps + clearAllFilters() + setMatchesList([]) + setTournamentMatches([]) + + fetchMatches(MATCHES_LIMIT, OFFSET).then(({ broadcast }) => { + setMatchesList(broadcast) + }) + // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedDate]) + useEffect(() => { + if (selectedTournament) { + setTournamentMatches( + filter(matchesList, + (match) => match.tournament.id === selectedTournament.id), + ) + } + }, [ + matchesList, + selectedTournament, + ]) + + const matchesForFilters = useMemo(() => ( + selectedTournament ? tournamentMatches : matchesList), + [ + matchesList, + selectedTournament, + tournamentMatches, + ]) + + const getDropdownList = useCallback((filterName: string, queryString: string) => { + switch (filterName) { + case 'gender': + return getGender(matchesForFilters) + case 'youth_age': + return getAge(matchesForFilters) + case 'division': + return getDivision(matchesForFilters) + case 'main_team': + return getMainTeam(matchesForFilters) + case 'arena': + return getArena(matchesForFilters, queryString) + case 'round': + return getRound(matchesForFilters) + case 'sport': + return getSport(matchesForFilters) + default: + return [] + } + }, [matchesForFilters]) + const currentFilters = useMemo(() => { const arr = [] - if (some(filtersList, (item) => !isNil(item.arena?.id))) arr.push('arena') - if (some(filtersList, (item) => !isNil(item.round?.id))) arr.push('round') - if (some(filtersList, (item) => !isNil(item.team1?.main_team) || !isNil(item.team2?.main_team))) arr.push('main_team') - if (some(filtersList, (item) => !isNil(item.team1?.youth_age) || !isNil(item.team2?.youth_age))) arr.push('youth_age') - if (some(filtersList, (item) => !isNil(item.team1?.gender) || !isNil(item.team2?.gender))) arr.push('gender') - if (some(filtersList, (item) => !isNil(item.team1?.division?.id) || !isNil(item.team2?.division?.id))) arr.push('division') - return arr - }, [filtersList]) - - const handleSetFilters = (filterName: string, value: any) => { - const isFilterPresent = !isNil(activeFilters[filterName as keyof typeof activeFilters]) + + const hasArena = some(matchesForFilters, (item) => !isNil(item.arena?.id)) + const hasRound = some(matchesForFilters, (item) => !isNil(item.round?.id)) + const hasSport = some(matchesForFilters, (item) => !isNil(item.sport)) + const hasMainTeam = some(matchesForFilters, + (item) => !isNil(item.team1?.main_team) || !isNil(item.team2?.main_team)) + const hasGender = some(matchesForFilters, + (item) => !isNil(item.team1?.gender) || !isNil(item.team2?.gender)) + const hasDivision = some(matchesForFilters, + (item) => !isNil(item.team1?.division?.id) || !isNil(item.team2?.division?.id)) + const hasYouthAge = some(matchesForFilters, + (item) => !isNil(item.team1?.youth_age) || !isNil(item.team2?.youth_age)) + + if (hasSport) arr.push('sport') + if (hasArena) arr.push('arena') + if (hasRound) arr.push('round') + if (hasMainTeam) arr.push('main_team') + if (hasYouthAge) arr.push('youth_age') + if (hasGender) arr.push('gender') + if (hasDivision) arr.push('division') + + return filter(arr, (filterName) => ( + getDropdownList(filterName, '').length > 1 + )) + }, [getDropdownList, matchesForFilters]) + + const handleSetFilters = (filterName: string, value: number) => { + const activeFilter = activeFilters[filterName as keyof typeof activeFilters] + const isFilterPresent = !isNil(activeFilter) + if (isFilterPresent) { - const isValuePresent = includes( - activeFilters[filterName as keyof typeof activeFilters], value, - ) + const isValuePresent = includes(activeFilter, value) const currentValue = isValuePresent - ? filter(activeFilters[filterName as keyof typeof activeFilters], (item) => item !== value) - : [...activeFilters[filterName as keyof typeof activeFilters]!, value] + ? filter(activeFilter, (item) => item !== value) + : [...activeFilter, value] return setActiveFilters({ ...activeFilters, [filterName]: currentValue, }) } + return setActiveFilters({ ...activeFilters, [filterName]: [value], @@ -112,31 +207,31 @@ export const useMatchFilters = (selectedDate: Date) => { const clearFilters = (filterName: string) => (e: MouseEvent | ChangeEvent) => { e.stopPropagation() e.preventDefault() - return setActiveFilters({ + + if (filterName === 'arena') { + setInputValue('') + } + + setActiveFilters({ ...activeFilters, [filterName]: [], }) } - const clearAllFilters = (e: MouseEvent) => { - e.stopPropagation() - setActiveFilters({}) - } - - const isEmptyFilters = some(activeFilters, (filterItem) => isEmpty(filterItem)) - || isEmpty(activeFilters) + const isEmptyFilters = every(activeFilters, (filterItem) => isEmpty(filterItem)) const queryParams: TQueryParams = useMemo(() => { const params = { - arena: map(activeFilters.arena, (item) => item.id), - division: map(activeFilters.division, (item) => item.id), - gender: map(activeFilters.gender, (item) => item.id), - main_team: map(activeFilters.main_team, (item) => item.id), - round: map(activeFilters.round, (item) => item.id), + arena: activeFilters.arena, + division: activeFilters.division, + gender: activeFilters.gender, + main_team: activeFilters.main_team, + round: activeFilters.round, + sport: activeFilters.sport, youth_age: activeFilters.youth_age, } - return (params) + return params }, [activeFilters]) const changeInput = (e: ChangeEvent) => { @@ -150,7 +245,7 @@ export const useMatchFilters = (selectedDate: Date) => { const confirmClear = (e: MouseEvent) => { setOpenPopup(false) - clearAllFilters(e) + clearAllFilters() } const clickCancel = () => { @@ -158,8 +253,14 @@ export const useMatchFilters = (selectedDate: Date) => { } const filtersSize = reduce(activeFilters, - (result, - value) => result + size(value), 0) + ( + result, + value, + ) => result + size(value), 0) + + const isFiltersShown = useMemo(() => ( + size(matchesList) < 12 || selectedTournament), + [matchesList, selectedTournament]) return { activeFilters, @@ -171,15 +272,17 @@ export const useMatchFilters = (selectedDate: Date) => { closeDropdownList, confirmClear, currentFilters, - filtersList, + filtersListName, filtersSize, + getDropdownList, handleSetFilters, inputValue, isEmptyFilters, - isOpenList, - openDropdownList, + isFiltersShown, + matchesList, openPopup, queryParams, - setFilters, + setTournamentMatches, + toggleDropdownList, } } diff --git a/src/features/HeaderMobile/index.tsx b/src/features/HeaderMobile/index.tsx index 6076bce9..280063fc 100644 --- a/src/features/HeaderMobile/index.tsx +++ b/src/features/HeaderMobile/index.tsx @@ -1,16 +1,12 @@ -import { useRecoilValue } from 'recoil' - import { isIOS } from 'config/userAgent' -import { isLffClient } from 'config/clients' +import { isInSportsClient } from 'config/clients' import { HeaderMenu } from 'features/HeaderMenu' import { DateFilter } from 'features/HeaderFilters' import { ScoreSwitch } from 'features/MatchSwitches' -import { SportsFilter } from 'features/SportsFilter' -import { isSportFilterShownAtom } from 'features/HomePage/Atoms/HomePageAtoms' import { SmartBanner } from 'components/SmartBanner' +import { MobileMatchesFilters } from 'features/HomePage/components/MobileMatchesFilters' -import { MobileMathesFilters } from 'features/HomePage/components/MobileMatchesFilters' import { HeaderStyled, ScoreSwitchWrapper, @@ -22,31 +18,22 @@ type HeaderBannerProps = { setIsOpenDownload: (open: boolean) => void, } -export const HeaderMobile = ({ isOpenDownload, setIsOpenDownload }: HeaderBannerProps) => { - const isSportFilterShown = useRecoilValue(isSportFilterShownAtom) - - return ( - <> - { - isOpenDownload +export const HeaderMobile = ({ isOpenDownload, setIsOpenDownload }: HeaderBannerProps) => ( + <> + { + isOpenDownload && !isIOS && - } - - - - - {!isLffClient && isSportFilterShown ? ( - <> - - - - ) : null} - - - - - - - ) -} + } + + + + + {isInSportsClient && } + + + + + + +) diff --git a/src/features/HomePage/Atoms/HomePageAtoms.tsx b/src/features/HomePage/Atoms/HomePageAtoms.tsx deleted file mode 100644 index 9e65d944..00000000 --- a/src/features/HomePage/Atoms/HomePageAtoms.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { atom } from 'recoil' - -export const isSportFilterShownAtom = atom({ - default: true, - key: 'isSportFilterShownAtom', -}) diff --git a/src/features/HomePage/components/ClearFiltersPopup/index.tsx b/src/features/HomePage/components/ClearFiltersPopup/index.tsx index 3a510448..1c1ac54d 100644 --- a/src/features/HomePage/components/ClearFiltersPopup/index.tsx +++ b/src/features/HomePage/components/ClearFiltersPopup/index.tsx @@ -1,6 +1,6 @@ import { useHeaderFiltersStore } from 'features/HeaderFilters' import { T9n } from 'features/T9n' -import React from 'react' + import { ButtonsContainer, CancelButton, diff --git a/src/features/HomePage/components/ClearFiltersPopup/styled.tsx b/src/features/HomePage/components/ClearFiltersPopup/styled.tsx index 690d81cb..caebc2a2 100644 --- a/src/features/HomePage/components/ClearFiltersPopup/styled.tsx +++ b/src/features/HomePage/components/ClearFiltersPopup/styled.tsx @@ -1,113 +1,120 @@ import styled, { css } from 'styled-components/macro' import { ModalWindow } from 'features/Modal/styled' +import { OutsideClickWrapper } from 'features/OutsideClick' import { Modal as BaseModal, } from 'features/AuthServiceApp/components/RegisterPopup/styled' import { isMobileDevice } from 'config/userAgent' export const Modal = styled(BaseModal)` + ${OutsideClickWrapper} { + ${isMobileDevice + ? css`height: 100%;` + : ''} + } + ${ModalWindow} { ${isMobileDevice ? css` - min-height: 201px; - max-width: 351px; - padding: 26px 19px 33px 19px; + min-height: 201px; + max-width: 351px; + padding: 26px 15px 33px 15px; + top: 19vh; ` : css` - min-height: 220px; - max-width: 611px; - padding: 37px 0 39px 0; + min-height: 220px; + max-width: 611px; + padding: 37px 0 39px 0; `} } ` export const PopupContainer = styled.div` -display: flex; -flex-direction: column; -align-items: center; -justify-content: center; -font-style: normal; -color: #FFFFFF; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-style: normal; + color: #FFFFFF; -${isMobileDevice - ? css`` - : css` - min-width: 611px;`} + ${isMobileDevice + ? '' + : css`min-width: 611px;`} ` export const PopupTitle = styled.div` -font-weight: 700; -font-size: 24px; -line-height: 24px; -margin-bottom: 45px; -${isMobileDevice - ? css` - font-size: 20px; - line-height: 24px; - margin-bottom: 25px;` - : css` + font-weight: 700; font-size: 24px; line-height: 24px; - margin-bottom: 45px;`} + margin-bottom: 45px; + + ${isMobileDevice + ? css` + font-size: 20px; + line-height: 24px; + margin-bottom: 25px;` + : css` + font-size: 24px; + line-height: 24px; + margin-bottom: 45px;`} ` export const PopupText = styled.div` -font-weight: 400; + font-weight: 400; -${isMobileDevice + ${isMobileDevice ? css` - font-size: 16px; - line-height: 22px; -margin-bottom: 33px;` + font-size: 16px; + line-height: 22px; + margin-bottom: 33px;` : css` - font-size: 20px; - line-height: 28px; - margin-bottom: 55px;`} + font-size: 20px; + line-height: 28px; + margin-bottom: 55px;`} ` export const ButtonsContainer = styled.div` -display: flex; -flex-direction: row; -align-items: center; -${isMobileDevice - ? css` - gap: 15px;` - : css` - gap: 20px; - `} + display: flex; + flex-direction: row; + align-items: center; + + ${isMobileDevice + ? css`gap: 15px;` + : css`gap: 20px;`} ` const Button = styled.button` -display: flex; -flex-direction: row; -justify-content: center; -align-items: center; -border-radius: 5px; -color: #FFFF; -font-weight: 600; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + border-radius: 5px; + color: #FFFF; + font-weight: 600; -${isMobileDevice + ${isMobileDevice ? css` - font-size: 16px; -line-height: 16px; -width: 149px; -height: 38px;` + font-size: 16px; + line-height: 16px; + width: 149px; + height: 38px;` : css` - font-size: 20px; - line-height: 50px; - cursor: pointer; - width: 134px; - height: 50px;`} + font-size: 20px; + line-height: 50px; + cursor: pointer; + width: 134px; + height: 50px;`} ` export const ConfirmButton = styled(Button)` -background: #294FC4; -border: 1px solid #294FC4; -filter: drop-shadow(0px 1px 1px rgba(0, 0, 0, 0.3)); + background: #294FC4; + border: 1px solid #294FC4; + filter: drop-shadow(0px 1px 1px rgba(0, 0, 0, 0.3)); ` + export const CancelButton = styled(Button)` -border: 1px solid #FFFFFF; -background: none; -filter: drop-shadow(0px 1px 1px rgba(0, 0, 0, 0.3)); + border: 1px solid #FFFFFF; + background: none; + filter: drop-shadow(0px 1px 1px rgba(0, 0, 0, 0.3)); ` diff --git a/src/features/HomePage/components/Dropdown/Dropdown.tsx b/src/features/HomePage/components/Dropdown/Dropdown.tsx deleted file mode 100644 index 5ba084b7..00000000 --- a/src/features/HomePage/components/Dropdown/Dropdown.tsx +++ /dev/null @@ -1,160 +0,0 @@ -import React, { useMemo } from 'react' - -import map from 'lodash/map' -import isEmpty from 'lodash/isEmpty' -import includes from 'lodash/includes' - -import { T9n } from 'features/T9n' -import { Name } from 'features/Name' - -import { useLexicsStore } from 'features/LexicsStore' -import { isMobileDevice } from 'config/userAgent' -import { - getAge, - getArena, - getDivision, - getGender, - getMainTeam, - getRound, -} from './helpers' -import { - TDropDownProps, - TFilterItem, - TItem, -} from './types' -import { - DropDownContainer, - FiltersList, - FilterItem, - Checkbox, - CommonButtonsBlock, - ClearButtonContainer, - SearchWithAllContainer, - SearchContainer, - SearchInput, - BackButton, -} from './styled' - -const Label = ({ item }: TFilterItem) => { - const isNumber = typeof item === 'number' - - return ( - <> - {isNumber ? (<>U{item}) : ()} - - ) -} - -export const DropDown = ({ - activeFilters, - changeInput, - clearFilters, - closeDropdownList, - filterList, - filterTitle, - inputValue, - setFilters, -}: TDropDownProps) => { - const { translate } = useLexicsStore() - - const dropDownList = useMemo(() => { - switch (filterTitle) { - case 'gender': - return getGender(filterList) - case 'youth_age': - return getAge(filterList) - case 'division': - return getDivision(filterList) - case 'main_team': - return getMainTeam(filterList) - case 'arena': - return getArena(filterList, inputValue) - case 'round': - return getRound(filterList) - default: - return [] - } - }, [filterTitle, filterList, inputValue]) as Array | Array - - const currentActiveFilter = activeFilters[filterTitle as keyof typeof activeFilters] - - return ( - - - - - {/* {isMobileDevice && ()} */} - {isMobileDevice && closeDropdownList - && ( - - {filterTitle} - - )} - {filterTitle === 'arena' && ( - - e.stopPropagation()} - placeholder={translate('search')} - /> - - )} - - - - - - - - {!isEmpty(dropDownList) && map(dropDownList, (filterItem, i) => ( - <> - { - e.preventDefault() - e.stopPropagation() - setFilters(filterTitle, filterItem) - }} - > - {filterTitle === 'gender' - ? ( - { - e.preventDefault() - e.stopPropagation() - setFilters(filterTitle, filterItem) - }} - labelLexic={filterItem.title} - /> - ) - : ( - { - e.preventDefault() - e.stopPropagation() - setFilters(filterTitle, filterItem) - }} - label={( - - ))} - - - ) -} diff --git a/src/features/HomePage/components/Dropdown/helpers.tsx b/src/features/HomePage/components/Dropdown/helpers.tsx index caffc6fc..ec5415e0 100644 --- a/src/features/HomePage/components/Dropdown/helpers.tsx +++ b/src/features/HomePage/components/Dropdown/helpers.tsx @@ -2,16 +2,18 @@ import map from 'lodash/map' import some from 'lodash/some' import filter from 'lodash/filter' import uniq from 'lodash/uniq' +import uniqBy from 'lodash/uniqBy' import flatten from 'lodash/flatten' import compact from 'lodash/compact' -import startsWith from 'lodash/startsWith' +import includes from 'lodash/includes' import toLower from 'lodash/toLower' import { Match } from 'requests' -const checkStartString = (text: string, searchString: string) => startsWith( +const checkString = (text: string, searchString: string) => includes( toLower(text), toLower(searchString), ) + export const getAge = (filterList: Array) => compact( uniq( flatten( @@ -42,21 +44,31 @@ export const getArena = (filterList: Array, inputValue: string) => filter map( filterList, (item) => item.arena, ), (item) => item?.id - && (checkStartString(item.name_eng, inputValue) - || checkStartString(item.name_rus, inputValue)), + && (checkString(item.name_eng, inputValue) + || checkString(item.name_rus, inputValue)), ) -export const getRound = (filterList: Array) => filter( - map( - filterList, (item) => item.round, - ), (item) => item?.id, +export const getSport = (filterList: Array) => uniqBy( + filter( + map( + filterList, (item) => item.sport_info, + ), (item) => item?.id, + ), 'id', +) + +export const getRound = (filterList: Array) => uniqBy( + filter( + map( + filterList, (item) => item.round, + ), (item) => item?.id, + ), 'id', ) export const getGender = (filterList: Array) => { const list = [] - if (some(filterList, (item) => item.team1.gender === 1 || item.team2.gender === 1)) list.push({ id: 1, title: 'gender_male_long' }) - if (some(filterList, (item) => item.team1.gender === 2 || item.team2.gender === 2)) list.push({ id: 2, title: 'gender_female_long' }) + if (some(filterList, (item) => item.team1.gender === 1 || item.team2.gender === 1)) list.push({ id: 1, lexic: 'gender_male_long' }) + if (some(filterList, (item) => item.team1.gender === 2 || item.team2.gender === 2)) list.push({ id: 2, lexic: 'gender_female_long' }) return list } diff --git a/src/features/HomePage/components/Dropdown/index.tsx b/src/features/HomePage/components/Dropdown/index.tsx new file mode 100644 index 00000000..6116d5b0 --- /dev/null +++ b/src/features/HomePage/components/Dropdown/index.tsx @@ -0,0 +1,127 @@ +import { ChangeEvent, MouseEvent } from 'react' + +import map from 'lodash/map' +import isEmpty from 'lodash/isEmpty' +import includes from 'lodash/includes' +import isNumber from 'lodash/isNumber' + +import { T9n } from 'features/T9n' +import { Name } from 'features/Name' +import { useLexicsStore } from 'features/LexicsStore' +import { useHeaderFiltersStore } from 'features/HeaderFilters' + +import { isMobileDevice } from 'config/userAgent' + +import { + TDropDownProps, + TFilterItem, + TItem, +} from './types' +import { + DropDownContainer, + FiltersList, + FilterItem, + Checkbox, + CommonButtonsBlock, + ClearButtonContainer, + SearchWithAllContainer, + SearchContainer, + SearchInput, + BackButton, +} from './styled' +import { Title } from '../MatchesFilters/styled' + +const Label = ({ item }: TFilterItem) => ( + isNumber(item) ? <>U{item} : +) + +export const DropDown = ({ + activeFilters, + changeInput, + clearFilters, + closeDropdownList, + filterTitle, + inputValue, + setFilters, +}: TDropDownProps) => { + const { translate } = useLexicsStore() + const { getDropdownList } = useHeaderFiltersStore() + + const dropdownList = getDropdownList(filterTitle, inputValue) as Array + + const currentActiveFilter = activeFilters[filterTitle as keyof typeof activeFilters] + + return ( + + + + + {isMobileDevice && closeDropdownList + && ( + + {isMobileDevice && ()} + </BackButton> + )} + {filterTitle === 'arena' && ( + <SearchContainer> + <SearchInput + onChange={changeInput} + onClick={(e) => e.stopPropagation()} + placeholder={translate('search')} + value={inputValue} + /> + </SearchContainer> + )} + <Checkbox + onChange={clearFilters(filterTitle)} + checked={isEmpty(currentActiveFilter)} + labelLexic='all' + /> + </SearchWithAllContainer> + {!isEmpty(currentActiveFilter) && ( + <ClearButtonContainer + onClick={clearFilters(filterTitle)} + > + <T9n + className='clear_button' + t='clear' + /> + </ClearButtonContainer> + )} + </CommonButtonsBlock> + + {map(dropdownList, (filterItem) => { + const filterValue = isNumber(filterItem) ? filterItem : filterItem.id + const handleClick = (e: ChangeEvent | MouseEvent) => { + e.preventDefault() + e.stopPropagation() + setFilters(filterTitle, filterValue) + } + + return ( + <FilterItem + key={filterValue} + onClick={handleClick} + > + {includes(['gender', 'sport'], filterTitle) + ? ( + <Checkbox + checked={includes(currentActiveFilter, filterValue)} + onChange={handleClick} + labelLexic={!isNumber(filterItem) ? filterItem.lexic : ''} + /> + ) + : ( + <Checkbox + checked={includes(currentActiveFilter, filterValue)} + onChange={handleClick} + label={(<Label item={filterItem} />)} + /> + )} + </FilterItem> + ) + })} + </FiltersList> + </DropDownContainer> + ) +} diff --git a/src/features/HomePage/components/Dropdown/styled.tsx b/src/features/HomePage/components/Dropdown/styled.tsx index 4cff2a99..9817904a 100644 --- a/src/features/HomePage/components/Dropdown/styled.tsx +++ b/src/features/HomePage/components/Dropdown/styled.tsx @@ -1,4 +1,5 @@ import styled, { css } from 'styled-components/macro' + import { customScrollbar } from 'features/Common' import { Checkbox as BaseCheckbox } from 'features/Common/Checkbox' import { Label } from 'features/Common/Checkbox/styled' @@ -7,56 +8,67 @@ import { isMobileDevice } from 'config/userAgent' import { NameStyled } from 'features/Name' export const DropDownContainer = styled.div` -${isMobileDevice - ? css` - border-top: 1px solid #505050;` + ${isMobileDevice + ? css` border-top: 1px solid #505050;` : css` - position: absolute; - top: 57px; - right: -24px; - background: #333333; - border-radius: 3.5px; - z-index: 10;`} + position: absolute; + top: 57px; + right: -24px; + background: #333333; + border-radius: 3.5px; + z-index: 10;`} ` + export const FiltersList = styled.ul` -${customScrollbar} -overflow-y: auto; -display: flex; -flex-direction: column; -max-height: 500px; + overflow-y: auto; + display: flex; + flex-direction: column; + max-height: 500px; + + ${isMobileDevice + ? css` + @media (orientation: landscape){ + max-height: 300px; + } + ` + : ''} + + ${customScrollbar} ` -export const FilterItem = styled.li` -${isMobileDevice +export const FilterItem = styled.li` + ${isMobileDevice ? css` - max-width: 280px; - white-space: nowrap; - padding: 10px 0 10px 13px; - ` + max-width: 280px; + white-space: nowrap; + padding: 10px 0 10px 13px; + ` : css` - min-width: 286px; - white-space: nowrap; - padding: 15px 26px;`} -:hover { - background: rgba(255, 255, 255, 0.2); -} + min-width: 286px; + white-space: nowrap; + padding: 15px 26px;`} + + :hover { + background: rgba(255, 255, 255, 0.2); + } ` + export const Checkbox = styled(BaseCheckbox)` display: block; text-transform: uppercase; ${Label} { - text-transform: uppercase; + text-transform: uppercase; font-weight: 700; + ${isMobileDevice ? css` font-size: 10px; - line-height: 11px; - ` + line-height: 11px;` : css` font-size: 18px; - line-height: 16px; - `} + line-height: 16px;`} + ${NameStyled} { overflow: hidden; text-overflow: ellipsis; @@ -64,152 +76,159 @@ export const Checkbox = styled(BaseCheckbox)` } ${({ checked }) => (checked - ? css`` - : css` - color: rgba(255, 255, 255, 0.6);` - )} + ? '' + : css`color: rgba(255, 255, 255, 0.6);`)} } ${CheckboxSvg} { margin-right: 8px; - flex: 0 0 auto; + ${isMobileDevice ? css` width: 14px; height: 14px; - ` - : css` + ` + : css` width: 20px; - height: 20px; - `} + height: 20px;`} } ` + type TCommonButtonsBlock = { isArena?: boolean, } export const CommonButtonsBlock = styled.div<TCommonButtonsBlock>` -display: flex; -justify-content: space-between; -${({ isArena }) => (isArena + display: flex; + justify-content: space-between; + + ${({ isArena }) => (isArena ? css` - align-items: flex-start; - padding: ${isMobileDevice ? '8px 25px 10px 13px' : '24px 26px 15px 26px'}; - ` + align-items: flex-start; + padding: ${isMobileDevice ? '8px 25px 10px 13px' : '24px 26px 15px 26px'}; + ` : css` - align-items: center; - padding:${isMobileDevice ? '8px 25px 10px 13px' : '15px 26px'}; - ` - )} -` + align-items: center; + padding:${isMobileDevice ? '8px 25px 10px 13px' : '15px 26px'};`)} + ` + export const ClearButtonContainer = styled.div` -${isMobileDevice + ${isMobileDevice ? css` - position: absolute; - top: 14px; - right: 36px;` + position: absolute; + top: 14px; + right: 36px;` : ''} -.clear_button { - font-style: normal; - ${isMobileDevice + .clear_button { + ${isMobileDevice ? css` font-size: 10px; line-height: 12px;` : css` font-size: 18px; line-height: 22px;`} - font-weight: 400; - - letter-spacing: 0.05em; - text-transform: uppercase; - color: rgba(255, 255, 255, 0.5); - cursor: pointer; -} + + font-style: normal; + font-weight: 400; + letter-spacing: 0.05em; + text-transform: uppercase; + color: rgba(255, 255, 255, 0.5); + cursor: pointer; + } ` + export const SearchContainer = styled.div` -padding-right: ${isMobileDevice ? '0px' : '20px'}; -position: relative; + padding-right: ${isMobileDevice ? '0px' : '20px'}; + position: relative; -:before { - content: ''; - background: url(/images/search.svg) no-repeat; - position: absolute; - ${isMobileDevice + :before { + content: ''; + background: url(/images/search.svg) no-repeat; + position: absolute; + + ${isMobileDevice ? css` - left: 8px; - top: 7px;` + left: 8px; + top: 7px; + width: 11px; + height: 11px; + ` : css` - left: 13px; - top: 13px;`} - z-index: 2; - width: 13px; - height: 11px; -} + left: 13px; + top: 10px; + width: 16px; + height: 16px;`} + + z-index: 2; + } ` export const SearchInput = styled.input` -border: none; -background: transparent; -outline: none; -width: 100%; -background: #292929; -border-radius: 10px; -margin-bottom: 15px; - -color: #FFFF; -${isMobileDevice + border: none; + background: transparent; + outline: none; + width: 100%; + background: #292929; + border-radius: 10px; + margin-bottom: 15px; + color: #FFFF; + + ${isMobileDevice ? css` - height: 24px; - min-width: 242px; - padding-left: 23px;` + height: 24px; + min-width: 242px; + padding-left: 23px;` : css` - min-width: 513px; - padding-left: 36px; - height: 36px;`} + min-width: 513px; + padding-left: 36px; + height: 36px;`} -::placeholder { -${isMobileDevice + ${isMobileDevice ? css` - font-size: 10px; - line-height: 15px;` - : css` - font-size: 18px; - line-height: 22px;`} + font-size: 10px; + line-height: 15px;` + : css` + font-size: 18px; + line-height: 22px;`} - text-transform: uppercase; - letter-spacing: 0.05em; -} + ::placeholder { + text-transform: uppercase; + letter-spacing: 0.05em; + } ` + export const SearchWithAllContainer = styled.div` -flex: 1 1 auto; + flex: 1 1 auto; ` + export const BackButton = styled.div` -font-style: normal; -font-weight: 700; -font-size: 10px; -line-height: 12px; -align-items: center; -letter-spacing: 0.05em; -text-transform: uppercase; -color: #FFFFFF; -cursor: pointer; -position: absolute; -top: 12px; -left: 13px; -padding-left: 24px; -:before { - content: ''; - display: block; - background: url(/images/arrowUpWhite.svg) center no-repeat; - background-size: 12px 12xp; - transform: rotate(-90deg); - right: 0; - width: 12px; - height: 12px; + font-style: normal; + font-weight: 700; + font-size: 10px; + line-height: 12px; + align-items: center; + letter-spacing: 0.05em; + text-transform: uppercase; + color: #FFFFFF; + cursor: pointer; position: absolute; - top: 0; - left: 0; -} + top: 12px; + left: 13px; + padding-left: 24px; + + :before { + content: ''; + display: block; + background: url(/images/arrowUpWhite.svg) center no-repeat; + background-size: 12px 12xp; + transform: rotate(-90deg); + right: 0; + width: 12px; + height: 12px; + position: absolute; + top: 0; + left: 0; + } ` diff --git a/src/features/HomePage/components/Dropdown/types.tsx b/src/features/HomePage/components/Dropdown/types.tsx index 77c26e29..35e9ffab 100644 --- a/src/features/HomePage/components/Dropdown/types.tsx +++ b/src/features/HomePage/components/Dropdown/types.tsx @@ -1,5 +1,4 @@ import { MouseEvent, ChangeEvent } from 'react' -import { Match } from 'requests' import { TActiveFilters } from 'features/HeaderFilters/store/hooks/useMatchFilters' export type TDropDownProps = { @@ -7,7 +6,6 @@ export type TDropDownProps = { changeInput: (e: ChangeEvent<HTMLInputElement>) => void, clearFilters: (filterName: string) => (e: MouseEvent | ChangeEvent<HTMLInputElement>) => void, closeDropdownList?: () => void, - filterList: Array<Match>, filterTitle: string, inputValue: string, setFilters: (filterName: string, value: number) => void, @@ -15,6 +13,7 @@ export type TDropDownProps = { export type TItem = { id: number, + lexic?: string, name_eng: string, name_rus: string, } diff --git a/src/features/HomePage/components/Header/index.tsx b/src/features/HomePage/components/Header/index.tsx index 21b639ab..de8c84c2 100644 --- a/src/features/HomePage/components/Header/index.tsx +++ b/src/features/HomePage/components/Header/index.tsx @@ -15,14 +15,18 @@ import { Position, } from 'features/ProfileHeader/styled' -export const Header = () => { +type THeader = { + disabled: boolean, +} + +export const Header = ({ disabled }: THeader) => { const { resetFilters, updateDate, } = useHeaderFiltersStore() return ( - <HeaderStyled> + <HeaderStyled disabled={disabled}> <Position top={client.styles.logoTop} left={client.styles.logoLeft} diff --git a/src/features/HomePage/components/HeaderFilters/index.tsx b/src/features/HomePage/components/HeaderFilters/index.tsx index 781164e1..3a573967 100644 --- a/src/features/HomePage/components/HeaderFilters/index.tsx +++ b/src/features/HomePage/components/HeaderFilters/index.tsx @@ -1,39 +1,23 @@ -import { useRecoilValue } from 'recoil' - -import { isLffClient, isInSportsClient } from 'config/clients' +import styled from 'styled-components/macro' -import { SportsFilter } from 'features/SportsFilter' +import { isInSportsClient } from 'config/clients' import { SelectFilter } from 'components/SelectFilter' import { useHeaderFiltersStore } from 'features/HeaderFilters' import { T9n } from 'features/T9n' -import { - Modal as BaseModal, -} from 'features/AuthServiceApp/components/RegisterPopup/styled' -import styled from 'styled-components/macro' -import { ModalWindow } from 'features/Modal/styled' import { ScArrow, ScHeaderFilters, - ScFilterItemsWrap, - ScFilterItem, + SelectFilterWrapper, } from './styled' -import { isSportFilterShownAtom } from '../../Atoms/HomePageAtoms' import { ClearFiltersPopup } from '../ClearFiltersPopup' import { MatchesFilters } from '../MatchesFilters' -export const Modal = styled(BaseModal)` - ${ModalWindow} { - min-height: 452px; - max-width: 280px; - padding: 37px 0 39px 0; - } -` const ClearButton = styled.span` cursor: pointer; position: absolute; - left: 5px; - top: 38px; + left: 36px; + top: 30px; font-style: normal; font-weight: 400; font-size: 18px; @@ -45,82 +29,40 @@ const ClearButton = styled.span` export const HeaderFilters = () => { const { clickClearAll, + handleClickBack, isEmptyFilters, + isFiltersShown, isShowTournament, - selectedFilters, - selectTournament, - setIsShowTournament, - setSelectedFilters, - setSelectedLeague, + selectedTournament, } = useHeaderFiltersStore() - const isSportFilterShown = useRecoilValue(isSportFilterShownAtom) - - const isActiveFilter = (filterItem: string) => selectedFilters.indexOf(filterItem) >= 0 - const checkFilter = (item: string) => { - isActiveFilter(item) - ? setSelectedFilters((prev) => prev.filter((check) => item !== check)) - : setSelectedFilters([...selectedFilters, item]) - } - - const handleClickBack = () => { - setIsShowTournament(true) - setSelectedFilters([]) - setSelectedLeague(['all_competitions']) - } return ( <ScHeaderFilters> {!isShowTournament && ( - <> + <SelectFilterWrapper onClick={handleClickBack}> <ScArrow refIcon='Arrow' color='#ffffff' direction={90} - onClick={() => handleClickBack()} /> <SelectFilter open={false} - selectItem={selectTournament} + selectItem={selectedTournament} withArrow={false} /> - </> + </SelectFilterWrapper> )} - {!isLffClient && isShowTournament && isSportFilterShown && <SportsFilter />} - {!isEmptyFilters && ( <ClearButton onClick={clickClearAll}> <T9n t='clear' /> </ClearButton> )} - {!isLffClient && ( + {isInSportsClient && isFiltersShown && ( <> <MatchesFilters /> - <ClearFiltersPopup /> </> )} - {isShowTournament && !isInSportsClient && ( - <ScFilterItemsWrap> - <ScFilterItem - className={isActiveFilter('live') ? 'activeLive' : ''} - onClick={() => checkFilter('live')} - > - <T9n t='live' /> - </ScFilterItem> - <ScFilterItem - className={isActiveFilter('upcoming') ? 'activeButton' : ''} - onClick={() => checkFilter('upcoming')} - > - <T9n t='upcoming' /> - </ScFilterItem> - <ScFilterItem - className={isActiveFilter('completed') ? 'activeButton' : ''} - onClick={() => checkFilter('completed')} - > - <T9n t='completed' /> - </ScFilterItem> - </ScFilterItemsWrap> - )} </ScHeaderFilters> ) } diff --git a/src/features/HomePage/components/HeaderFilters/styled.tsx b/src/features/HomePage/components/HeaderFilters/styled.tsx index ec1b9067..ef2ec3bf 100644 --- a/src/features/HomePage/components/HeaderFilters/styled.tsx +++ b/src/features/HomePage/components/HeaderFilters/styled.tsx @@ -19,6 +19,12 @@ export const ScHeaderFilters = styled.div` } ` +export const SelectFilterWrapper = styled.div` + display: flex; + align-items: center; + cursor: pointer; +` + export const ScFilterItemsWrap = styled.div` display: flex; flex-direction: row; @@ -45,7 +51,12 @@ export const ScFilterItem = styled.div<Props>` export const ScArrow = styled(Icon)` margin-right: 15px; - cursor: pointer; + height: 20px; + + svg { + width: 20px; + height: 12px; + } :hover { /* background-color: rgba(255, 255, 255, 0.5);; */ diff --git a/src/features/HomePage/components/MatchesFilters/index.tsx b/src/features/HomePage/components/MatchesFilters/index.tsx index 15ff7714..4a822d1f 100644 --- a/src/features/HomePage/components/MatchesFilters/index.tsx +++ b/src/features/HomePage/components/MatchesFilters/index.tsx @@ -1,12 +1,15 @@ -import React from 'react' import map from 'lodash/map' import isNil from 'lodash/isNil' import size from 'lodash/size' +import find from 'lodash/find' +import includes from 'lodash/includes' import { useName } from 'features/Name' import { T9n } from 'features/T9n' import { useHeaderFiltersStore } from 'features/HeaderFilters' + import { isMobileDevice } from 'config/userAgent' + import { FilterContainer, FiltersCount, @@ -15,17 +18,27 @@ import { ActiveFilter, CloseButton, } from './styled' -import { DropDown } from '../Dropdown/Dropdown' +import { DropDown } from '../Dropdown' +import { TItem } from '../Dropdown/types' import { checkSize, truncateString } from './helpers' +import { Title } from '../MatchesFilters/styled' type TProps = { + dropdownList: Array<TItem | number>, filterTitle: string, - item: any, + item: number, } -const ActiveFilterText = ({ filterTitle, item }: TProps) => { - const name = useName(item) - if (filterTitle === 'gender') return (<T9n t={item.title} />) +const ActiveFilterText = ({ + dropdownList, + filterTitle, + item, +}: TProps) => { + const currentItem = find(dropdownList, { id: item }) as TItem + const name = useName(currentItem) + + if (includes(['gender', 'sport'], filterTitle)) return <T9n t={currentItem.lexic!} /> + return ( <> {truncateString(name)} @@ -42,17 +55,18 @@ export const MatchesFilters = ({ isMobile }: TFiltersProps) => { changeInput, clearFilters, currentFilters, - filtersList, + filtersListName, filtersSize, + getDropdownList, handleSetFilters, inputValue, - isOpenList, - openDropdownList, + matchesList, + toggleDropdownList, } = useHeaderFiltersStore() return ( <MatchFiltersContainer> - {map(currentFilters, (filterTitle, index) => { + {map(currentFilters, (filterTitle) => { const currentActiveFilters = activeFilters[filterTitle as keyof typeof activeFilters] const isShrinkFilters = filtersSize >= 7 || size(currentActiveFilters) >= 7 @@ -62,20 +76,27 @@ export const MatchesFilters = ({ isMobile }: TFiltersProps) => { ? [currentActiveFilters[0], currentActiveFilters[1]] : currentActiveFilters + const dropdownList = getDropdownList(filterTitle, '') as Array<TItem | number> + return ( <FilterContainer - active={isOpenList === filterTitle} - key={index} - onClick={openDropdownList(filterTitle)} + active={filtersListName === filterTitle} + key={filterTitle} + onClick={toggleDropdownList(filterTitle)} > - {/* <T9n className='filter_title' t={filterTitle} /> */} - <span className='filter_title'>{filterTitle}</span> + <Title t={filterTitle} /> <ActiveFilters> - {map(shrinkedActiveFilters, (item, i) => ( - <ActiveFilter key={i}> - {typeof item === 'number' + {map(shrinkedActiveFilters, (item) => ( + <ActiveFilter key={item}> + {filterTitle === 'youth_age' ? `U${item}` - : (<ActiveFilterText filterTitle={filterTitle} item={item} />)} + : ( + <ActiveFilterText + dropdownList={dropdownList} + filterTitle={filterTitle} + item={item} + /> + )} <CloseButton onClick={(e) => { e.stopPropagation() handleSetFilters(filterTitle, item) @@ -90,15 +111,14 @@ export const MatchesFilters = ({ isMobile }: TFiltersProps) => { </FiltersCount> )} </ActiveFilters> - {isOpenList === filterTitle && !isNil(filtersList) && !isMobileDevice && ( + {filtersListName === filterTitle && !isNil(matchesList) && !isMobileDevice && ( <DropDown + activeFilters={activeFilters} changeInput={changeInput} - inputValue={inputValue} clearFilters={clearFilters} - activeFilters={activeFilters} - setFilters={handleSetFilters} filterTitle={filterTitle} - filterList={filtersList} + inputValue={inputValue} + setFilters={handleSetFilters} /> )} </FilterContainer> diff --git a/src/features/HomePage/components/MatchesFilters/styled.tsx b/src/features/HomePage/components/MatchesFilters/styled.tsx index 656c771b..62c0aa72 100644 --- a/src/features/HomePage/components/MatchesFilters/styled.tsx +++ b/src/features/HomePage/components/MatchesFilters/styled.tsx @@ -1,25 +1,25 @@ -import { isMobileDevice } from 'config/userAgent' import styled, { css } from 'styled-components/macro' +import { isMobileDevice } from 'config/userAgent' +import { T9n } from 'features/T9n' + export const MatchFiltersContainer = styled.div` -display: flex; -flex-wrap: no-wrap; -justify-content: flex-end; -width: 100%; + display: flex; + flex-wrap: no-wrap; + justify-content: flex-end; + width: 100%; -${isMobileDevice + ${isMobileDevice ? css` - flex-direction: column; - padding-right: 16px; - border-top: 1px solid #505050; - padding-top: 19px; - gap: 22px; - ` - : css` - gap: 30px; - flex-direction: row; - padding-right: 25px; - `} + flex-direction: column; + padding-right: 16px; + border-top: 1px solid #505050; + padding-top: 19px; + gap: 22px; + ` : css` + gap: 30px; + flex-direction: row; + padding-right: 10px;`} ` type TFilterContainer = { @@ -27,143 +27,145 @@ type TFilterContainer = { } export const FilterContainer = styled.div<TFilterContainer>` -font-style: normal; -font-weight: 700; -letter-spacing: 0.05em; -text-transform: uppercase; -position: relative; -display: flex; - -${isMobileDevice - ? css` - color:#8b8b8b; - font-size: 10px; - line-height: 14px; - padding-left: 19px; - flex-direction: row; - align-items: center; -` - : css` - font-size: 18px; - line-height: 34px; - height: 34px; - color: #FFFFFF; - padding-left: 32px; - flex-direction: column;`} + font-style: normal; + font-weight: 700; + letter-spacing: 0.05em; + text-transform: uppercase; + position: relative; + display: flex; -.filter_title { - cursor: pointer; - ${isMobileDevice && 'margin-right: 6px;'} -} -${({ active }) => active && !isMobileDevice && css` -:after { - content: ''; - display: block; - position: fixed; - background: #000000; - opacity: 0.7; - top: 0px; - left: 0px; - width: 100%; - height: 100%; - z-index: 9; - cursor: auto; -}`} - - -:before { - display: block; - position: absolute; - top: 0; - content: ''; - height: 100%; - cursor: pointer; - - ${({ active }) => (active + ${isMobileDevice ? css` - z-index: 12; + color:#8b8b8b; + font-size: 10px; + line-height: 14px; + padding-left: 19px; + flex-direction: row; + align-items: center; ` : css` - transform: rotate(180deg); - `)} + font-size: 18px; + line-height: 34px; + height: 34px; + color: #FFFFFF; + padding-left: 32px; + flex-direction: column;`} - ${isMobileDevice + ${({ active }) => active && !isMobileDevice && css` + :after { + content: ''; + display: block; + position: fixed; + background: #000000; + opacity: 0.7; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + z-index: 9; + cursor: auto; + }`} + + :before { + display: block; + position: absolute; + top: 0; + content: ''; + height: 100%; + cursor: pointer; + + ${({ active }) => (active ? css` - background: url(/images/arrowUpWhite.svg) center no-repeat; - transform: rotate(90deg); - right: 0; - width: 10px; + z-index: 12; ` : css` - background: url(/images/arrowUpWhite.svg) center no-repeat; - background-size: 20px 12px; - left: 0; - width: 20px; - `} - - -} - span { - ${({ active }) => (active && css` - z-index:12; - position: relative; + transform: rotate(180deg); `)} + + ${isMobileDevice + ? css` + background: url(/images/arrowUpWhite.svg) center no-repeat; + transform: rotate(90deg); + right: 0; + width: 10px; + ` + : css` + background: url(/images/arrowUpWhite.svg) center no-repeat; + background-size: 20px 12px; + left: 0; + width: 20px; + `} } + span { + ${({ active }) => (active && css` + z-index: 12; + position: relative; + `)} + } ` export const ActiveFilters = styled.div` -display: flex; -flex-direction: row; -${isMobileDevice + display: flex; + flex-direction: row; + + ${isMobileDevice ? css` - gap: 5px;` + gap: 5px;` : css` - gap: 10px;`} + gap: 10px;`} ` + export const CloseButton = styled.div` -background: url(/images/closeWhite.svg) no-repeat; + background: url(/images/closeWhite.svg) no-repeat; -${isMobileDevice + ${isMobileDevice ? css` - width: 7px; - height: 7px; - background-size: 7px;` + width: 7px; + height: 7px; + background-size: 7px;` : css` - height: 9px; - width: 9px; - background-size: 10px;`} - + height: 9px; + width: 9px; + background-size: 10px;`} ` + export const ActiveFilter = styled.span` -font-style: normal; -font-weight: 600; -display: flex; -align-items: center; -letter-spacing: 0.05em; -text-transform: uppercase; -color: #FFFFFF; -border: 1px solid #FFFFFF; -border-radius: 16px; -gap: 5px; -cursor: pointer; -${isMobileDevice + font-style: normal; + font-weight: 600; + display: flex; + align-items: center; + letter-spacing: 0.05em; + text-transform: uppercase; + color: #FFFFFF; + border: 1px solid #FFFFFF; + border-radius: 16px; + gap: 5px; + cursor: pointer; + + ${isMobileDevice ? css` - padding: 0 5px; - font-size: 10px; - line-height: 12px;` + padding: 0 5px; + font-size: 10px; + line-height: 12px;` : css` - padding: 0 10px; - font-size: 14px; - height: 17px; - :hover { - background: #ffff; - color: #000000; - - ${CloseButton} { - background: url(/images/closeBlack.svg) no-repeat; - } - }`} - + padding: 0 10px; + font-size: 14px; + height: 17px; + :hover { + background: #ffff; + color: #000000; + + ${CloseButton} { + background: url(/images/closeBlack.svg) no-repeat; + } + }`} ` + export const FiltersCount = styled(ActiveFilter)`` + +export const Title = styled(T9n)` + cursor: pointer; + + ${isMobileDevice ? css`margin-right: 6px;` : ''} +` diff --git a/src/features/HomePage/components/MobileMatchesFilters/index.tsx b/src/features/HomePage/components/MobileMatchesFilters/index.tsx index 2547c38d..b21808f6 100644 --- a/src/features/HomePage/components/MobileMatchesFilters/index.tsx +++ b/src/features/HomePage/components/MobileMatchesFilters/index.tsx @@ -1,19 +1,23 @@ -import { useHeaderFiltersStore } from 'features/HeaderFilters' -import { T9n } from 'features/T9n' -import React, { useState } from 'react' +import { useState } from 'react' + import isEmpty from 'lodash/isEmpty' import isNil from 'lodash/isNil' + +import { useHeaderFiltersStore } from 'features/HeaderFilters' +import { T9n } from 'features/T9n' + import { MatchesFilters } from '../MatchesFilters' import { ClearButton, CloseButton, FilterContainer, + FiltersCount, Modal, } from './styled' -import { DropDown } from '../Dropdown/Dropdown' +import { DropDown } from '../Dropdown' import { ClearFiltersPopup } from '../ClearFiltersPopup' -export const MobileMathesFilters = () => { +export const MobileMatchesFilters = () => { const [isOpen, setOpen] = useState(false) const { activeFilters, @@ -22,11 +26,12 @@ export const MobileMathesFilters = () => { clickClearAll, closeDropdownList, currentFilters, - filtersList, + filtersListName, filtersSize, handleSetFilters, inputValue, - isOpenList, + isEmptyFilters, + matchesList, } = useHeaderFiltersStore() const openFilters = () => setOpen(true) @@ -46,14 +51,14 @@ export const MobileMathesFilters = () => { <> <FilterContainer active={filtersSize !== 0} onClick={openFilters}> <T9n t='filter' /> - {filtersSize !== 0 && ` ${filtersSize}`} + {filtersSize !== 0 && <FiltersCount>{` ${filtersSize}`}</FiltersCount>} </FilterContainer> <Modal isOpen={isOpen} withCloseButton={false}> - {isEmpty(isOpenList) + {!filtersListName ? ( <> <MatchesFilters isMobile /> - {filtersSize !== 0 && ( + {!isEmptyFilters && ( <ClearButton onClick={clearAllFilters}> <T9n t='clear' /> </ClearButton> @@ -63,16 +68,15 @@ export const MobileMathesFilters = () => { ) : ( <> - {!isNil(filtersList) && ( + {!isNil(matchesList) && ( <DropDown + activeFilters={activeFilters} changeInput={changeInput} - inputValue={inputValue} clearFilters={clearFilters} - activeFilters={activeFilters} - setFilters={handleSetFilters} - filterTitle={isOpenList} - filterList={filtersList} closeDropdownList={closeDropdownList} + filterTitle={filtersListName} + inputValue={inputValue} + setFilters={handleSetFilters} /> )} <CloseButton onClick={closeFilters} /> diff --git a/src/features/HomePage/components/MobileMatchesFilters/styled.tsx b/src/features/HomePage/components/MobileMatchesFilters/styled.tsx index 1b40d4f8..77b0961f 100644 --- a/src/features/HomePage/components/MobileMatchesFilters/styled.tsx +++ b/src/features/HomePage/components/MobileMatchesFilters/styled.tsx @@ -1,27 +1,32 @@ import styled, { css } from 'styled-components/macro' +import { OutsideClickWrapper } from 'features/OutsideClick' import { ModalWindow } from 'features/Modal/styled' import { Modal as BaseModal, } from 'features/AuthServiceApp/components/RegisterPopup/styled' export const Modal = styled(BaseModal)` + ${OutsideClickWrapper} { + height: 100%; + } + ${ModalWindow} { min-height: auto; - max-height: 452px; max-width: 293px; padding: 35px 0 9px 0; + top: 4vh; } ` export const CloseButton = styled.div` -position: absolute; -width: 13px; -height: 13px; -background:url(/images/closeWhite.svg) no-repeat; -background-size: 13px; -top: 13px; -right: 13px; + position: absolute; + width: 13px; + height: 13px; + background:url(/images/closeWhite.svg) no-repeat; + background-size: 13px; + top: 13px; + right: 13px; ` type TFilterProps = { @@ -29,43 +34,47 @@ type TFilterProps = { } export const FilterContainer = styled.div<TFilterProps>` -font-style: normal; -font-weight: 700; -font-size: 10px; -line-height: 12px; -letter-spacing: 0.05em; -text-transform: uppercase; -color: #FFFFFF; -padding-left: 22px; -position: relative; -margin-left: 20px; + font-style: normal; + font-weight: 700; + font-size: 10px; + line-height: 14px; + letter-spacing: 0.05em; + text-transform: uppercase; + color: #FFFFFF; + padding-left: 22px; + position: relative; -:before{ - content: ''; - display: block; - position: absolute; - left: 0; - top: 0; - width:14px; - height: 14px; - ${({ active }) => (active + :before{ + content: ''; + display: block; + position: absolute; + left: 0; + top: 0; + width:14px; + height: 14px; + background-size: 14px 14px; + + ${({ active }) => (active ? css` - background: url(/images/filter-white.svg) no-repeat;` + background: url(/images/filter-white.svg) no-repeat;` : css` - background: url(/images/filter-gray.svg) no-repeat;`)} - background-size: 14px 14px; -} + background: url(/images/filter-gray.svg) no-repeat;`)} + } ` export const ClearButton = styled.div` -font-style: normal; -position: absolute; -top: 14px; -right: 36px; -font-size: 10px; -line-height: 12px; -font-weight: 400; -letter-spacing: 0.05em; -text-transform: uppercase; -color: rgba(255,255,255,0.5); + font-style: normal; + position: absolute; + top: 14px; + right: 36px; + font-size: 10px; + line-height: 12px; + font-weight: 400; + letter-spacing: 0.05em; + text-transform: uppercase; + color: rgba(255,255,255,0.5); +` + +export const FiltersCount = styled.span` + font-weight: 400; ` diff --git a/src/features/HomePage/hooks.tsx b/src/features/HomePage/hooks.tsx index 6f14c4d1..16875978 100644 --- a/src/features/HomePage/hooks.tsx +++ b/src/features/HomePage/hooks.tsx @@ -6,19 +6,12 @@ import { import { format } from 'date-fns' -import { useSetRecoilState } from 'recoil' - -import { client } from 'config/clients' -import { ClientNames } from 'config/clients/types' - import { useAuthStore } from 'features/AuthStore' import { useHeaderFiltersStore } from 'features/HeaderFilters' import { getHomeMatches } from 'requests/getMatches' import { getAgreements, setAgreements } from 'requests/getAgreements' -import { isSportFilterShownAtom } from './Atoms/HomePageAtoms' - /** * возвращает смещение в минутах относительно UTC * @@ -38,7 +31,6 @@ export const useHomePage = () => { const { queryParams, selectedDate } = useHeaderFiltersStore() const [isOpenDownload, setIsOpenDownload] = useState(false) const [isShowConfirmPopup, setIsShowConfirmPopup] = useState(false) - const setIsSportFilterShown = useSetRecoilState(isSportFilterShownAtom) const handleCloseConfirmPopup = useCallback(async () => { await setAgreements(user?.profile?.email || '') @@ -74,12 +66,6 @@ export const useHomePage = () => { }, ), [selectedDate, queryParams]) - useEffect(() => { - if (client.name === ClientNames.Facr) { - setIsSportFilterShown(false) - } - }, [setIsSportFilterShown]) - return { fetchMatches, handleCloseConfirmPopup, diff --git a/src/features/HomePage/index.tsx b/src/features/HomePage/index.tsx index 6f9fd6ca..178a1346 100644 --- a/src/features/HomePage/index.tsx +++ b/src/features/HomePage/index.tsx @@ -7,6 +7,7 @@ import { ConfirmPopup } from 'features/AuthServiceApp/components/ConfirmPopup' import { Matches } from 'features/Matches' import { HeaderFiltersStore, + useHeaderFiltersStore, } from 'features/HeaderFilters' import { @@ -30,6 +31,7 @@ const Home = () => { isShowConfirmPopup, setIsOpenDownload, } = useHomePage() + const { filtersListName } = useHeaderFiltersStore() return ( <PageWrapper> @@ -39,7 +41,7 @@ const Home = () => { setIsOpenDownload={setIsOpenDownload} /> ) : ( - <Header /> + <Header disabled={Boolean(filtersListName)} /> )} <Main> <UserFavorites /> diff --git a/src/features/Matches/helpers/prepareMatches.tsx b/src/features/Matches/helpers/prepareMatches.tsx index f218cd87..9a5a6fd6 100644 --- a/src/features/Matches/helpers/prepareMatches.tsx +++ b/src/features/Matches/helpers/prepareMatches.tsx @@ -10,6 +10,7 @@ import { getMatchAccess } from './getMatchClickAction' const prepareMatch = (match: Match) => { const { + arena, calc, country, country_id, @@ -21,6 +22,7 @@ const prepareMatch = (match: Match) => { live, preview, previewURL, + round, sport, sport_info, storage, @@ -32,6 +34,7 @@ const prepareMatch = (match: Match) => { const date = parseDate(matchDate) return { access: getMatchAccess(match), + arena, calc, countryId: country_id, countryInfo: country, @@ -44,6 +47,7 @@ const prepareMatch = (match: Match) => { live, preview, previewURL, + round, sportInfo: sport_info, sportType: sport, storage, diff --git a/src/features/OutsideClick/index.tsx b/src/features/OutsideClick/index.tsx index ddfa62aa..ff97d3a1 100644 --- a/src/features/OutsideClick/index.tsx +++ b/src/features/OutsideClick/index.tsx @@ -11,7 +11,7 @@ type Props = { onClick: (event?: MouseEvent) => void, } -const OutsideClickWrapper = styled.div`` +export const OutsideClickWrapper = styled.div`` export const OutsideClick = ({ children, diff --git a/src/features/ProfileHeader/styled.tsx b/src/features/ProfileHeader/styled.tsx index 2c1f2b2f..084bbf3e 100644 --- a/src/features/ProfileHeader/styled.tsx +++ b/src/features/ProfileHeader/styled.tsx @@ -44,6 +44,7 @@ export const defaultHeaderStyles = ( type HeaderProps = { color?: string, + disabled?: boolean, headerImage?: string | null, height?: number, isMatchPage?: boolean, @@ -63,6 +64,12 @@ export const HeaderStyled = styled.header<HeaderProps>` ` : '' )} + ${({ disabled }) => ( + disabled ? css` + pointer-events: none; + ` : '' + )} + ${({ isMatchPage }) => css` ${isMobileDevice ? css` @@ -71,7 +78,6 @@ export const HeaderStyled = styled.header<HeaderProps>` ` : ''} `} - ` type Props = { @@ -105,7 +111,7 @@ export const HeaderLogo = styled(Logo)` transform: translateX(-50%); position: absolute; - ${client.styles.matchPageMobileHeaderLogo} + ${client.styles.matchPageMobileHeaderLogo} ` : ''} ` : css` ${isMobileDevice ? css` @@ -119,8 +125,6 @@ export const HeaderLogo = styled(Logo)` } ` : ''} `)} - - ` type PositionProps = { diff --git a/src/features/TournamentList/components/CollapseTournament/index.tsx b/src/features/TournamentList/components/CollapseTournament/index.tsx index d6b8d406..7d5167d8 100644 --- a/src/features/TournamentList/components/CollapseTournament/index.tsx +++ b/src/features/TournamentList/components/CollapseTournament/index.tsx @@ -35,7 +35,7 @@ export const CollapseTournament = ({ const { setIsShowTournament, setSelectedLeague, - setSelectTournament, + setSelectedTournament, } = useHeaderFiltersStore() const { countryId, @@ -47,7 +47,7 @@ export const CollapseTournament = ({ const handleClick = () => { setIsShowTournament(false) setSelectedLeague([tournament.id]) - setSelectTournament(tournament) + setSelectedTournament(tournament) } const { countryInfo, sportInfo } = tournamentMatches[0] diff --git a/src/requests/getMatches/getHomeMatches.tsx b/src/requests/getMatches/getHomeMatches.tsx index f1519251..194c5b4a 100644 --- a/src/requests/getMatches/getHomeMatches.tsx +++ b/src/requests/getMatches/getHomeMatches.tsx @@ -15,6 +15,7 @@ export type TQueryParams = { gender?: Array<number>, main_team?: Array<number>, round?: Array<number>, + sport?: Array<number>, youth_age?: Array<number>, } @@ -45,6 +46,7 @@ export const getHomeMatches = async ({ main_team: !isEmpty(queryParams?.main_team) ? queryParams?.main_team : undefined, offset: String(offset), round: !isEmpty(queryParams?.round) ? queryParams?.round : undefined, + sport: !isEmpty(queryParams?.sport) ? queryParams?.sport : undefined, youth_age: !isEmpty(queryParams?.youth_age) ? queryParams?.youth_age : undefined, ...client.requests?.[proc], }, diff --git a/src/requests/getMatches/types.tsx b/src/requests/getMatches/types.tsx index ff130b6f..75bbc9c8 100644 --- a/src/requests/getMatches/types.tsx +++ b/src/requests/getMatches/types.tsx @@ -12,6 +12,7 @@ export type TDefaultType = { name_eng: string, name_rus: string, } + type Team = { division?: TDefaultType, // Дивизион gender?: number, // ИД пола