Ott 283 matches list changes (#81)

keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
Ruslan Khayrullin 5 years ago committed by GitHub
parent 22d93b845c
commit 53cd031d5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/config/lexics/indexLexics.tsx
  2. 12
      src/features/HeaderFilters/components/DateFilter/index.tsx
  3. 8
      src/features/HeaderFilters/components/MatchStatusFilter/styled.tsx
  4. 15
      src/features/HeaderFilters/components/SportTypeFilter/index.tsx
  5. 4
      src/features/HeaderFilters/components/SportTypeFilter/styled.tsx
  6. 9
      src/features/HeaderFilters/components/TournamentFilter/index.tsx
  7. 8
      src/features/HeaderFilters/components/TournamentList/index.tsx
  8. 2
      src/features/HeaderFilters/store/hooks/index.tsx
  9. 45
      src/features/HomePage/components/Matches/hooks.tsx
  10. 22
      src/features/HomePage/components/Matches/index.tsx
  11. 10
      src/features/HomePage/index.tsx
  12. 9
      src/features/HomePage/styled.tsx
  13. 4
      src/features/LanguageSelect/index.tsx
  14. 4
      src/features/LanguageSelect/styled.tsx
  15. 6
      src/features/MatchCard/CardFinished/index.tsx
  16. 0
      src/features/MatchCard/CardFinishedHover/index.tsx
  17. 6
      src/features/MatchCard/CardLive/index.tsx
  18. 0
      src/features/MatchCard/CardLiveHover/index.tsx
  19. 6
      src/features/MatchCard/CardSoon/index.tsx
  20. 0
      src/features/MatchCard/config/index.tsx
  21. 6
      src/features/MatchCard/index.tsx
  22. 3
      src/features/MatchCard/styled.tsx
  23. 59
      src/features/Matches/index.tsx
  24. 14
      src/features/Matches/styled.tsx
  25. 18
      src/features/MatchesGrid/index.tsx
  26. 9
      src/features/MatchesGrid/styled.tsx
  27. 3
      src/features/MatchesSlider/hooks.tsx
  28. 2
      src/features/MatchesSlider/index.tsx
  29. 8
      src/features/Menu/index.tsx
  30. 2
      src/features/Menu/styled.tsx
  31. 6
      src/features/ToggleScore/index.tsx
  32. 2
      src/features/UserFavorites/styled.tsx
  33. 2
      src/requests/getMatches.tsx

@ -2,6 +2,8 @@ import { proceduresLexics } from './procedures'
export const indexLexics = { export const indexLexics = {
basketball: 6960, basketball: 6960,
broadcast: 13049,
features: 13051,
football: 6958, football: 6958,
full_game: 13028, full_game: 13028,
game_finished: 13026, game_finished: 13026,
@ -20,6 +22,8 @@ export const indexLexics = {
match_video: 13025, match_video: 13025,
player: 630, player: 630,
players_video: 13032, players_video: 13032,
round_highilights: 13050,
select_language: 1005,
sport: 12993, sport: 12993,
team: 658, team: 658,
tournament: 1009, tournament: 1009,

@ -29,7 +29,11 @@ export const DateFilter = () => {
} = useDateFilter() } = useDateFilter()
return ( return (
<Wrapper active={isOpen}> <Wrapper active={isOpen}>
<Button onClick={onPreviousClick} borderLeftRadius={2}> <Button
onClick={onPreviousClick}
borderLeftRadius={2}
aria-label='Previous day'
>
<ArrowLeft /> <ArrowLeft />
</Button> </Button>
<OutsideClick onClick={close}> <OutsideClick onClick={close}>
@ -46,7 +50,11 @@ export const DateFilter = () => {
onChange={onDateChange} onChange={onDateChange}
/> />
</OutsideClick> </OutsideClick>
<Button onClick={onNextClick} borderRightRadius={2}> <Button
onClick={onNextClick}
borderRightRadius={2}
aria-label='Next day'
>
<ArrowRight /> <ArrowRight />
</Button> </Button>
</Wrapper> </Wrapper>

@ -1,6 +1,8 @@
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
export const RadioButtonGroup = styled.div` export const RadioButtonGroup = styled.div.attrs({
role: 'group',
})`
height: 100%; height: 100%;
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
border-radius: 2px; border-radius: 2px;
@ -12,7 +14,9 @@ type RadioButtonProps = {
selected?: boolean, selected?: boolean,
} }
export const RadioButton = styled.button<RadioButtonProps>` export const RadioButton = styled.button.attrs(({ selected }: RadioButtonProps) => ({
'aria-pressed': selected,
}))<RadioButtonProps>`
border: none; border: none;
outline: none; outline: none;
height: 100%; height: 100%;

@ -29,7 +29,12 @@ export const SportTypeFilter = () => {
return ( return (
<Wrapper> <Wrapper>
<DropdownButton active={isOpen} onClick={open}> <DropdownButton
active={isOpen}
onClick={open}
aria-expanded={isOpen}
aria-controls='sportList'
>
<ButtonTitle> <ButtonTitle>
<T9n t={selectedSportType?.lexic || 'sport'} /> <T9n t={selectedSportType?.lexic || 'sport'} />
</ButtonTitle> </ButtonTitle>
@ -39,7 +44,7 @@ export const SportTypeFilter = () => {
{ {
isOpen && ( isOpen && (
<OutsideClick onClick={close}> <OutsideClick onClick={close}>
<SportList> <SportList id='sportList' role='listbox'>
{ {
map(sportList, ({ map(sportList, ({
id, id,
@ -48,10 +53,12 @@ export const SportTypeFilter = () => {
}) => ( }) => (
<CustomOption <CustomOption
key={id} key={id}
t={lexic}
image={name} image={name}
onClick={() => onSelect(id)} onClick={() => onSelect(id)}
/> role='option'
>
<T9n t={lexic} />
</CustomOption>
)) ))
} }
</SportList> </SportList>

@ -1,7 +1,5 @@
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { T9n } from 'features/T9n'
import { DropdownButton } from '../TournamentFilter/styled' import { DropdownButton } from '../TournamentFilter/styled'
export const Wrapper = styled.div` export const Wrapper = styled.div`
@ -27,7 +25,7 @@ export const SportList = styled.ul`
z-index: 1; z-index: 1;
` `
export const CustomOption = styled(T9n)<{ image: string }>` export const CustomOption = styled.li<{ image: string }>`
width: 100%; width: 100%;
height: 48px; height: 48px;
display: flex; display: flex;

@ -24,7 +24,12 @@ export const TournamentFilter = () => {
} = useTournamentFilter() } = useTournamentFilter()
return ( return (
<Wrapper> <Wrapper>
<DropdownButton onClick={open} active={isOpen}> <DropdownButton
onClick={open}
active={isOpen}
aria-expanded={isOpen}
aria-controls='tournamentsList'
>
<ButtonTitle> <ButtonTitle>
{ {
selectedTournament selectedTournament
@ -37,7 +42,7 @@ export const TournamentFilter = () => {
{ {
isOpen && ( isOpen && (
<OutsideClick onClick={close}> <OutsideClick onClick={close}>
<ListWrapper> <ListWrapper id='tournamentsList'>
<TournamentList <TournamentList
tournaments={tournaments} tournaments={tournaments}
onSelect={onTournamentSelect} onSelect={onTournamentSelect}

@ -37,7 +37,7 @@ export const TournamentList = ({ onSelect, tournaments }: TournamentListProps) =
} = useItemsList() } = useItemsList()
return ( return (
<Wrapper ref={ref}> <Wrapper ref={ref} role='listbox'>
{map(tournaments, ({ {map(tournaments, ({
color, color,
country, country,
@ -47,7 +47,11 @@ export const TournamentList = ({ onSelect, tournaments }: TournamentListProps) =
name, name,
sportLexic, sportLexic,
}) => ( }) => (
<ListItem key={id} onClick={() => onSelect(id)}> <ListItem
key={id}
onClick={() => onSelect(id)}
role='option'
>
<LogoWrapper> <LogoWrapper>
<Logo <Logo
data-src={logo} data-src={logo}

@ -57,6 +57,7 @@ export const useFilters = () => {
broadcast: [], broadcast: [],
features: [], features: [],
highlights: [], highlights: [],
isVideoSections: false,
}) })
// временно здесь запрашиваются матчи при изменении фильтров, // временно здесь запрашиваются матчи при изменении фильтров,
@ -119,6 +120,7 @@ export const useFilters = () => {
broadcast: prepareMatches(matches.broadcast), broadcast: prepareMatches(matches.broadcast),
features: prepareMatches(matches.features), features: prepareMatches(matches.features),
highlights: prepareMatches(matches.highlights), highlights: prepareMatches(matches.highlights),
isVideoSections: matches.isVideoSections,
} }
const store = useMemo(() => ({ const store = useMemo(() => ({

@ -1,45 +0,0 @@
import size from 'lodash/size'
import slice from 'lodash/slice'
import chunk from 'lodash/chunk'
import type { Match } from 'features/HeaderFilters'
import { useHeaderFiltersStore } from 'features/HeaderFilters'
const MATCHES_PER_ROW = 6
const ROWS_COUNT = 3
export const useMatches = () => {
const {
matches: {
broadcast: matchesList,
},
} = useHeaderFiltersStore()
const matchesCount = size(matchesList)
let groupedMatches: Array<Array<Match>> = []
/**
* Распределяем матчи в ROWS_COUNT рядов
* Если общее количество матчей не больше количества
* ячеек в сетке размера ROWS_COUNT x MATCHES_PER_ROW,
* заполняем по максимуму каждый ряд с MATCHES_PER_ROW
* матчей в каждом, иначе распределяем поровну
*/
if (matchesCount <= MATCHES_PER_ROW * ROWS_COUNT) {
for (let i = 0; i < ROWS_COUNT; i++) {
const matches = slice(
matchesList,
i * MATCHES_PER_ROW,
i * MATCHES_PER_ROW + MATCHES_PER_ROW,
)
groupedMatches.push(matches)
}
} else {
groupedMatches = chunk(matchesList, Math.ceil(matchesCount / ROWS_COUNT))
}
return {
groupedMatches,
}
}

@ -1,22 +0,0 @@
import React, { Fragment } from 'react'
import map from 'lodash/map'
import { MatchesSlider } from 'features/MatchesSlider'
import { useMatches } from './hooks'
export const Matches = () => {
const { groupedMatches } = useMatches()
return (
<Fragment>
{map(groupedMatches, (matches, i) => (
<MatchesSlider
key={i}
matches={matches}
/>
))}
</Fragment>
)
}

@ -13,14 +13,9 @@ import {
HeaderFiltersStore, HeaderFiltersStore,
} from 'features/HeaderFilters' } from 'features/HeaderFilters'
import { UserFavorites } from 'features/UserFavorites' import { UserFavorites } from 'features/UserFavorites'
import { T9n } from 'features/T9n' import { Matches } from 'features/Matches'
import { Matches } from './components/Matches' import { FilterWrapper, Content } from './styled'
import {
FilterWrapper,
Title,
Content,
} from './styled'
export const HomePage = () => { export const HomePage = () => {
useLexicsConfig(homeLexics) useLexicsConfig(homeLexics)
@ -48,7 +43,6 @@ export const HomePage = () => {
</FilterWrapper> </FilterWrapper>
</Header> </Header>
<Content> <Content>
<Title><T9n t='video_from_my_subscriptions' /></Title>
<Matches /> <Matches />
</Content> </Content>
</MainWrapper> </MainWrapper>

@ -11,12 +11,3 @@ export const Content = styled.main`
margin-top: 75px; margin-top: 75px;
padding: 0 16px; padding: 0 16px;
` `
export const Title = styled.h1`
margin-bottom: 17px;
font-weight: bold;
font-size: 36px;
line-height: 24px;
letter-spacing: -0.02em;
color: #fff;
`

@ -37,9 +37,11 @@ export const LanguageSelect = () => {
onClick={open} onClick={open}
active={isOpen} active={isOpen}
title={translate('select_language')} title={translate('select_language')}
aria-expanded={isOpen}
aria-controls='langsList'
/> />
{isOpen && ( {isOpen && (
<LangsList> <LangsList id='langsList'>
{ {
map( map(
langsList, langsList,

@ -10,10 +10,12 @@ type WorldIconProps = {
active?: boolean, active?: boolean,
} }
export const WorldIcon = styled.span<WorldIconProps>` export const WorldIcon = styled.button<WorldIconProps>`
display: block; display: block;
width: 18px; width: 18px;
height: 18px; height: 18px;
border: none;
background: none;
background-image: url(/images/worldIcon.svg); background-image: url(/images/worldIcon.svg);
background-position-x: -1px; background-position-x: -1px;
cursor: pointer; cursor: pointer;

@ -68,14 +68,14 @@ export const CardFinished = ({
</PreviewWrapper> </PreviewWrapper>
<Info> <Info>
<SportName t={sportName} color={getSportColor(sportType)} /> <SportName t={sportName} color={getSportColor(sportType)} />
<TournamentName>{tournamentName}</TournamentName> <TournamentName title={tournamentName}>{tournamentName}</TournamentName>
<Teams> <Teams>
<Team> <Team>
<TeamName>{team1Name}</TeamName> <TeamName title={team1Name}>{team1Name}</TeamName>
<Score>{team1Score}</Score> <Score>{team1Score}</Score>
</Team> </Team>
<Team> <Team>
<TeamName>{team2Name}</TeamName> <TeamName title={team2Name}>{team2Name}</TeamName>
<Score>{team2Score}</Score> <Score>{team2Score}</Score>
</Team> </Team>
</Teams> </Teams>

@ -92,14 +92,14 @@ export const CardLive = ({
</PreviewWrapper> </PreviewWrapper>
<Info> <Info>
<SportName t={sportName} color={getSportColor(sportType)} /> <SportName t={sportName} color={getSportColor(sportType)} />
<TournamentName>{tournamentName}</TournamentName> <TournamentName title={tournamentName}>{tournamentName}</TournamentName>
<Teams> <Teams>
<Team> <Team>
<TeamName>{team1Name}</TeamName> <TeamName title={team1Name}>{team1Name}</TeamName>
<Score>{team1Score}</Score> <Score>{team1Score}</Score>
</Team> </Team>
<Team> <Team>
<TeamName>{team2Name}</TeamName> <TeamName title={team2Name}>{team2Name}</TeamName>
<Score>{team2Score}</Score> <Score>{team2Score}</Score>
</Team> </Team>
</Teams> </Teams>

@ -87,13 +87,13 @@ export const CardSoon = ({
</PreviewWrapper> </PreviewWrapper>
<Info> <Info>
<SportName t={sportName} color={getSportColor(sportType)} /> <SportName t={sportName} color={getSportColor(sportType)} />
<TournamentName>{tournamentName}</TournamentName> <TournamentName title={tournamentName}>{tournamentName}</TournamentName>
<Teams> <Teams>
<Team> <Team>
<TeamName>{team1Name}</TeamName> <TeamName title={team1Name}>{team1Name}</TeamName>
</Team> </Team>
<Team> <Team>
<TeamName>{team2Name}</TeamName> <TeamName title={team2Name}>{team2Name}</TeamName>
</Team> </Team>
</Teams> </Teams>
</Info> </Info>

@ -3,9 +3,9 @@ import React from 'react'
import type { Match } from 'features/HeaderFilters' import type { Match } from 'features/HeaderFilters'
import { MatchStatuses } from 'features/HeaderFilters' import { MatchStatuses } from 'features/HeaderFilters'
import { CardLive } from '../CardLive' import { CardLive } from './CardLive'
import { CardFinished } from '../CardFinished' import { CardFinished } from './CardFinished'
import { CardSoon } from '../CardSoon' import { CardSoon } from './CardSoon'
type MatchCardProps = { type MatchCardProps = {
match: Match, match: Match,

@ -2,7 +2,7 @@ import styled from 'styled-components/macro'
import { T9n } from 'features/T9n' import { T9n } from 'features/T9n'
import { MATCH_CARD_WIDTH, MATCH_CARD_GAP } from '../config' import { MATCH_CARD_WIDTH, MATCH_CARD_GAP } from './config'
export const CardWrapper = styled.li.attrs({ export const CardWrapper = styled.li.attrs({
tabIndex: 0, tabIndex: 0,
@ -42,6 +42,7 @@ export const MatchStatus = styled.div`
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.1em; letter-spacing: 0.1em;
text-align: center; text-align: center;
white-space: nowrap;
` `
export const Info = styled.div` export const Info = styled.div`

@ -0,0 +1,59 @@
import React, { Fragment } from 'react'
import isEmpty from 'lodash/isEmpty'
import { useHeaderFiltersStore } from 'features/HeaderFilters'
import { MatchesSlider } from 'features/MatchesSlider'
import { MatchesGrid } from 'features/MatchesGrid'
import { T9n } from 'features/T9n'
import { Title, Section } from './styled'
export const Matches = () => {
const {
matches: {
broadcast,
features,
highlights,
isVideoSections,
},
} = useHeaderFiltersStore()
if (isVideoSections) {
return (
<Fragment>
{!isEmpty(broadcast) && (
<Section>
<Title><T9n t='broadcast' /></Title>
<MatchesSlider matches={broadcast} />
</Section>
)}
{!isEmpty(highlights) && (
<Section>
<Title><T9n t='round_highilights' /></Title>
<MatchesSlider matches={highlights} />
</Section>
)}
{!isEmpty(features) && (
<Section>
<Title><T9n t='features' /></Title>
<MatchesSlider matches={highlights} />
</Section>
)}
</Fragment>
)
}
return (
<Fragment>
{!isEmpty(broadcast) && (
<Section>
<Title><T9n t='broadcast' /></Title>
<MatchesGrid matches={broadcast} />
</Section>
)}
</Fragment>
)
}

@ -0,0 +1,14 @@
import styled from 'styled-components/macro'
export const Section = styled.section`
margin-bottom: 30px;
`
export const Title = styled.h2`
margin-bottom: 17px;
font-weight: bold;
font-size: 36px;
line-height: 24px;
letter-spacing: -0.02em;
color: #fff;
`

@ -0,0 +1,18 @@
import React from 'react'
import map from 'lodash/map'
import type { Match } from 'features/HeaderFilters'
import { MatchCard } from 'features/MatchCard'
import { Wrapper } from './styled'
type MatchesGridProps = {
matches: Array<Match>,
}
export const MatchesGrid = ({ matches }: MatchesGridProps) => (
<Wrapper>
{map(matches, (match) => <MatchCard key={match.id} match={match} />)}
</Wrapper>
)

@ -0,0 +1,9 @@
import styled from 'styled-components/macro'
import { MATCH_CARD_WIDTH } from 'features/MatchCard/config'
export const Wrapper = styled.ul`
display: grid;
grid-template-columns: repeat(6, ${MATCH_CARD_WIDTH}px);
grid-gap: 13px;
`

@ -7,10 +7,9 @@ import {
} from 'react' } from 'react'
import type { Match } from 'features/HeaderFilters' import type { Match } from 'features/HeaderFilters'
import { MATCH_CARD_WIDTH, MATCH_CARD_GAP } from 'features/MatchCard/config'
import { useToggle } from 'hooks' import { useToggle } from 'hooks'
import { MATCH_CARD_WIDTH, MATCH_CARD_GAP } from './config'
export const useCard = () => { export const useCard = () => {
const { const {
close, close,

@ -4,9 +4,9 @@ import map from 'lodash/map'
import isEmpty from 'lodash/isEmpty' import isEmpty from 'lodash/isEmpty'
import type { Match } from 'features/HeaderFilters' import type { Match } from 'features/HeaderFilters'
import { MatchCard } from 'features/MatchCard'
import { useMatchesSlider } from './hooks' import { useMatchesSlider } from './hooks'
import { MatchCard } from './components/MatchCard'
import { import {
Wrapper, Wrapper,
Arrow, Arrow,

@ -27,9 +27,13 @@ export const Menu = () => {
return ( return (
<OutsideClick onClick={close}> <OutsideClick onClick={close}>
<Wrapper> <Wrapper>
<ToggleButton onClick={open} /> <ToggleButton
onClick={open}
aria-expanded={isOpen}
aria-controls='menuList'
/>
{isOpen && ( {isOpen && (
<MenuList> <MenuList id='menuList'>
<MenuItem> <MenuItem>
<Icon image='userAccount' /> <Icon image='userAccount' />
<StyledLink to={PAGES.useraccount}> <StyledLink to={PAGES.useraccount}>

@ -2,7 +2,7 @@ import { Link } from 'react-router-dom'
import styled, { css } from 'styled-components/macro' import styled, { css } from 'styled-components/macro'
export const Wrapper = styled.div` export const Wrapper = styled.nav`
position: relative; position: relative;
display: flex; display: flex;
justify-content: center; justify-content: center;

@ -12,7 +12,11 @@ export * from './store'
export const ToggleScore = () => { export const ToggleScore = () => {
const { isVisible, toggle } = useScoreStore() const { isVisible, toggle } = useScoreStore()
return ( return (
<Switch onClick={toggle}> <Switch
onClick={toggle}
role='switch'
aria-checked={isVisible}
>
<Title t='hide_score' /> <Title t='hide_score' />
<Icon isOn={isVisible} /> <Icon isOn={isVisible} />
</Switch> </Switch>

@ -7,7 +7,7 @@ import { TooltipBlockWrapper } from './TooltipBlock/styled'
export const StyledLink = styled(Link)`` export const StyledLink = styled(Link)``
export const UserSportFavWrapper = styled.div` export const UserSportFavWrapper = styled.aside`
position: fixed; position: fixed;
left: 0; left: 0;
top: 0; top: 0;

@ -60,6 +60,7 @@ export type Matches = {
broadcast: Array<Content>, broadcast: Array<Content>,
features: Array<Content>, features: Array<Content>,
highlights: Array<Content>, highlights: Array<Content>,
isVideoSections: boolean,
} }
export const getMatches = async ({ export const getMatches = async ({
@ -95,5 +96,6 @@ export const getMatches = async ({
broadcast: broadcast.content || [], broadcast: broadcast.content || [],
features: features.content || [], features: features.content || [],
highlights: highlights.content || [], highlights: highlights.content || [],
isVideoSections: data.is_video_sections,
} }
} }

Loading…
Cancel
Save