parent
873718947f
commit
291d44c858
|
After Width: | Height: | Size: 329 B |
|
After Width: | Height: | Size: 314 B |
|
After Width: | Height: | Size: 609 B |
|
After Width: | Height: | Size: 590 B |
|
After Width: | Height: | Size: 1.0 KiB |
@ -0,0 +1,101 @@ |
||||
import { useMemo, useState } from 'react' |
||||
|
||||
import includes from 'lodash/includes' |
||||
import filter from 'lodash/filter' |
||||
import isEmpty from 'lodash/isEmpty' |
||||
import size from 'lodash/size' |
||||
|
||||
type TTogglePlayers = { |
||||
id: Number, |
||||
team: String, |
||||
} |
||||
|
||||
type TFilters = { |
||||
events: Array<Number>, |
||||
players: Array<Number>, |
||||
} |
||||
|
||||
export const useFiltersPopup = () => { |
||||
const [isOpen, setIsOpen] = useState(false) |
||||
const [activeEvents, setActiveEvents] = useState<Array<Number>>([]) |
||||
const [activeFirstTeamPlayers, setActiveFirstTeamPlayers] = useState<Array<Number>>([]) |
||||
const [activeSecondTeamPlayers, setActiveSecondTeamPlayers] = useState<Array<Number>>([]) |
||||
const [activeFilters, setActiveFilters] = useState<TFilters>({ events: [], players: [] }) |
||||
|
||||
const toggle = () => { |
||||
setIsOpen(!isOpen) |
||||
} |
||||
|
||||
const close = () => { |
||||
setIsOpen(false) |
||||
} |
||||
|
||||
const toggleActiveEvents = (id: number) => () => { |
||||
setActiveEvents(includes(activeEvents, id) |
||||
? [...filter(activeEvents, (item) => item !== id)] |
||||
: [...activeEvents, id]) |
||||
} |
||||
|
||||
const toggleActivePlayers = ({ id, team }: TTogglePlayers) => () => { |
||||
const teamState = team === 'team1' |
||||
? activeFirstTeamPlayers |
||||
: activeSecondTeamPlayers |
||||
|
||||
const setterTeamState = team === 'team1' |
||||
? setActiveFirstTeamPlayers |
||||
: setActiveSecondTeamPlayers |
||||
|
||||
setterTeamState(includes(teamState, id) |
||||
? [...filter(teamState, (item) => item !== id)] |
||||
: [...teamState, id]) |
||||
} |
||||
|
||||
const resetPlayers = (team: string) => () => { |
||||
const teamState = team === 'team1' |
||||
? activeFirstTeamPlayers |
||||
: activeSecondTeamPlayers |
||||
|
||||
const setterTeamState = team === 'team1' |
||||
? setActiveFirstTeamPlayers |
||||
: setActiveSecondTeamPlayers |
||||
|
||||
if (isEmpty(teamState)) return |
||||
setterTeamState([]) |
||||
} |
||||
|
||||
const resetEvents = () => { |
||||
if (isEmpty(activeEvents)) return |
||||
setActiveEvents([]) |
||||
} |
||||
|
||||
const applyFilters = () => { |
||||
setActiveFilters({ |
||||
events: [...activeEvents], |
||||
players: [...activeFirstTeamPlayers, ...activeSecondTeamPlayers], |
||||
}) |
||||
close() |
||||
} |
||||
|
||||
const isEmptyFilters = useMemo(() => ( |
||||
isEmpty(activeFilters.events) && isEmpty(activeFilters.players)), [activeFilters]) |
||||
|
||||
const countOfFilters = useMemo(() => ( |
||||
size(activeFilters.events) + size(activeFilters.players)), [activeFilters]) |
||||
|
||||
return { |
||||
activeEvents, |
||||
activeFirstTeamPlayers, |
||||
activeSecondTeamPlayers, |
||||
applyFilters, |
||||
close, |
||||
countOfFilters, |
||||
filters: activeFilters, |
||||
isEmptyFilters, |
||||
isOpen, |
||||
resetEvents, |
||||
resetPlayers, |
||||
toggle, |
||||
toggleActiveEvents, |
||||
toggleActivePlayers, |
||||
} |
||||
} |
||||
@ -0,0 +1,80 @@ |
||||
import { |
||||
useCallback, |
||||
useMemo, |
||||
useState, |
||||
} from 'react' |
||||
|
||||
import map from 'lodash/map' |
||||
import groupBy from 'lodash/groupBy' |
||||
import reverse from 'lodash/reverse' |
||||
import filter from 'lodash/filter' |
||||
import values from 'lodash/values' |
||||
import flatten from 'lodash/flatten' |
||||
import { Events, MatchInfo } from 'requests' |
||||
import { useToggle } from 'hooks' |
||||
import { EventPlaylistOption } from 'features/MatchPage/types' |
||||
|
||||
type TPropsTabEvents = { |
||||
events?: Events, |
||||
profile?: MatchInfo, |
||||
} |
||||
|
||||
export const useTabEvents = ({ |
||||
events, |
||||
profile, |
||||
}: TPropsTabEvents) => { |
||||
const [likesOnly, setLikesOnly] = useState(false) |
||||
|
||||
const { |
||||
close: setUnreversed, |
||||
isOpen: areEventsReversed, |
||||
open: setReversed, |
||||
} = useToggle() |
||||
|
||||
const likeToggle = useCallback(() => setLikesOnly((state) => !state), []) |
||||
const likeImage = likesOnly ? '/images/like-active-icon.svg' : '/images/likeDisable.svg' |
||||
|
||||
const isLiveMatch = profile?.live |
||||
const reverseStatus = (areEventsReversed || isLiveMatch) && (areEventsReversed !== isLiveMatch) |
||||
const activeStatus = isLiveMatch ? areEventsReversed : !areEventsReversed |
||||
|
||||
const reversedGroupEvents = useMemo(() => { |
||||
const eventsList = likesOnly ? filter(events, 'like') : events |
||||
const groupedEvents = values( |
||||
groupBy( |
||||
reverseStatus |
||||
? reverse([...eventsList!]) |
||||
: eventsList, |
||||
({ h }) => h, |
||||
), |
||||
) |
||||
return reverseStatus |
||||
? reverse(groupedEvents) |
||||
: groupedEvents |
||||
}, [ |
||||
events, |
||||
likesOnly, |
||||
reverseStatus, |
||||
]) |
||||
|
||||
const episodesToPlay = map(flatten(reversedGroupEvents), ((event) => ({ |
||||
episodes: [{ |
||||
e: event.e, |
||||
h: event.h, |
||||
s: event.s, |
||||
}], |
||||
id: event.n, |
||||
type: 3, |
||||
}))) as Array<EventPlaylistOption> |
||||
|
||||
return { |
||||
activeStatus, |
||||
episodesToPlay, |
||||
isLiveMatch, |
||||
likeImage, |
||||
likeToggle, |
||||
reversedGroupEvents, |
||||
setReversed, |
||||
setUnreversed, |
||||
} |
||||
} |
||||
@ -0,0 +1,145 @@ |
||||
import uniq from 'lodash/uniq' |
||||
import map from 'lodash/map' |
||||
import isEmpty from 'lodash/isEmpty' |
||||
import includes from 'lodash/includes' |
||||
import filter from 'lodash/filter' |
||||
|
||||
import { T9n } from 'features/T9n' |
||||
import { useMatchPageStore } from 'features/MatchPage/store' |
||||
import { PlayerPlaylistOption } from 'features/MatchPage/types' |
||||
import { CloseButton } from 'features/PopupComponents' |
||||
import { Name, useName } from 'features/Name' |
||||
|
||||
import { |
||||
Checkbox, |
||||
CloseButtonContainer, |
||||
PartBlock, |
||||
HeaderText, |
||||
ItemBlock, |
||||
ItemsContainer, |
||||
ItemText, |
||||
MainCheckboxContainer, |
||||
PopupContainer, |
||||
PopupHeader, |
||||
Button, |
||||
ButtonConatiner, |
||||
PlayerNumber, |
||||
} from './styled' |
||||
|
||||
type TLabelProps = { |
||||
player: PlayerPlaylistOption, |
||||
} |
||||
|
||||
const Label = ({ player }: TLabelProps) => { |
||||
const { num } = player |
||||
return ( |
||||
<ItemText> |
||||
<PlayerNumber> |
||||
{num} |
||||
</PlayerNumber> |
||||
<Name nameObj={player} /> |
||||
</ItemText> |
||||
) |
||||
} |
||||
|
||||
export const FiltersPopup = () => { |
||||
const { |
||||
activeEvents, |
||||
activeFirstTeamPlayers, |
||||
activeSecondTeamPlayers, |
||||
applyFilters, |
||||
closePopup, |
||||
events, |
||||
matchPlaylists, |
||||
profile, |
||||
resetEvents, |
||||
resetPlayers, |
||||
toggleActiveEvents, |
||||
toggleActivePlayers, |
||||
} = useMatchPageStore() |
||||
const currentEvents = filter(events, (event) => event.pl !== undefined |
||||
&& event.t !== undefined) |
||||
|
||||
const uniqEvents = uniq(map(currentEvents, ({ l }) => l)) |
||||
|
||||
const team1Name = useName(profile!.team1) |
||||
const team2Name = useName(profile!.team2) |
||||
|
||||
return ( |
||||
<PopupContainer> |
||||
<CloseButtonContainer> |
||||
<CloseButton onClick={closePopup} /> |
||||
</CloseButtonContainer> |
||||
<PopupHeader> |
||||
<HeaderText> |
||||
<T9n t='filter' /> |
||||
</HeaderText> |
||||
</PopupHeader> |
||||
<PartBlock> |
||||
<MainCheckboxContainer> |
||||
<Checkbox |
||||
onChange={resetEvents} |
||||
checked={isEmpty(activeEvents)} |
||||
labelLexic='all_actions' |
||||
/> |
||||
</MainCheckboxContainer> |
||||
<ItemsContainer> |
||||
{map(uniqEvents, ((event) => ( |
||||
<ItemBlock key={event}> |
||||
<Checkbox |
||||
checked={includes(activeEvents, event)} |
||||
onChange={toggleActiveEvents(event)} |
||||
labelLexic={event} |
||||
/> |
||||
</ItemBlock> |
||||
)))} |
||||
</ItemsContainer> |
||||
</PartBlock> |
||||
<PartBlock> |
||||
<MainCheckboxContainer> |
||||
<Checkbox |
||||
checked={isEmpty(activeFirstTeamPlayers)} |
||||
label={team1Name} |
||||
onChange={resetPlayers('team1')} |
||||
/> |
||||
</MainCheckboxContainer> |
||||
<ItemsContainer> |
||||
{map(matchPlaylists.players.team1, ((player) => ( |
||||
<ItemBlock key={player.id}> |
||||
<Checkbox |
||||
onChange={toggleActivePlayers({ id: player.id, team: 'team1' })} |
||||
checked={includes(activeFirstTeamPlayers, player.id)} |
||||
label={(<Label player={player} />)} |
||||
/> |
||||
</ItemBlock> |
||||
)))} |
||||
</ItemsContainer> |
||||
</PartBlock> |
||||
<PartBlock> |
||||
<MainCheckboxContainer> |
||||
<Checkbox |
||||
checked={isEmpty(activeSecondTeamPlayers)} |
||||
label={team2Name} |
||||
onChange={resetPlayers('team2')} |
||||
/> |
||||
</MainCheckboxContainer> |
||||
<ItemsContainer> |
||||
{map(matchPlaylists.players.team2, ((player) => ( |
||||
<ItemBlock key={player.id}> |
||||
<Checkbox |
||||
onChange={toggleActivePlayers({ id: player.id, team: 'team2' })} |
||||
checked={includes(activeSecondTeamPlayers, player.id)} |
||||
label={(<Label player={player} />)} |
||||
/> |
||||
</ItemBlock> |
||||
)))} |
||||
</ItemsContainer> |
||||
</PartBlock> |
||||
<ButtonConatiner> |
||||
<Button onClick={applyFilters}> |
||||
<T9n t='apply_filter' /> |
||||
</Button> |
||||
</ButtonConatiner> |
||||
</PopupContainer> |
||||
) |
||||
} |
||||
@ -0,0 +1,199 @@ |
||||
import styled, { css } from 'styled-components/macro' |
||||
|
||||
import { Checkbox as BaseCheckbox } from 'features/Common/Checkbox' |
||||
import { Label } from 'features/Common/Checkbox/styled' |
||||
import { CheckboxSvg } from 'features/Common/Checkbox/Icon' |
||||
import { customScrollbar } from 'features/Common' |
||||
import { NameStyled } from 'features/Name' |
||||
import { isMobileDevice } from 'config/userAgent' |
||||
import { BaseButton } from 'features/PopupComponents' |
||||
|
||||
export const PopupContainer = styled.div` |
||||
background: #333333; |
||||
box-shadow: 0px 2px 40px rgba(0, 0, 0, 0.6); |
||||
border-radius: 2px; |
||||
display: flex; |
||||
flex-direction: column; |
||||
position: absolute; |
||||
overflow-y: auto; |
||||
z-index: 1000; |
||||
height: 100%; |
||||
right: 0; |
||||
top: 0; |
||||
|
||||
${customScrollbar} |
||||
|
||||
${isMobileDevice |
||||
? css` |
||||
position: fixed; |
||||
height: calc(100vh - 40px); |
||||
width: 100%; |
||||
padding-bottom: 70px; |
||||
top: 40px;` |
||||
: css` |
||||
width: 651px;`}
|
||||
` |
||||
|
||||
export const PopupHeader = styled.div` |
||||
flex: 0 0 auto; |
||||
${isMobileDevice |
||||
? css` |
||||
height: auto; |
||||
padding: 12px 0px 0px 0px; |
||||
margin-bottom: 14px;` |
||||
: css` |
||||
height: 50px; |
||||
padding: 17px 22px 0px 22px;`}
|
||||
` |
||||
|
||||
export const CloseButtonContainer = styled.div` |
||||
position: absolute; |
||||
top: 14px; |
||||
right: 12px; |
||||
|
||||
${BaseButton} { |
||||
top: -4px; |
||||
right:0 ; |
||||
} |
||||
` |
||||
|
||||
export const HeaderText = styled.div` |
||||
font-family: 'Montserrat'; |
||||
font-style: normal; |
||||
font-weight: 700; |
||||
text-transform: uppercase; |
||||
|
||||
color: #FFFFFF; |
||||
${isMobileDevice |
||||
? css` |
||||
font-size: 12px; |
||||
line-height: 15px; |
||||
text-align: center;` |
||||
: css` |
||||
font-size: 18px; |
||||
line-height: 22px; |
||||
margin-bottom: 21px;`}
|
||||
` |
||||
|
||||
export const PartBlock = styled.div` |
||||
flex: 1 0 auto; |
||||
border-bottom: 1px solid #505050; |
||||
padding: 17px 22px 17px 22px; |
||||
` |
||||
|
||||
export const ItemsContainer = styled.ul` |
||||
display: flex; |
||||
flex-direction: row; |
||||
flex-wrap: wrap; |
||||
` |
||||
|
||||
export const MainCheckboxContainer = styled.div` |
||||
margin-bottom: 15px; |
||||
display: flex; |
||||
` |
||||
|
||||
export const ItemBlock = styled.div` |
||||
flex: 0 0 33.33%; |
||||
margin-bottom: 4px; |
||||
|
||||
${isMobileDevice |
||||
? css` |
||||
flex: 0 0 50%;` |
||||
: css` |
||||
flex: 0 0 33.33%;`}
|
||||
` |
||||
|
||||
export const Checkbox = styled(BaseCheckbox)` |
||||
height: 28px; |
||||
display: block; |
||||
|
||||
${Label} { |
||||
height: 100%; |
||||
font-style: normal; |
||||
font-weight: 400; |
||||
|
||||
${isMobileDevice |
||||
? css` |
||||
font-size: 12px; |
||||
line-height: 18px;` |
||||
: css` |
||||
font-size: 14px; |
||||
line-height: 16px;`}
|
||||
|
||||
${({ checked }) => (checked |
||||
? css`` |
||||
: css` |
||||
color: rgba(255, 255, 255, 0.6);` |
||||
)} |
||||
} |
||||
|
||||
${CheckboxSvg} { |
||||
margin-right: 8px; |
||||
width: 20px; |
||||
height: 20px; |
||||
} |
||||
` |
||||
|
||||
export const ItemText = styled.div` |
||||
display: flex; |
||||
height: 100%; |
||||
align-items: center; |
||||
|
||||
${NameStyled} { |
||||
white-space: nowrap; |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
width: 130px; |
||||
} |
||||
|
||||
${isMobileDevice |
||||
? css` |
||||
width: 110px;` |
||||
: css` |
||||
width: 130px;`}
|
||||
` |
||||
|
||||
export const TeamBlock = styled.div`` |
||||
|
||||
export const ButtonConatiner = styled.div` |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
flex: 0 0 66px; |
||||
|
||||
${isMobileDevice |
||||
? css` |
||||
position: fixed; |
||||
bottom: 14px; |
||||
left: 50%; |
||||
transform: translate(-50%, 0);` |
||||
: css``} |
||||
` |
||||
|
||||
export const Button = styled.button` |
||||
height: 41px; |
||||
background: #294FC4; |
||||
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); |
||||
border-radius: 5px; |
||||
border: none; |
||||
cursor: pointer; |
||||
font-size: 15px; |
||||
line-height: 50px; |
||||
font-weight: 600; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
color: #ffff; |
||||
|
||||
${isMobileDevice |
||||
? css` |
||||
width: 301px;` |
||||
: css` |
||||
width: 167px;`}
|
||||
` |
||||
export const PlayerNumber = styled.span` |
||||
margin-right: 8px; |
||||
font-size: 11px; |
||||
line-height: 16px; |
||||
font-weight: 600; |
||||
` |
||||
Loading…
Reference in new issue