Ott 511 profile link and name components (#200)

* Ott 511 profile link and name components part 1 (#195)

* refactor(#511): replaced profile links to ProfileLink component

* test(#511): added tests to getProfileUrl helper

* Ott 511 profile link and name components part 2 (#197)

* feat(#511): added Name component for displaying names

* refactor(#511): added using name as alt text in ProfileLogo

* refactor(#511): used Name in UserFavorites

* refactor(#511): used Name in header tournaments filter

* refactor(#511): used Name in search result

* fix(#515): pr fix

* fix(#515): renamed prop name

* Ott 511 profile link and name components part 3 (#199)

* refactor(#511): replaced names to Name in MatchProfile

* refactor(#511): replaced names in match cards to Name

* refactor(#511): replaced names in ProfileCard

* refactor(#511): pr fix
keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
Mirlan 5 years ago committed by GitHub
parent 6e63d05404
commit 8245c56b0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 26
      src/features/HeaderFilters/components/TournamentFilter/helpers.tsx
  2. 17
      src/features/HeaderFilters/components/TournamentFilter/hooks.tsx
  3. 3
      src/features/HeaderFilters/components/TournamentFilter/index.tsx
  4. 39
      src/features/HeaderFilters/components/TournamentList/index.tsx
  5. 52
      src/features/ItemsList/index.tsx
  6. 11
      src/features/ItemsList/styled.tsx
  7. 94
      src/features/MatchCard/CardSoon/index.tsx
  8. 18
      src/features/MatchCard/MatchInfoCard/index.tsx
  9. 3
      src/features/MatchCard/styled.tsx
  10. 91
      src/features/MatchPage/MatchProfileCard/index.tsx
  11. 5
      src/features/MatchPage/MatchProfileCard/styled.tsx
  12. 35
      src/features/MatchPage/hooks/useMatchProfile.tsx
  13. 21
      src/features/Matches/helpers/prepareMatches.tsx
  14. 11
      src/features/Matches/hooks.tsx
  15. 36
      src/features/Name/index.tsx
  16. 18
      src/features/PlayerPage/hooks.tsx
  17. 4
      src/features/PlayerPage/index.tsx
  18. 5
      src/features/ProfileCard/index.tsx
  19. 4
      src/features/ProfileCard/types.tsx
  20. 22
      src/features/ProfileLink/helpers/__tests__/index.tsx
  21. 0
      src/features/ProfileLink/helpers/index.tsx
  22. 43
      src/features/ProfileLink/index.tsx
  23. 14
      src/features/ProfileLogo/index.tsx
  24. 4
      src/features/Search/hooks/index.tsx
  25. 95
      src/features/Search/hooks/useNormalizedItems.tsx
  26. 21
      src/features/Search/index.tsx
  27. 18
      src/features/TeamPage/hooks.tsx
  28. 4
      src/features/TeamPage/index.tsx
  29. 16
      src/features/TournamentPage/hooks.tsx
  30. 4
      src/features/TournamentPage/index.tsx
  31. 59
      src/features/UserFavorites/TooltipBlock/index.tsx
  32. 5
      src/features/UserFavorites/TooltipBlock/styled.tsx
  33. 36
      src/features/UserFavorites/helpers.tsx
  34. 18
      src/features/UserFavorites/hooks/index.tsx
  35. 20
      src/features/UserFavorites/index.tsx
  36. 3
      src/features/UserFavorites/styled.tsx
  37. 1
      src/helpers/index.tsx
  38. 2
      src/requests/getUserSportFavs.tsx

@ -1,26 +0,0 @@
import map from 'lodash/map'
import { Tournaments } from 'requests'
import { ProfileTypes } from 'config'
type Name = 'name_rus' | 'name_eng'
type ShortName = 'short_name_rus' | 'short_name_eng'
export const normalizeTournaments = (tournaments: Tournaments, suffix: string) => (
map(tournaments, (tournament) => {
const profileType = ProfileTypes.TOURNAMENTS
const { id, sport: sportType } = tournament
const name = tournament[`name_${suffix}` as Name]
const shortName = tournament[`short_name_${suffix}` as ShortName] || name
const country = tournament.country?.[`name_${suffix}` as Name]
return {
country,
id,
name,
profileType,
shortName,
sportType,
}
})
)

@ -8,14 +8,9 @@ import { getSportTournaments } from 'requests'
import { useRequest, useToggle } from 'hooks'
import { useHeaderFiltersStore } from 'features/HeaderFilters'
import { useLexicsStore } from 'features/LexicsStore'
import { normalizeTournaments } from './helpers'
export const useTournamentFilter = () => {
const [list, setList] = useState<Tournaments>([])
const { suffix } = useLexicsStore()
const [tournaments, setTournaments] = useState<Tournaments>([])
const {
selectedSportTypeId,
@ -34,9 +29,9 @@ export const useTournamentFilter = () => {
const [page, setPage] = useState(0)
useEffect(() => {
setList([])
requestTournaments(selectedSportTypeId, 0).then((tournaments) => {
setList(tournaments)
setTournaments([])
requestTournaments(selectedSportTypeId, 0).then((newTournaments) => {
setTournaments(newTournaments)
setPage(1)
})
}, [selectedSportTypeId, requestTournaments])
@ -45,12 +40,10 @@ export const useTournamentFilter = () => {
if (isFetching) return
const newTournaments = await requestTournaments(selectedSportTypeId, page)
setList([...list, ...newTournaments])
setTournaments([...tournaments, ...newTournaments])
setPage(page + 1)
}
const tournaments = normalizeTournaments(list, suffix)
const selectedTournament = find(
tournaments,
(tournament) => tournament.id === selectedTournamentId,

@ -1,6 +1,7 @@
import React from 'react'
import { T9n } from 'features/T9n'
import { Name } from 'features/Name'
import { OutsideClick } from 'features/OutsideClick'
import { TournamentList } from '../TournamentList'
@ -36,7 +37,7 @@ export const TournamentFilter = () => {
<ButtonTitle>
{
selectedTournament
? selectedTournament.shortName
? <Name nameObj={selectedTournament} prefix='short_name_' />
: <T9n t='tournament' />
}
</ButtonTitle>

@ -2,7 +2,8 @@ import React from 'react'
import map from 'lodash/map'
import { SportTypes, ProfileTypes } from 'config'
import type { Tournaments } from 'requests'
import { ProfileTypes } from 'config'
import {
Logo,
@ -16,45 +17,31 @@ import { SportName } from 'features/Common'
import { ListItem } from './styled'
type Tournament = {
country?: string,
id: number,
name: string,
profileType: ProfileTypes,
sportType: SportTypes,
}
type TournamentListProps = {
onSelect: (id: number) => void,
tournaments: Array<Tournament>,
tournaments: Tournaments,
}
export const TournamentList = ({ onSelect, tournaments }: TournamentListProps) => (
<Wrapper role='listbox'>
{map(tournaments, ({
country,
id,
name,
profileType,
sportType,
}) => (
{map(tournaments, (tournament) => (
<ListItem
key={`${id}_${name}`}
onClick={() => onSelect(id)}
key={`${tournament.id}_${tournament.name_eng}`}
onClick={() => onSelect(tournament.id)}
role='option'
>
<LogoWrapper>
<Logo
id={id}
profileType={profileType}
sportType={sportType}
alt={name}
id={tournament.id}
profileType={ProfileTypes.TOURNAMENTS}
sportType={tournament.sport}
altNameObj={tournament}
/>
</LogoWrapper>
<ItemInfo>
<Name>{name}</Name>
<SportName sport={sportType} />
<TeamOrCountry>{country}</TeamOrCountry>
<Name nameObj={tournament} />
<SportName sport={tournament.sport} />
<TeamOrCountry nameObj={tournament.country} />
</ItemInfo>
</ListItem>
))}

@ -21,49 +21,55 @@ import {
GenderComponent,
} from './styled'
type Name = {
name_eng: string,
name_rus: string,
}
type SearchItemsListProps = {
close: () => void,
list: Array<{
gender?: Gender,
id: number,
name: string,
profileType: ProfileTypes,
profileUrl: string,
sportType: SportTypes,
teamOrCountry?: string,
name_eng: string,
name_rus: string,
sport: SportTypes,
teamOrCountry?: Name,
}>,
profileType: ProfileTypes,
}
export const ItemsList = ({ close, list }: SearchItemsListProps) => {
export const ItemsList = ({
close,
list,
profileType,
}: SearchItemsListProps) => {
const { ref } = useItemsList()
return (
<Wrapper ref={ref}>
{map(list, ({
gender,
id,
name,
profileType,
profileUrl,
sportType,
teamOrCountry,
}) => (
<Item key={id}>
<StyledLink to={profileUrl} onClick={close}>
{map(list, (item) => (
<Item key={item.id}>
<StyledLink
id={item.id}
sportType={item.sport}
profileType={profileType}
onClick={close}
>
<LogoWrapper>
<Logo
lazy
id={id}
id={item.id}
profileType={profileType}
sportType={sportType}
sportType={item.sport}
/>
</LogoWrapper>
<ItemInfo>
<Name>{name}</Name>
<SportName sport={sportType} />
<TeamOrCountry>{teamOrCountry}</TeamOrCountry>
<Name nameObj={item} />
<SportName sport={item.sport} />
{item.teamOrCountry && <TeamOrCountry nameObj={item.teamOrCountry} />}
</ItemInfo>
{gender && <GenderComponent type={gender} /> }
{item.gender && <GenderComponent type={item.gender} /> }
</StyledLink>
</Item>
))}

@ -1,9 +1,9 @@
import { Link } from 'react-router-dom'
import styled from 'styled-components/macro'
import { GenderComponent as GenderBase } from 'features/Gender'
import { ProfileLogo } from 'features/ProfileLogo'
import { ProfileLink } from 'features/ProfileLink'
import { Name as NameBase } from 'features/Name'
export const Wrapper = styled.ul`
margin: 0;
@ -17,7 +17,7 @@ export const Item = styled.li`
}
`
export const StyledLink = styled(Link)`
export const StyledLink = styled(ProfileLink)`
position: relative;
display: flex;
align-items: center;
@ -37,7 +37,8 @@ export const ItemInfo = styled.div`
line-height: 17px;
`
export const Name = styled.div`
export const Name = styled(NameBase)`
display: block;
font-size: 16px;
font-weight: bold;
color: #ccc;
@ -46,7 +47,7 @@ export const Name = styled.div`
overflow: hidden;
`
export const TeamOrCountry = styled.span`
export const TeamOrCountry = styled(NameBase)`
font-size: 11px;
color: #ccc;
`

@ -6,6 +6,7 @@ import { ProfileTypes } from 'config'
import type { Match } from 'features/Matches'
import { SportName } from 'features/Common'
import { useName } from 'features/Name'
import {
MatchDate,
@ -41,50 +42,53 @@ export const CardSoon = ({
team1,
team2,
time,
tournamentName,
tournament,
},
showSportName,
}: CardSoonProps) => (
<CardWrapper>
<MatchDate>
{date}
<Time>
{time}
</Time>
</MatchDate>
<PreviewWrapper>
<TeamLogos>
<TeamLogo
id={team1.id}
alt={team1.name}
title={team1.name}
sportType={sportType}
profileType={ProfileTypes.TEAMS}
/>
<TeamLogo
id={team2.id}
alt={team2.name}
title={team2.name}
sportType={sportType}
profileType={ProfileTypes.TEAMS}
/>
</TeamLogos>
</PreviewWrapper>
<Info>
{showSportName && <SportName sport={sportType} />}
{tournamentName && (
<TournamentName title={tournamentName}>
{tournamentName}
</TournamentName>
)}
<Teams>
<Team>
<TeamName title={team1.name}>{team1.name}</TeamName>
</Team>
<Team>
<TeamName title={team2.name}>{team2.name}</TeamName>
</Team>
</Teams>
</Info>
</CardWrapper>
)
}: CardSoonProps) => {
const tournamentName = useName(tournament)
return (
<CardWrapper>
<MatchDate>
{date}
<Time>
{time}
</Time>
</MatchDate>
<PreviewWrapper>
<TeamLogos>
<TeamLogo
id={team1.id}
nameAsTitle
altNameObj={team1}
sportType={sportType}
profileType={ProfileTypes.TEAMS}
/>
<TeamLogo
id={team2.id}
nameAsTitle
altNameObj={team2}
sportType={sportType}
profileType={ProfileTypes.TEAMS}
/>
</TeamLogos>
</PreviewWrapper>
<Info>
{showSportName && <SportName sport={sportType} />}
{tournamentName && (
<TournamentName title={tournamentName}>
{tournamentName}
</TournamentName>
)}
<Teams>
<Team>
<TeamName nameObj={team1} />
</Team>
<Team>
<TeamName nameObj={team2} />
</Team>
</Teams>
</Info>
</CardWrapper>
)
}

@ -6,6 +6,7 @@ import { ProfileTypes } from 'config'
import type { Match } from 'features/Matches'
import { SportName } from 'features/Common'
import { useScoreStore } from 'features/ToggleScore'
import { useName } from 'features/Name'
import {
CardWrapper,
@ -39,12 +40,13 @@ export const MatchInfoCard = ({
team1,
team2,
time,
tournamentName,
tournament,
},
onClick,
onKeyPress,
showSportName,
}: Props) => {
const tournamentName = useName(tournament)
const { isHidden } = useScoreStore()
return (
@ -72,15 +74,15 @@ export const MatchInfoCard = ({
<TeamLogos>
<TeamLogo
id={team1.id}
alt={team1.name}
title={team1.name}
nameAsTitle
altNameObj={team1}
sportType={sportType}
profileType={ProfileTypes.TEAMS}
/>
<TeamLogo
id={team2.id}
alt={team2.name}
title={team2.name}
nameAsTitle
altNameObj={team2}
sportType={sportType}
profileType={ProfileTypes.TEAMS}
/>
@ -90,18 +92,18 @@ export const MatchInfoCard = ({
</PreviewWrapper>
<Info>
{showSportName && <SportName sport={sportType} />}
{tournamentName && (
{tournament && (
<TournamentName title={tournamentName}>
{tournamentName}
</TournamentName>
)}
<Teams>
<Team>
<TeamName title={team1.name}>{team1.name}</TeamName>
<TeamName nameObj={team1} />
{!isHidden && <Score>{team1.score}</Score>}
</Team>
<Team>
<TeamName title={team2.name}>{team2.name}</TeamName>
<TeamName nameObj={team2} />
{!isHidden && <Score>{team2.score}</Score>}
</Team>
</Teams>

@ -3,6 +3,7 @@ import styled from 'styled-components/macro'
import { devices } from 'config/devices'
import { T9n } from 'features/T9n'
import { Name } from 'features/Name'
import { ProfileLogo } from 'features/ProfileLogo'
import { MATCH_CARD_WIDTH } from './config'
@ -124,7 +125,7 @@ export const Team = styled.div`
color: #fff;
`
export const TeamName = styled.span`
export const TeamName = styled(Name)`
max-width: 90%;
text-overflow: ellipsis;
white-space: nowrap;

@ -1,19 +1,17 @@
import React, { Fragment } from 'react'
import isNull from 'lodash/isNull'
import React from 'react'
import format from 'date-fns/format'
import { getProfileUrl } from 'helpers'
import type { MatchInfo } from 'requests'
import { ProfileTypes } from 'config'
import { SportName } from 'features/Common/SportName'
import { useScoreStore } from 'features/ToggleScore'
import { Name } from 'features/Name'
import { useSportNameParam } from 'hooks/useSportNameParam'
import type { MatchProfile } from '../hooks/useMatchProfile'
import {
Wrapper,
Teams,
@ -27,7 +25,7 @@ import {
const dateFormat = 'dd.MM.yyyy'
type Props = {
profile: MatchProfile,
profile: MatchInfo,
}
export const MatchProfileCard = ({ profile }: Props) => {
@ -44,52 +42,43 @@ export const MatchProfileCard = ({ profile }: Props) => {
return (
<Wrapper>
{!isNull(profile)
&& (
<Fragment>
<Teams>
<StyledLink
to={getProfileUrl({
id: team1.id,
profileType: ProfileTypes.TEAMS,
sportType,
})}
>
{team1.name}
</StyledLink>
{
!isHidden
? (
<Score>
{team1?.score} : {team2?.score}
</Score>
)
: <Dash />
}
<StyledLink to={getProfileUrl({
id: team2.id,
profileType: ProfileTypes.TEAMS,
sportType,
})}
>
{team2.name}
</StyledLink>
</Teams>
<Teams>
<StyledLink
id={team1.id}
profileType={ProfileTypes.TEAMS}
sportType={sportType}
>
<Name nameObj={team1} />
</StyledLink>
{
isHidden
? <Dash />
: (
<Score>
{team1?.score} : {team2?.score}
</Score>
)
}
<StyledLink
id={team2.id}
profileType={ProfileTypes.TEAMS}
sportType={sportType}
>
<Name nameObj={team2} />
</StyledLink>
</Teams>
<Tournament>
<SportName sport={sportType} />
<StyledLink to={getProfileUrl({
id: tournament.id,
profileType: ProfileTypes.TOURNAMENTS,
sportType,
})}
>
{tournament?.name}
</StyledLink>
</Tournament>
<DateStyled>{format(new Date(profile.date), dateFormat)}</DateStyled>
</Fragment>
)}
<Tournament>
<SportName sport={sportType} />
<StyledLink
id={tournament.id}
profileType={ProfileTypes.TOURNAMENTS}
sportType={sportType}
>
<Name nameObj={profile.tournament} />
</StyledLink>
</Tournament>
<DateStyled>{format(new Date(profile.date), dateFormat)}</DateStyled>
</Wrapper>
)
}

@ -1,8 +1,7 @@
import { Link } from 'react-router-dom'
import styled from 'styled-components/macro'
import { devices } from 'config/devices'
import { ProfileLink } from 'features/ProfileLink'
export const Wrapper = styled.div`
display: flex;
@ -25,7 +24,7 @@ export const Teams = styled.div`
display: flex;
`
export const StyledLink = styled(Link)`
export const StyledLink = styled(ProfileLink)`
font-weight: bold;
color: white;
&:hover{

@ -1,45 +1,17 @@
import {
useEffect,
useState,
useMemo,
} from 'react'
import type { MatchInfo } from 'requests'
import { getMatchInfo } from 'requests'
import { useLexicsStore } from 'features/LexicsStore'
import { useSportNameParam, usePageId } from 'hooks'
type Name = 'name_rus' | 'name_eng'
const addNames = (profile: MatchInfo, suffixArg: string) => (
profile
? ({
...profile,
team1: {
...profile.team1,
name: profile.team1[`name_${suffixArg}` as Name],
},
team2: {
...profile.team2,
name: profile.team2[`name_${suffixArg}` as Name],
},
tournament: {
...profile.tournament,
name: profile.tournament[`name_${suffixArg}` as Name],
},
})
: null
)
export type MatchProfile = ReturnType<typeof useMatchProfile>
export const useMatchProfile = () => {
const [rawMatchProfile, setMatchProfile] = useState<MatchInfo>(null)
const [matchProfile, setMatchProfile] = useState<MatchInfo>(null)
const { sportType } = useSportNameParam()
const matchId = usePageId()
const { suffix } = useLexicsStore()
useEffect(() => {
getMatchInfo(sportType, matchId).then(setMatchProfile)
@ -49,10 +21,5 @@ export const useMatchProfile = () => {
matchId,
])
const matchProfile = useMemo(
() => addNames(rawMatchProfile, suffix),
[rawMatchProfile, suffix],
)
return matchProfile
}

@ -2,16 +2,9 @@ import map from 'lodash/map'
import format from 'date-fns/format'
import type { Match, Team } from 'requests'
import type { Match } from 'requests'
import { getSportLexic } from 'helpers'
type Name = 'name_rus' | 'name_eng'
const prepareTeam = (team: Team, suffix: string) => ({
...team,
name: team[`name_${suffix}` as Name],
})
const prepareMatch = ({
date,
has_video,
@ -21,7 +14,7 @@ const prepareMatch = ({
team1,
team2,
tournament,
}: Match, suffix: string) => ({
}: Match) => ({
date: format(new Date(date), 'dd.MM.yy'),
hasVideo: has_video,
id,
@ -29,13 +22,13 @@ const prepareMatch = ({
sportName: getSportLexic(sport),
sportType: sport,
streamStatus: stream_status,
team1: prepareTeam(team1, suffix),
team2: prepareTeam(team2, suffix),
team1,
team2,
time: format(new Date(date), 'HH:mm'),
tournamentName: tournament?.[`name_${suffix}` as Name],
tournament,
})
export const prepareMatches = (matches: Array<Match>, suffix: string) => map(
export const prepareMatches = (matches: Array<Match>) => map(
matches,
(match: Match) => prepareMatch(match, suffix),
prepareMatch,
)

@ -10,8 +10,6 @@ import type { MatchesBySection } from 'requests'
import { useRequest } from 'hooks'
import { useLexicsStore } from 'features/LexicsStore'
import { prepareMatches } from './helpers/prepareMatches'
export type Match = ReturnType<typeof prepareMatches>[number]
@ -31,7 +29,6 @@ const initialState = {
}
export const useMatches = ({ fetch }: Props) => {
const { suffix } = useLexicsStore()
const {
isFetching,
request: requestMatches,
@ -71,11 +68,11 @@ export const useMatches = ({ fetch }: Props) => {
}, [fetchMatches])
const preparedMatches = useMemo(() => ({
broadcast: prepareMatches(matches.broadcast, suffix),
features: prepareMatches(matches.features, suffix),
highlights: prepareMatches(matches.highlights, suffix),
broadcast: prepareMatches(matches.broadcast),
features: prepareMatches(matches.features),
highlights: prepareMatches(matches.highlights),
isVideoSections: matches.isVideoSections,
}), [suffix, matches])
}), [matches])
return {
fetchMoreMatches,

@ -0,0 +1,36 @@
import React from 'react'
import styled from 'styled-components/macro'
import { useLexicsStore } from 'features/LexicsStore'
export type ObjectWithName = {
[key: string]: any,
name_eng?: string,
name_rus?: string,
}
type Props = {
className?: string,
nameObj: ObjectWithName,
prefix?: string,
}
const NameStyled = styled.span``
export const useName = (
nameObj: ObjectWithName,
prefix: string = 'name_',
): string => {
const { suffix } = useLexicsStore()
return nameObj?.[`${prefix}${suffix}`]
}
export const Name = ({
className,
nameObj,
prefix,
}: Props) => {
const name = useName(nameObj, prefix)
return <NameStyled className={className}>{name}</NameStyled>
}

@ -9,29 +9,27 @@ import { useSportNameParam, usePageId } from 'hooks'
import type { PlayerProfile } from 'requests/getPlayerInfo'
import { getPlayerInfo, getPlayerMatches } from 'requests'
import { useName } from 'features/Name'
import { useLexicsStore } from 'features/LexicsStore'
import { addSportType } from 'features/Matches/helpers/addSportType'
type Firstname = 'firstname_eng' | 'firstname_rus'
type Lastname = 'lastname_eng' | 'lastname_rus'
type Name = 'name_eng' | 'name_rus'
export const usePlayerPage = () => {
const [playerProfile, setPlayerProfile] = useState<PlayerProfile>(null)
const { sportType } = useSportNameParam()
const playerId = usePageId()
const { suffix, translate } = useLexicsStore()
const { translate } = useLexicsStore()
const {
club_team,
height,
weight,
[`firstname_${suffix}` as Firstname]: firstName = '',
[`lastname_${suffix}` as Lastname]: lastName = '',
} = playerProfile || {}
const fullName = `${firstName} ${lastName}`
const teamName = club_team?.[`name_${suffix}` as Name] || ''
const fullName = {
name_eng: `${playerProfile?.firstname_eng} ${playerProfile?.lastname_eng}`,
name_rus: `${playerProfile?.firstname_rus} ${playerProfile?.lastname_rus}`,
}
const teamName = useName(club_team || {})
const infoItems = [
`${height ? `${height} ${translate('cm')}` : ''}${
@ -56,6 +54,6 @@ export const usePlayerPage = () => {
return {
fetchMatches,
infoItems,
name: fullName,
titleObj: fullName,
}
}

@ -11,14 +11,14 @@ export const PlayerPage = () => {
const {
fetchMatches,
infoItems,
name,
titleObj,
} = usePlayerPage()
return (
<Content>
<ProfileCard
profileType={ProfileTypes.PLAYERS}
name={name}
titleObj={titleObj}
infoItems={infoItems}
/>
<Matches fetch={fetchMatches} />

@ -4,6 +4,7 @@ import map from 'lodash/map'
import { T9n } from 'features/T9n'
import { StarIcon } from 'features/Common'
import { useName } from 'features/Name'
import type { ProfileCardProps } from './types'
import {
@ -22,10 +23,12 @@ import { useProfileCard } from './hooks'
export const ProfileCard = (props: ProfileCardProps) => {
const {
infoItems,
name,
profileType,
titleObj,
} = props
const name = useName(titleObj || {})
const {
isFavorite,
profileId,

@ -1,7 +1,9 @@
import { ProfileTypes } from 'config'
import type { ObjectWithName } from 'features/Name'
export type ProfileCardProps = {
infoItems: Array<string>,
name: string,
profileType: ProfileTypes,
titleObj: ObjectWithName | null,
}

@ -0,0 +1,22 @@
import { ProfileTypes, SportTypes } from 'config'
import { getProfileUrl } from '..'
it('returns correct profile urls', () => {
expect(getProfileUrl({
id: 1,
profileType: ProfileTypes.PLAYERS,
sportType: SportTypes.FOOTBALL,
})).toBe('/football/players/1')
expect(getProfileUrl({
id: 2,
profileType: ProfileTypes.TEAMS,
sportType: SportTypes.BASKETBALL,
})).toBe('/basketball/teams/2')
expect(getProfileUrl({
id: 3,
profileType: ProfileTypes.TOURNAMENTS,
sportType: SportTypes.HOCKEY,
})).toBe('/hockey/tournaments/3')
})

@ -0,0 +1,43 @@
import type { ReactNode, MouseEvent } from 'react'
import React from 'react'
import { Link } from 'react-router-dom'
import { ProfileTypes, SportTypes } from 'config'
import { getProfileUrl } from './helpers'
type Props = {
children: ReactNode,
className?: string,
id: number,
onClick?: (e: MouseEvent<HTMLAnchorElement>) => void,
profileType: ProfileTypes,
sportType: SportTypes,
target?: string,
}
export const ProfileLink = ({
children,
className,
id,
onClick,
profileType,
sportType,
target,
}: Props) => {
const url = getProfileUrl({
id,
profileType,
sportType,
})
return (
<Link
to={url}
className={className}
target={target}
onClick={onClick}
>
{children}
</Link>
)
}

@ -4,12 +4,17 @@ import { ProfileTypes, SportTypes } from 'config'
import { getProfileFallbackLogo, getProfileLogo } from 'helpers'
import { Image } from 'features/Common'
import type { ObjectWithName } from 'features/Name'
import { useName } from 'features/Name'
type ProfileImageProps = {
alt?: string,
altNameObj?: ObjectWithName,
className?: string,
id: number,
lazy?: boolean,
nameAsTitle?: boolean,
prefix?: string,
profileType: ProfileTypes,
size?: number,
sportType: SportTypes,
@ -18,14 +23,19 @@ type ProfileImageProps = {
export const ProfileLogo = ({
alt,
altNameObj,
className,
id,
lazy = false,
nameAsTitle,
prefix,
profileType,
size,
sportType,
title,
}: ProfileImageProps) => {
const altName = useName(altNameObj || {}, prefix)
const titleText = nameAsTitle ? altName : title
const src = getProfileLogo({
id,
profileType,
@ -39,12 +49,12 @@ export const ProfileLogo = ({
return (
<Image
alt={alt}
alt={alt || altName}
src={lazy ? '' : src}
data-src={lazy ? src : ''}
fallbackSrc={fallbackSrc}
className={className}
title={title}
title={titleText}
/>
)
}

@ -19,7 +19,7 @@ import {
} from 'hooks'
import { SEARCH_DELAY, MIN_CHARACTERS_LENGTH } from '../config'
import { useNormalizedItems } from './useNormalizedItems'
import { normalizeItems } from './useNormalizedItems'
export const useSearch = () => {
const [searchItems, setSearchItems] = useState<SearchItems>({})
@ -85,7 +85,7 @@ export const useSearch = () => {
return {
close,
isFetching,
normalizedItems: useNormalizedItems(searchItems),
normalizedItems: normalizeItems(searchItems),
onChange,
onFocus,
onSubmit,

@ -1,85 +1,24 @@
import map from 'lodash/map'
import { SearchItems } from 'requests'
import { ProfileTypes } from 'config'
import { getProfileUrl } from 'helpers'
import { useLexicsStore } from 'features/LexicsStore'
type Firstname = 'firstname_eng' | 'firstname_rus'
type Lastname = 'lastname_eng' | 'lastname_rus'
type Name = 'name_eng' | 'name_rus'
export const useNormalizedItems = (searchItems: SearchItems) => {
const {
suffix,
} = useLexicsStore()
const players = map(searchItems.players, (player) => {
const { id, sport: sportType } = player
const profileType = ProfileTypes.PLAYERS
const firstName = player[`firstname_${suffix}` as Firstname]
const lastName = player[`lastname_${suffix}` as Lastname]
const teamName = player.team?.[`name_${suffix}` as Name]
return {
gender: player.gender,
id,
name: `${firstName} ${lastName}`,
profileType,
profileUrl: getProfileUrl({
id,
profileType,
sportType,
}),
sportType,
teamOrCountry: teamName,
}
})
const teams = map(searchItems.teams, (team) => {
const { id, sport: sportType } = team
const profileType = ProfileTypes.TEAMS
const name = team[`name_${suffix}` as Name]
const country = team.country?.[`name_${suffix}` as Name]
return {
gender: team.gender,
id,
name,
profileType,
profileUrl: getProfileUrl({
id,
profileType,
sportType,
}),
sportType,
teamOrCountry: country,
}
})
const tournaments = map(searchItems.tournaments, (tournament) => {
const profileType = ProfileTypes.TOURNAMENTS
const { id, sport: sportType } = tournament
const name = tournament[`name_${suffix}` as Name]
const country = tournament.country?.[`name_${suffix}` as Name]
return {
gender: tournament.gender,
id,
name,
profileType,
profileUrl: getProfileUrl({
id,
profileType,
sportType,
}),
sportType,
teamOrCountry: country,
}
})
export const normalizeItems = (searchItems: SearchItems) => {
const players = map(searchItems.players, (player) => ({
...player,
name_eng: `${player.firstname_eng} ${player.lastname_eng}`,
name_rus: `${player.firstname_rus} ${player.lastname_rus}`,
teamOrCountry: player.team,
}))
const teams = map(searchItems.teams, (team) => ({
...team,
teamOrCountry: team.country,
}))
const tournaments = map(searchItems.tournaments, (tournament) => ({
...tournament,
teamOrCountry: tournament.country,
}))
return {
players,

@ -2,7 +2,8 @@ import React, { Fragment } from 'react'
import { useRouteMatch } from 'react-router-dom'
import isEmpty from 'lodash/isEmpty'
import { PAGES } from 'config'
import { PAGES, ProfileTypes } from 'config'
import { Input } from 'features/Common'
import { ItemsList } from 'features/ItemsList'
import { OutsideClick } from 'features/OutsideClick'
@ -54,21 +55,33 @@ export const Search = () => {
{!isEmpty(tournaments) && (
<Fragment>
<Header title='tournament' image='tournament' />
<ItemsList list={tournaments} close={close} />
<ItemsList
list={tournaments}
close={close}
profileType={ProfileTypes.TOURNAMENTS}
/>
</Fragment>
)}
{!isEmpty(teams) && (
<Fragment>
<Header title='team' image='team' />
<ItemsList list={teams} close={close} />
<ItemsList
list={teams}
close={close}
profileType={ProfileTypes.TEAMS}
/>
</Fragment>
)}
{!isEmpty(players) && (
<Fragment>
<Header title='player' image='player' />
<ItemsList list={players} close={close} />
<ItemsList
list={players}
close={close}
profileType={ProfileTypes.PLAYERS}
/>
</Fragment>
)}
</Results>

@ -7,26 +7,16 @@ import {
import type { TeamInfo } from 'requests'
import { getTeamInfo, getTeamMatches } from 'requests'
import { useLexicsStore } from 'features/LexicsStore'
import { useSportNameParam, usePageId } from 'hooks'
import { addSportType } from 'features/Matches/helpers/addSportType'
type Name = 'name_rus' | 'name_eng'
import { useName } from 'features/Name'
import { addSportType } from 'features/Matches/helpers/addSportType'
export const useTeamPage = () => {
const [teamProfile, setTeamProfile] = useState<TeamInfo>(null)
const { sportType } = useSportNameParam()
const teamId = usePageId()
const { suffix } = useLexicsStore()
const {
[`name_${suffix}` as Name]: name = '',
} = teamProfile || {}
const {
[`name_${suffix}` as Name]: country = '',
} = teamProfile?.country || {}
const country = useName(teamProfile?.country || {})
useEffect(() => {
getTeamInfo(sportType, teamId)
@ -50,7 +40,7 @@ export const useTeamPage = () => {
return {
fetchMatches,
infoItems: [country],
name,
sportType,
titleObj: teamProfile,
}
}

@ -12,7 +12,7 @@ export const TeamPage = () => {
const {
fetchMatches,
infoItems,
name,
titleObj,
} = useTeamPage()
return (
@ -20,7 +20,7 @@ export const TeamPage = () => {
<Content>
<ProfileCard
profileType={ProfileTypes.TEAMS}
name={name}
titleObj={titleObj}
infoItems={infoItems}
/>
<Matches fetch={fetchMatches} />

@ -9,24 +9,14 @@ import { getTournamentInfo, getTournamentMatches } from 'requests'
import { useSportNameParam, usePageId } from 'hooks'
import { useLexicsStore } from 'features/LexicsStore'
import { useName } from 'features/Name'
import { addSportType } from 'features/Matches/helpers/addSportType'
type Name = 'name_rus' | 'name_eng'
export const useTournamentPage = () => {
const [tournamentProfile, setTournamentProfile] = useState<TournamentInfo>(null)
const { sportType } = useSportNameParam()
const tournamentId = usePageId()
const { suffix } = useLexicsStore()
const {
[`name_${suffix}` as Name]: name = '',
} = tournamentProfile || {}
const {
[`name_${suffix}` as Name]: country = '',
} = tournamentProfile?.country || {}
const country = useName(tournamentProfile?.country || {})
useEffect(() => {
getTournamentInfo(sportType, tournamentId)
@ -50,6 +40,6 @@ export const useTournamentPage = () => {
return {
fetchMatches,
infoItems: [country],
name,
titleObj: tournamentProfile,
}
}

@ -12,7 +12,7 @@ export const TournamentPage = () => {
const {
fetchMatches,
infoItems,
name,
titleObj,
} = useTournamentPage()
return (
@ -20,7 +20,7 @@ export const TournamentPage = () => {
<Content>
<ProfileCard
profileType={ProfileTypes.TOURNAMENTS}
name={name}
titleObj={titleObj}
infoItems={infoItems}
/>
<Matches fetch={fetchMatches} />

@ -1,8 +1,8 @@
import React from 'react'
import { SportTypes } from 'config'
import { getSportColor, getSportLexic } from 'helpers'
import { T9n } from 'features/T9n'
import { UserFavorite } from 'requests'
import { Name, useName } from 'features/Name'
import {
TooltipBlockWrapper,
@ -12,37 +12,32 @@ import {
} from './styled'
type TooltipBlockProps = {
countryName?: string,
date?: string,
playerFirstName?: string,
playerLastName?: string,
playerTeamName?: string,
sport: SportTypes,
teamName?: string,
favorite: UserFavorite,
topPosition: number | null,
}
export const TooltipBlock = ({
countryName,
playerFirstName,
playerLastName,
playerTeamName,
sport,
teamName,
favorite: {
info,
sport,
},
topPosition,
}: TooltipBlockProps) => (
<TooltipBlockWrapper top={topPosition}>
<TooltipBlockItem>
{playerFirstName && playerLastName && `${playerFirstName} ${playerLastName}`}
</TooltipBlockItem>
<TooltipBlockItem>
{teamName}
</TooltipBlockItem>
<TooltipBlockItemThin>
<TooltipBlockItemThinUpperCase color={getSportColor(sport)}>
<T9n t={getSportLexic(sport)} />
</TooltipBlockItemThinUpperCase>{' '}
{playerTeamName || countryName}
</TooltipBlockItemThin>
</TooltipBlockWrapper>
)
}: TooltipBlockProps) => {
const playerFirstName = useName(info, 'firstname_')
const playerLastName = useName(info, 'lastname_')
return (
<TooltipBlockWrapper top={topPosition}>
<TooltipBlockItem>
{playerFirstName && playerLastName && `${playerFirstName} ${playerLastName}`}
</TooltipBlockItem>
<TooltipBlockItem>
<Name nameObj={info} />
</TooltipBlockItem>
<TooltipBlockItemThin>
<TooltipBlockItemThinUpperCase sport={sport} />{' '}
{info.team && <Name nameObj={info.team} />}
{info.country && <Name nameObj={info.country} />}
</TooltipBlockItemThin>
</TooltipBlockWrapper>
)
}

@ -1,5 +1,7 @@
import styled, { css } from 'styled-components/macro'
import { SportName } from 'features/Common'
export const TooltipBlockWrapper = styled.div<{top: number | null}>`
background-color: #fff;
border-radius: 10px;
@ -45,7 +47,8 @@ export const TooltipBlockItemThin = styled(TooltipBlockItem)`
font-weight: 400;
`
export const TooltipBlockItemThinUpperCase = styled(TooltipBlockItem)`
export const TooltipBlockItemThinUpperCase = styled(SportName)`
${TooltipStyles}
display: inline;
text-transform: uppercase;
font-weight: 400;

@ -1,36 +0,0 @@
import map from 'lodash/map'
import { getProfileUrl } from 'helpers'
import type { UserFavorites } from 'requests'
type Names = 'name_eng' | 'name_rus'
type ShortNames = 'short_name_eng' | 'short_name_rus'
type FirstNames = 'firstname_eng' | 'firstname_rus'
type LastNames = 'lastname_eng' | 'firstname_rus'
type NickNames = 'nickname_eng' | 'nickname_rus'
export const normalizeUserFavorites = (favorites: UserFavorites, suffix: string) => {
const nameField = `name_${suffix}` as Names
const shortNameField = `short_name_${suffix}` as ShortNames
const firtsNameField = `firstname_${suffix}` as FirstNames
const lastNameField = `lastname_${suffix}` as LastNames
const nickNameField = `nickname_${suffix}` as NickNames
return map(favorites, (item) => ({
countryName: item.info.country?.[nameField],
firstname: item.info[firtsNameField],
id: item.id,
lastname: item.info[lastNameField],
name: item.info[nameField],
nickname: item.info[nickNameField],
profileUrl: getProfileUrl({
id: item.id,
profileType: item.type,
sportType: item.sport,
}),
shortName: item.info[shortNameField],
sport: item.sport,
teamName: item.info.team?.[nameField],
type: item.type,
}))
}

@ -1,22 +1,13 @@
import {
useEffect,
useState,
useMemo,
} from 'react'
import { useEffect, useState } from 'react'
import type { UserFavorites } from 'requests'
import { modifyUserFavorites, getUserFavorites } from 'requests'
import { useLexicsStore } from 'features/LexicsStore'
import { useToggle } from 'hooks/useToggle'
import { normalizeUserFavorites } from '../helpers'
type Args = Parameters<typeof modifyUserFavorites>[0]
export const useUserFavorites = () => {
const { suffix } = useLexicsStore()
const [userFavorites, setUserFavorites] = useState<UserFavorites>([])
const {
@ -33,16 +24,11 @@ export const useUserFavorites = () => {
modifyUserFavorites(args).then(setUserFavorites, open)
}
const memoizedUserFavorites = useMemo(
() => normalizeUserFavorites(userFavorites, suffix),
[userFavorites, suffix],
)
return {
addRemoveFavorite,
close,
isOpen,
open,
userFavorites: memoizedUserFavorites,
userFavorites,
}
}

@ -9,11 +9,11 @@ import { FavoritesActions } from 'requests'
import { PAGES } from 'config'
import { Modal } from 'features/Modal'
import { ProfileLink } from 'features/ProfileLink'
import { TooltipBlock } from './TooltipBlock'
import { useUserFavoritesStore } from './store'
import {
StyledLink,
UserSportFavItemLogoWrapper,
UserSportFavXWrapper,
UserSportFavImgWrapper,
@ -67,21 +67,21 @@ export const UserFavorites = () => {
/>
<TooltipBlock
topPosition={position}
countryName={item.countryName}
teamName={item.name}
playerTeamName={item.teamName}
playerFirstName={item.firstname}
playerLastName={item.lastname}
sport={item.sport}
favorite={item}
/>
<StyledLink to={item.profileUrl} target='_blank'>
<ProfileLink
id={item.id}
sportType={item.sport}
profileType={item.type}
target='_blank'
>
<UserSportFavImgWrapper
id={item.id}
alt={item.name}
altNameObj={item}
sportType={item.sport}
profileType={item.type}
/>
</StyledLink>
</ProfileLink>
</UserSportFavItemLogoWrapper>
))
}

@ -1,4 +1,3 @@
import { Link } from 'react-router-dom'
import { devices } from 'config/devices'
@ -11,8 +10,6 @@ import { ProfileLogo } from 'features/ProfileLogo'
import { TooltipBlockWrapper } from './TooltipBlock/styled'
export const StyledLink = styled(Link)``
export const UserSportFavWrapper = styled.aside`
display: flex;
flex-direction: column;

@ -3,7 +3,6 @@ export * from './callApi/getResponseData'
export * from './token'
export * from './getProfileLogo'
export * from './getProfileFallbackLogo'
export * from './getProfileUrl'
export * from './getSportColor'
export * from './getSportLexic'
export * from './msToMinutesAndSeconds'

@ -31,7 +31,7 @@ type Info = {
team2?: ObjectWithName,
}
type UserFavorite = {
export type UserFavorite = {
id: number,
info: Info,
sport: SportTypes,

Loading…
Cancel
Save