feat(ott-142): sport type filter (#59)

keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
Ruslan Khayrullin 5 years ago committed by GitHub
parent 7e765341f5
commit e6873a698f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      public/images/arrowUp.svg
  2. 9
      public/images/basketball.svg
  3. 12
      public/images/football.svg
  4. 6
      public/images/hockey.svg
  5. 5
      src/config/lexics/authenticated.tsx
  6. 5
      src/config/lexics/procedures.tsx
  7. 1
      src/config/procedures.tsx
  8. 32
      src/features/Combobox/components/Arrow/index.tsx
  9. 8
      src/features/Combobox/hooks/index.tsx
  10. 17
      src/features/Combobox/index.tsx
  11. 20
      src/features/Combobox/styled.tsx
  12. 12
      src/features/Combobox/types.tsx
  13. 11
      src/features/Common/customStyles/index.tsx
  14. 1
      src/features/Common/index.tsx
  15. 45
      src/features/HeaderFilters/components/SportTypeFilter/hooks.tsx
  16. 26
      src/features/HeaderFilters/components/SportTypeFilter/index.tsx
  17. 61
      src/features/HeaderFilters/components/SportTypeFilter/styled.tsx
  18. 4
      src/features/HeaderFilters/store/hooks/index.tsx
  19. 24
      src/requests/getSportList.tsx

@ -0,0 +1,3 @@
<svg width="12" height="8" viewBox="0 0 12 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.6 8L6 3.4L1.4 8L0 6.6L6 0.6L12 6.6L10.6 8Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 213 B

@ -0,0 +1,9 @@
<svg width="19" height="24" viewBox="0 0 19 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.3517 4.14362C16.7741 2.89876 16.1076 1.54656 14.8627 1.12411C13.6178 0.701653 12.2656 1.36823 11.8432 2.61309C11.4207 3.85794 12.0873 5.21014 13.3322 5.63259C14.577 6.05505 15.9275 5.38847 16.3517 4.14362Z" stroke="white" stroke-width="0.5" stroke-miterlimit="10"/>
<path d="M6.45344 14.9231L5.29688 16.7861L1.41342 17.0129C0.829951 16.9731 0.324391 17.4163 0.291495 18.0015C0.258599 18.585 0.707024 19.0819 1.28876 19.1113L6.39111 18.9641C6.69237 18.978 6.97631 18.8274 7.13214 18.5711L8.01514 16.8467" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M15.9085 19.1078C17.0636 19.1078 17.9999 18.1714 17.9999 17.0163C17.9999 15.8612 17.0636 14.9248 15.9085 14.9248C14.7533 14.9248 13.817 15.8612 13.817 17.0163C13.817 18.1714 14.7533 19.1078 15.9085 19.1078Z" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M15.9084 18.069C15.3284 18.069 14.8558 17.5964 14.8558 17.0164C14.8558 16.4363 15.3284 15.9637 15.9084 15.9637C16.4885 15.9637 16.9611 16.4363 16.9611 17.0164C16.9611 17.5964 16.4885 18.069 15.9084 18.069Z" fill="#F1903B"/>
<path d="M15.0705 20.1294C15.628 20.4202 16.3309 20.4168 16.8849 20.1207" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M14.2896 21.1543C14.8246 21.4815 15.4531 21.6547 16.0816 21.646C16.7084 21.6374 17.3334 21.4487 17.8597 21.1076" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M11.5436 12.1114L9.8746 14.6894L11.6718 17.0804C11.8674 17.3401 11.9297 17.6778 11.8414 17.9911L10.6018 22.3784C10.4338 22.9723 9.81747 23.3168 9.22361 23.1489C8.62975 22.9809 8.2852 22.3646 8.45315 21.7707L9.3777 18.4967L6.59885 15.1205C6.15042 14.5769 5.99806 13.8462 6.19025 13.1675C6.23699 13.0031 6.30278 12.8455 6.38589 12.6983L9.49543 7.17007C10.0685 6.1451 11.3653 5.77978 12.3903 6.35287C12.5634 6.44982 12.7106 6.57621 12.8526 6.70087C13.1036 6.92249 13.2352 7.2376 13.2975 7.55617C13.4153 8.14657 13.2889 8.75947 12.9876 9.28061L12.9651 9.32043L14.3571 11.5539L16.317 11.9885C16.7429 12.0837 17.0113 12.5062 16.9143 12.9321C16.8174 13.3563 16.3949 13.6212 15.9725 13.5242L13.9122 13.0533C13.6438 12.9927 13.4066 12.8403 13.2404 12.6222L10.7005 9.32043" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@ -0,0 +1,12 @@
<svg width="23" height="25" viewBox="0 0 23 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19.9843 17.7664L20.799 15.7761" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M21.0723 18.2114L22.7472 16.8641" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M18.828 17.2934L18.5775 15.1559" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M12.8519 3.53313C12.9202 2.20511 11.8988 1.07157 10.5708 1.00324C9.2428 0.93491 8.10925 1.95633 8.04093 3.28434C7.9726 4.61236 8.99402 5.7459 10.322 5.81423C11.6483 5.88431 12.7818 4.8629 12.8519 3.53313Z" stroke="white" stroke-width="0.5" stroke-miterlimit="10"/>
<path d="M10.1434 13.3514L9.44431 15.5834L11.8516 17.4178C12.1144 17.6175 12.2668 17.9276 12.2668 18.257V22.87C12.2668 23.4937 11.7605 24 11.1367 24C10.513 24 10.0067 23.4937 10.0067 22.87V19.4273L6.3713 16.9044C5.78438 16.498 5.43573 15.8287 5.43573 15.1156C5.43573 14.9439 5.45675 14.7722 5.49705 14.604L7.00377 8.36516C7.28059 7.20884 8.44216 6.49753 9.59848 6.77435C9.79471 6.82165 9.97692 6.89348 10.1451 6.98634C10.8056 7.35426 11.1753 8.08659 11.1437 8.84171V8.84521" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M9.47057 8.23026L12.0863 11.6572L14.0643 12.1179C14.4953 12.2178 14.7616 12.6488 14.6582 13.0798C14.5549 13.5073 14.1256 13.7718 13.6982 13.6685L11.6185 13.1709C11.3487 13.1061 11.1087 12.9501 10.9423 12.7276L8.41061 9.35854" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M5.41467 10.9739L4.84702 11.3926L4.35471 13.3636C4.24784 13.7929 3.81159 14.0522 3.3841 13.9418C2.95837 13.8332 2.70082 13.3987 2.8112 12.9729L3.33154 10.9459C3.40688 10.6498 3.59434 10.394 3.85364 10.231L7.04403 8.23026" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M6.17855 16.7537L5.56535 18.8859L1.84585 20.1754C1.26594 20.2963 0.89627 20.8692 1.02592 21.4473C1.15381 22.0237 1.72672 22.3864 2.30313 22.2533L7.23151 20.7062C7.52759 20.6379 7.76411 20.4119 7.84471 20.1193L8.23015 18.1974" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M18.2428 24C19.7687 24 21.0057 22.763 21.0057 21.2371C21.0057 19.7112 19.7687 18.4742 18.2428 18.4742C16.7169 18.4742 15.4799 19.7112 15.4799 21.2371C15.4799 22.763 16.7169 24 18.2428 24Z" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M18.2428 19.5254C17.931 19.5254 17.6384 19.6112 17.3861 19.7567C17.8977 20.0527 18.2428 20.6046 18.2428 21.2371C18.2428 21.8696 17.8977 22.4214 17.3861 22.7175C17.6384 22.8647 17.931 22.9488 18.2428 22.9488C19.1872 22.9488 19.9545 22.1814 19.9545 21.2371C19.9545 20.2945 19.1854 19.5254 18.2428 19.5254Z" fill="#00A435"/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

@ -0,0 +1,6 @@
<svg width="29" height="23" viewBox="0 0 29 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M22.1319 4.47993C22.4241 3.14234 21.5766 1.82117 20.239 1.52901C18.9014 1.23685 17.5803 2.08433 17.2881 3.42192C16.9959 4.75951 17.8434 6.08069 19.181 6.37285C20.5186 6.66501 21.8398 5.81752 22.1319 4.47993Z" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M19.7093 5.16244C19.0415 5.16244 18.4984 4.61932 18.4984 3.95151C18.4984 3.2837 19.0415 2.74057 19.7093 2.74057C20.3771 2.74057 20.9203 3.2837 20.9203 3.95151C20.9203 4.61932 20.3771 5.16244 19.7093 5.16244Z" fill="#5EB2FF"/>
<path d="M21.6007 14.7654C22.0488 14.4167 22.1629 13.7869 21.8691 13.3009L19.6734 9.69766L19.462 7.74283" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16.385 10.9509L14.9247 12.1618C14.6056 12.4175 14.5211 12.8655 14.724 13.2206L16.4823 16.2891C16.6534 16.5871 16.6851 16.9464 16.571 17.2697L15.0198 21.6549C14.8339 22.1832 14.3351 22.534 13.7751 22.534C12.8494 22.534 12.2112 21.6063 12.543 20.7419L13.7117 17.6945C13.8448 17.3479 13.8068 16.959 13.6102 16.6463L11.9534 14.1335L8.74113 16.9886C8.35862 17.2824 7.84931 17.35 7.4034 17.1683L1.89395 14.9366C1.15428 14.6365 0.801356 13.7869 1.11413 13.0515C1.42267 12.3203 2.27012 11.98 2.99922 12.2928L6.95748 13.9962C7.47314 14.2181 8.07332 14.0046 8.33115 13.5038L8.83412 12.5295C9.52729 11.1918 10.455 9.99351 11.5772 8.98757L14.9543 5.91056C15.5524 5.36532 16.5161 5.68444 16.6703 6.47905L17.4523 10.488L23.7965 20.67C24.179 21.285 24.9947 21.4583 25.5949 21.0526L28.057 19.3746C28.5895 19.0132 28.7248 18.2862 28.3613 17.7558C27.9957 17.2232 27.2687 17.0901 26.7382 17.4578L24.6672 18.897" stroke="white" stroke-width="0.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -1,3 +1,5 @@
import { proceduresLexics } from './procedures'
export const authenticatedLexics = {
basketball: 6960,
football: 6958,
@ -8,7 +10,10 @@ export const authenticatedLexics = {
match_status_live: 12984,
match_status_soon: 12986,
player: 630,
sport: 12993,
team: 658,
tournament: 1009,
user_account: 12928,
...proceduresLexics,
}

@ -0,0 +1,5 @@
export const proceduresLexics = {
3556: 3556,
6959: 6959,
12980: 12980,
}

@ -4,6 +4,7 @@ export const PROCEDURES = {
get_cities: 'get_cities',
get_matches: 'get_matches',
get_players_teams_tournaments: 'get_players_teams_tournaments',
get_sport_list: 'get_sport_list',
get_user_favorites: 'get_user_favorites',
logout_user: 'logout_user',
lst_c_country: 'lst_c_country',

@ -0,0 +1,32 @@
import React from 'react'
import styled from 'styled-components/macro'
import { useComboboxContext } from '@reach/combobox'
const Wrapper = styled.div<{ isExpanded: boolean }>`
position: absolute;
right: 16px;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
background-size: 12px 12px;
background-image: url(/images/${({ isExpanded }) => (
isExpanded
? 'arrowUp.svg'
: 'arrowDown.svg'
)});
background-position: center;
background-repeat: no-repeat;
:hover {
cursor: pointer;
}
`
export const Arrow = () => {
const { isExpanded } = useComboboxContext()
return <Wrapper isExpanded={isExpanded} />
}

@ -29,7 +29,11 @@ const useQuery = <T extends Option>({ onChange, value }: Props<T>) => {
}
export const useCombobox = <T extends Option>(props: Props<T>) => {
const { onSelect, options } = props
const {
filterOptions = true,
onSelect,
options,
} = props
const {
onQueryChange,
@ -70,7 +74,7 @@ export const useCombobox = <T extends Option>(props: Props<T>) => {
onInputBlur,
onOptionSelect,
onQueryChange,
options: results,
options: filterOptions ? results : options,
query,
}
}

@ -19,11 +19,12 @@ import {
ComboboxPopoverStyled,
ComboboxListStyled,
ComboboxOptionStyled,
Arrow,
} from './styled'
import { Arrow } from './components/Arrow'
export const Combobox = <T extends Option>(props: Props<T>) => {
const {
customListStyles,
disabled,
error,
id,
@ -32,6 +33,7 @@ export const Combobox = <T extends Option>(props: Props<T>) => {
labelWidth,
openOnFocus,
pattern,
placeholder,
required,
title,
withArrow,
@ -74,15 +76,22 @@ export const Combobox = <T extends Option>(props: Props<T>) => {
onChange={onQueryChange}
onBlur={onInputBlur}
onKeyDown={onKeyDown}
placeholder={placeholder}
/>
{!isEmpty(options) && (
<ComboboxPopoverStyled>
<ComboboxListStyled ref={popoverRef}>
{map(options, ({ id: optionId, name }) => (
<ComboboxListStyled ref={popoverRef} customstyles={customListStyles}>
{map(options, ({
children,
id: optionId,
name,
}) => (
<ComboboxOptionStyled
key={optionId}
value={name}
/>
>
{children}
</ComboboxOptionStyled>
))}
</ComboboxListStyled>
</ComboboxPopoverStyled>

@ -9,7 +9,7 @@ import {
} from '@reach/combobox'
import { wrapperStyles, inputStyles } from 'features/Common/Input/styled'
import { сustomScrollbar } from 'features/Common'
import { сustomScrollbar, customStylesMixin } from 'features/Common'
export const ComboboxStyled = styled(Combobox)`
${wrapperStyles}
@ -21,23 +21,6 @@ export const ComboboxInputStyled = styled(ComboboxInput)`
padding-right: 24px;
`
export const Arrow = styled.div`
position: absolute;
right: 16px;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
background-size: 12px 12px;
background-image: url(/images/arrowDown.svg);
background-position: center;
background-repeat: no-repeat;
:hover {
cursor: pointer;
}
`
export const ComboboxPopoverStyled = styled(ComboboxPopover)`
border: none;
`
@ -55,6 +38,7 @@ export const ComboboxListStyled = styled(ComboboxList)`
overflow: auto;
${сustomScrollbar}
${customStylesMixin}
`
export const ComboboxOptionStyled = styled(ComboboxOption)`

@ -1,6 +1,13 @@
import type { InputHTMLAttributes, ChangeEvent } from 'react'
import type {
InputHTMLAttributes,
ChangeEvent,
ReactNode,
} from 'react'
import type { TCustomStyles } from 'features/Common'
export type Option = {
children?: ReactNode,
id: number,
name: string,
}
@ -12,8 +19,11 @@ export type Props<T> = Pick<InputHTMLAttributes<HTMLInputElement>, (
| 'disabled'
| 'pattern'
| 'title'
| 'placeholder'
)> & {
customListStyles?: TCustomStyles,
error?: string | null,
filterOptions?: boolean,
label?: string,
labelLexic?: string,
labelWidth?: number,

@ -0,0 +1,11 @@
import { css } from 'styled-components'
export type TCustomStyles = string | ReturnType<typeof css>
type TCustomStylesMixin = {
customstyles?: TCustomStyles,
}
export const customStylesMixin = css<TCustomStylesMixin>`
${({ customstyles }) => customstyles}
`

@ -4,3 +4,4 @@ export * from './Radio'
export * from './Checkbox'
export * from './Arrows'
export * from './сustomScrollbar'
export * from './customStyles'

@ -0,0 +1,45 @@
import React, { useState, useEffect } from 'react'
import map from 'lodash/map'
import type { SportList } from 'requests/getSportList'
import type { Option } from 'features/Combobox/types'
import { getSportList } from 'requests/getSportList'
import { useLexicsStore } from 'features/LexicsStore'
import { useHeaderFiltersStore } from 'features/HeaderFilters/store'
import { CustomOption } from './styled'
export const useSportTypeFilter = () => {
const [sportList, setSportList] = useState<SportList>([])
const { setSelectedSportTypes } = useHeaderFiltersStore()
const {
translate,
} = useLexicsStore()
useEffect(() => {
getSportList().then(setSportList)
}, [])
const options = map(sportList, ({
id,
lexic,
name,
}) => ({
children: <CustomOption t={lexic} image={name} />,
id,
name: translate(String(lexic)),
}))
const onSelect = (option: Option | null) => {
if (option) {
setSelectedSportTypes(option.id)
}
}
return {
onSelect,
options,
}
}

@ -1,5 +1,27 @@
import React from 'react'
import { Wrapper } from './styled'
import { Combobox } from 'features/Combobox'
export const SportTypeFilter = () => <Wrapper />
import { useLexicsStore } from 'features/LexicsStore'
import { useSportTypeFilter } from './hooks'
import { Wrapper, customListStyles } from './styled'
export const SportTypeFilter = () => {
const { onSelect, options } = useSportTypeFilter()
const { translate } = useLexicsStore()
return (
<Wrapper>
<Combobox
id='sportTypeFilter'
options={options}
placeholder={translate('sport')}
customListStyles={customListStyles}
filterOptions={false}
onSelect={onSelect}
openOnFocus
withArrow
/>
</Wrapper>
)
}

@ -1,3 +1,60 @@
import styled from 'styled-components/macro'
import styled, { css } from 'styled-components/macro'
export const Wrapper = styled.div``
import {
ComboboxStyled,
ComboboxInputStyled,
ComboboxOptionStyled,
} from 'features/Combobox/styled'
import { T9n } from 'features/T9n'
export const Wrapper = styled.div`
width: 50%;
${ComboboxStyled} {
margin-top: 0;
padding-left: 18px;
}
${ComboboxInputStyled} {
margin-left: 0;
overflow: hidden;
font-size: 18px;
&[aria-expanded="true"] {
::placeholder {
color: #fff;
}
}
&[aria-expanded="false"] {
::placeholder {
color: #999;
}
}
}
`
export const CustomOption = styled(T9n)<{ image: string }>`
display: flex;
align-items: center;
height: 100%;
::before {
content: '';
width: 58px;
height: 100%;
background-image: url(/images/${({ image }) => `${image}.svg`});
background-position: center;
background-repeat: no-repeat;
}
`
export const customListStyles = css`
left: -19px;
min-width: 460px;
${ComboboxOptionStyled} {
height: 56px;
padding-left: 0;
}
`

@ -21,8 +21,8 @@ export enum MatchStatuses {
export enum SportTypes {
Football = 1,
Basketball = 2,
Hockey = 3,
Basketball = 3,
Hockey = 2,
}
const dateFormat = 'dd/MM/yyyy HH:mm:ss'

@ -0,0 +1,24 @@
import { DATA_URL, PROCEDURES } from 'config'
import { callApi, getResponseData } from 'helpers'
const proc = PROCEDURES.get_sport_list
export type SportList = Array<{
id: number,
lexic: number,
name: string,
}>
export const getSportList = (): Promise<SportList> => {
const config = {
body: {
params: {},
proc,
},
}
return callApi({
config,
url: DATA_URL,
}).then(getResponseData(proc))
}
Loading…
Cancel
Save