Ott 799 buy match popup (#295)

* Ott 799 part 1 (#289)

* refactor(799): moved reusable popup components into PopupComponents

* feat(799): added subscriptions request

* fix(799): fixed subscription types

* Ott 799 part 2 (#293)

* refactor(799): moved Price into features

* refactor(799): moved popupScrollbarStyles into PopupComponents feature

* refactor(799): created config of currency symbols

* feat(799): added buy popup and its subscriptions selection step (#294)

* feat(799): added buy popup and its subscriptions selection step

* refactor(799): review comments fix
keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
Mirlan 5 years ago committed by GitHub
parent 9fcff60af8
commit 75f6911da1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/config/currencies.tsx
  2. 1
      src/config/dashes.tsx
  3. 2
      src/config/index.tsx
  4. 11
      src/config/lexics/indexLexics.tsx
  5. 54
      src/features/App/AuthenticatedApp.tsx
  6. 67
      src/features/BuyMatchPopup/components/MatchSubscriptions/index.tsx
  7. 59
      src/features/BuyMatchPopup/components/PaymentPeriods/index.tsx
  8. 45
      src/features/BuyMatchPopup/components/SelectedCard/index.tsx
  9. 31
      src/features/BuyMatchPopup/components/Subscriptions/index.tsx
  10. 52
      src/features/BuyMatchPopup/components/SubscriptionsList/index.tsx
  11. 80
      src/features/BuyMatchPopup/components/SubscriptionsList/styled.tsx
  12. 39
      src/features/BuyMatchPopup/index.tsx
  13. 71
      src/features/BuyMatchPopup/store/hooks/index.tsx
  14. 53
      src/features/BuyMatchPopup/store/hooks/useSubscriptions.tsx
  15. 20
      src/features/BuyMatchPopup/store/index.tsx
  16. 39
      src/features/BuyMatchPopup/styled.tsx
  17. 7
      src/features/BuyMatchPopup/types.tsx
  18. 21
      src/features/MatchCard/CardFrontside/index.tsx
  19. 5
      src/features/MatchPopup/components/BackButton/index.tsx
  20. 13
      src/features/MatchPopup/components/CloseButton/index.tsx
  21. 2
      src/features/MatchPopup/components/FinishedMatchPopup/index.tsx
  22. 22
      src/features/MatchPopup/components/FinishedPlaylistPage/index.tsx
  23. 14
      src/features/MatchPopup/components/LivePlaylistPage/index.tsx
  24. 15
      src/features/MatchPopup/components/PlayersListDesktop/index.tsx
  25. 5
      src/features/MatchPopup/components/SettingsButton/index.tsx
  26. 77
      src/features/MatchPopup/components/SettingsPage/index.tsx
  27. 89
      src/features/MatchPopup/styled.tsx
  28. 29
      src/features/PopupComponents/BaseButton/index.tsx
  29. 15
      src/features/PopupComponents/CloseButton/index.tsx
  30. 69
      src/features/PopupComponents/Header/index.tsx
  31. 4
      src/features/PopupComponents/index.tsx
  32. 18
      src/features/PopupComponents/popupScrollbarStyles/index.tsx
  33. 30
      src/features/Price/index.tsx
  34. 0
      src/features/Price/styled.tsx
  35. 2
      src/features/Register/components/AdditionalSubscription/index.tsx
  36. 2
      src/features/Register/components/MainSubscription/index.tsx
  37. 31
      src/features/Register/components/Price/index.tsx
  38. 17
      src/features/UserAccount/components/CardNumber/styled.tsx
  39. 2
      src/features/UserAccount/components/Subscription/index.tsx
  40. 2
      src/features/UserAccount/components/TextNoBorder/index.tsx
  41. 2
      src/features/UserAccount/components/UserAccountSubscription/index.tsx
  42. 2
      src/features/UserAccount/components/UserAccountSubscriptionMatch/index.tsx
  43. 28
      src/requests/getMatchSubscriptions.tsx
  44. 1
      src/requests/index.tsx

@ -0,0 +1,4 @@
export const currencySymbols = {
dollar: '$',
ruble: '₽',
}

@ -0,0 +1 @@
export const MDASH = '\u2014'

@ -6,3 +6,5 @@ export * from './sportTypes'
export * from './profileTypes'
export * from './history'
export * from './devices'
export * from './currencies'
export * from './dashes'

@ -19,6 +19,16 @@ const matchPopupLexics = {
watch_live_stream: 13020,
}
const buyMatchPopupLexics = {
buy_subscription: 13565,
change_card: 13564,
choose_subscription: 13563,
for_month: 13561,
for_year: 13562,
per_month: 13573,
per_year: 13574,
}
export const indexLexics = {
add_to_favorites: 1701,
add_to_favorites_error: 12943,
@ -69,4 +79,5 @@ export const indexLexics = {
...proceduresLexics,
...matchPopupLexics,
...buyMatchPopupLexics,
}

@ -20,6 +20,7 @@ import { UserAccountForm } from 'features/UserAccount'
import { MatchSwitchesStore } from 'features/MatchSwitches'
import { UserFavoritesStore } from 'features/UserFavorites/store'
import { MatchPopupStore } from 'features/MatchPopup'
import { BuyMatchPopup, BuyMatchPopupStore } from 'features/BuyMatchPopup'
export const AuthenticatedApp = () => {
useLexicsConfig(indexLexics)
@ -29,32 +30,35 @@ export const AuthenticatedApp = () => {
<UserFavoritesStore>
<ExtendedSearchStore>
<MatchPopupStore>
<BuyMatchPopupStore>
<BuyMatchPopup />
{/* в Switch как прямой children можно рендерить только Route или Redirect */}
<Switch>
<Route path={PAGES.useraccount}>
<UserAccountForm />
</Route>
<Route exact path={PAGES.home}>
<HomePage />
</Route>
<Route path={`/:sportName${PAGES.tournament}/:pageId`}>
<TournamentPage />
</Route>
<Route path={`/:sportName${PAGES.team}/:pageId`}>
<TeamPage />
</Route>
<Route path={`/:sportName${PAGES.player}/:pageId`}>
<PlayerPage />
</Route>
<Route path={`/:sportName${PAGES.match}/:pageId`}>
<MatchPage />
</Route>
<Route path={PAGES.extendedSearch}>
<ExtendedSearchPage />
</Route>
<Redirect to={PAGES.home} />
</Switch>
{/* в Switch как прямой children можно рендерить только Route или Redirect */}
<Switch>
<Route path={PAGES.useraccount}>
<UserAccountForm />
</Route>
<Route exact path={PAGES.home}>
<HomePage />
</Route>
<Route path={`/:sportName${PAGES.tournament}/:pageId`}>
<TournamentPage />
</Route>
<Route path={`/:sportName${PAGES.team}/:pageId`}>
<TeamPage />
</Route>
<Route path={`/:sportName${PAGES.player}/:pageId`}>
<PlayerPage />
</Route>
<Route path={`/:sportName${PAGES.match}/:pageId`}>
<MatchPage />
</Route>
<Route path={PAGES.extendedSearch}>
<ExtendedSearchPage />
</Route>
<Redirect to={PAGES.home} />
</Switch>
</BuyMatchPopupStore>
</MatchPopupStore>
</ExtendedSearchStore>
</UserFavoritesStore>

@ -0,0 +1,67 @@
import styled from 'styled-components/macro'
import isEmpty from 'lodash/isEmpty'
import { MDASH } from 'config'
import { T9n } from 'features/T9n'
import { useBuyMatchPopupStore } from 'features/BuyMatchPopup'
import {
CloseButton,
Header,
HeaderActions,
HeaderTitle,
} from 'features/PopupComponents'
import { Name } from 'features/Name'
import { Steps } from 'features/BuyMatchPopup/types'
import { SelectedCard } from '../SelectedCard'
import { Subscriptions } from '../Subscriptions'
import { Button } from '../../styled'
const Wrapper = styled.div`
width: 870px;
height: 695px;
`
const Center = styled.div`
width: 100%;
display: flex;
justify-content: center;
`
export const MatchSubscriptionsStep = () => {
const {
close,
goTo,
match,
selectedSubscriptions,
} = useBuyMatchPopupStore()
if (!match) return null
return (
<Wrapper>
<Header height={50}>
<HeaderTitle>
<Name nameObj={match.team1} />
{' '} {MDASH} {' '}
<Name nameObj={match.team2} />
</HeaderTitle>
<HeaderActions position='right'>
<CloseButton onClick={close} />
</HeaderActions>
</Header>
<Subscriptions />
<SelectedCard />
<Center>
<Button
disabled={isEmpty(selectedSubscriptions)}
onClick={(e) => goTo(e, Steps.Confirmation)}
>
<T9n t='buy_subscription' />
</Button>
</Center>
</Wrapper>
)
}

@ -0,0 +1,59 @@
import styled, { css } from 'styled-components/macro'
import { SubscriptionType } from 'requests'
import { T9n } from 'features/T9n'
import { useBuyMatchPopupStore } from 'features/BuyMatchPopup/store'
const List = styled.ul`
display: flex;
padding: 0 35px;
margin-top: 9px;
`
type ItemProps = {
active?: boolean,
}
const Item = styled.li.attrs(() => ({
tabIndex: 0,
}))<ItemProps>`
width: 50%;
font-size: 20px;
line-height: 42px;
display: flex;
align-items: center;
justify-content: center;
color: rgba(255, 255, 255, 0.5);
cursor: pointer;
${({ active }) => (
active
? css`
border-bottom: 3px solid #fff;
color: #fff;
`
: ''
)}
`
export const PaymentPeriods = () => {
const { onPeriodSelect, selectedPeriod } = useBuyMatchPopupStore()
return (
<List>
<Item
active={selectedPeriod === SubscriptionType.Month}
onClick={() => onPeriodSelect(SubscriptionType.Month)}
>
<T9n t='for_month' />
</Item>
<Item
active={selectedPeriod === SubscriptionType.Year}
onClick={() => onPeriodSelect(SubscriptionType.Year)}
>
<T9n t='for_year' />
</Item>
</List>
)
}

@ -0,0 +1,45 @@
import styled from 'styled-components/macro'
import { T9n } from 'features/T9n'
import { ButtonOutline } from 'features/Common'
const Wrapper = styled.div`
display: flex;
margin-top: 40px;
margin-bottom: 30px;
padding: 0 35px;
`
const CardInfo = styled.span`
font-weight: 500;
font-size: 18px;
line-height: 20px;
color: rgba(255, 255, 255, 0.7);
`
const ChangeCardButton = styled(ButtonOutline)`
border: none;
padding: 0;
width: auto;
height: auto;
padding: 0 10px;
margin-left: 10px;
line-height: 20px;
font-size: 14px;
color: rgba(255, 255, 255, 0.5);
cursor: pointer;
:hover {
color: rgba(255, 255, 255);
}
`
export const SelectedCard = () => (
<Wrapper>
<CardInfo>Mastercard 4432</CardInfo>
<ChangeCardButton>
<T9n t='change_card' />
</ChangeCardButton>
</Wrapper>
)

@ -0,0 +1,31 @@
import styled from 'styled-components/macro'
import { T9n } from 'features/T9n'
import { PaymentPeriods } from '../PaymentPeriods'
import { SubscriptionsList } from '../SubscriptionsList'
const Wrapper = styled.div`
width: 100%;
display: flex;
flex-direction: column;
`
const Title = styled.span`
font-weight: normal;
font-size: 20px;
line-height: 21px;
text-transform: uppercase;
margin-top: 30px;
padding: 0 35px;
`
export const Subscriptions = () => (
<Wrapper>
<PaymentPeriods />
<Title>
<T9n t='choose_subscription' />
</Title>
<SubscriptionsList />
</Wrapper>
)

@ -0,0 +1,52 @@
import map from 'lodash/map'
import includes from 'lodash/includes'
import { useBuyMatchPopupStore } from 'features/BuyMatchPopup/store'
import {
List,
Item,
InfoWrapper,
Header,
Description,
Price,
} from './styled'
export const SubscriptionsList = () => {
const {
onSubscriptionSelect,
selectedSubscriptions,
subscriptions,
} = useBuyMatchPopupStore()
return (
<List>
{
map(subscriptions, ({
description,
header,
price,
subscription_id,
type,
}) => (
<Item
key={subscription_id}
onClick={() => onSubscriptionSelect(subscription_id)}
active={includes(selectedSubscriptions, subscription_id)}
>
<InfoWrapper>
<Header>
{header}
</Header>
<Description>
{description}
</Description>
</InfoWrapper>
<Price amount={price} perPeriod={`per_${type}`} />
</Item>
))
}
</List>
)
}

@ -0,0 +1,80 @@
import styled from 'styled-components/macro'
import { popupScrollbarStyles } from 'features/PopupComponents'
import { Price as BasePrice } from 'features/Price'
import { PriceAmount, PriceDetails } from 'features/Price/styled'
export const List = styled.ul`
height: 364px;
display: flex;
flex-direction: column;
overflow-y: auto;
margin-top: 20px;
padding: 0 35px;
${popupScrollbarStyles}
`
type ItemProps = {
active?: boolean,
}
export const Item = styled.li.attrs(() => ({
tabIndex: 0,
}))<ItemProps>`
width: 100%;
min-height: 108px;
padding: 20px;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%), #5C5C5C;
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
border-radius: 2px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
:first-child {
margin-top: 2px;
}
:not(:last-child) {
margin-bottom: 20px;
}
${({ active }) => (
active ? 'background-color: #294FC3' : ''
)};
`
export const InfoWrapper = styled.div`
width: 80%;
`
export const Header = styled.span`
font-weight: 600;
font-size: 20px;
line-height: 23px;
letter-spacing: 0.03em;
`
export const Description = styled.p`
margin-top: 10px;
font-weight: 500;
font-size: 17px;
letter-spacing: 0.03em;
`
export const Price = styled(BasePrice)`
${PriceAmount} {
font-size: 24px;
line-height: 24px;
font-weight: normal;
}
${PriceDetails} {
font-weight: 500;
font-size: 12px;
line-height: 18px;
}
`

@ -0,0 +1,39 @@
import { useBuyMatchPopupStore } from 'features/BuyMatchPopup'
import { MatchSubscriptionsStep } from './components/MatchSubscriptions'
import { Modal } from './styled'
import { Steps } from './types'
export * from './store'
const Empty = () => null
const components = {
[Steps.Subscriptions]: MatchSubscriptionsStep,
[Steps.CardSelection]: Empty,
[Steps.Confirmation]: Empty,
[Steps.Success]: Empty,
[Steps.Error]: Empty,
}
export const BuyMatchPopup = () => {
const {
close,
currentStep,
match,
} = useBuyMatchPopupStore()
if (!match || !currentStep) return null
const Step = components[currentStep]
return (
<Modal
isOpen
close={close}
withCloseButton={false}
>
<Step />
</Modal>
)
}

@ -0,0 +1,71 @@
import type { MouseEvent } from 'react'
import { useCallback, useState } from 'react'
import last from 'lodash/last'
import type { Match } from 'features/Matches/hooks'
import { useMatchPopupStore } from 'features/MatchPopup'
import { Steps } from 'features/BuyMatchPopup/types'
import { useSubscriptions } from './useSubscriptions'
type MatchData = Pick<Match, (
'id'
| 'team1'
| 'team2'
)> | null
export const useBuyMatchPopup = () => {
const { closePopup: closeMatchPopup } = useMatchPopupStore()
const [steps, setSteps] = useState<Array<Steps>>([])
const [match, setMatch] = useState<MatchData>(null)
const {
onPeriodSelect,
onSubscriptionSelect,
resetSubscriptions,
selectedPeriod,
selectedSubscriptions,
subscriptions,
} = useSubscriptions()
const goTo = useCallback(
(e: MouseEvent<HTMLButtonElement>, step: Steps) => setSteps((state) => {
e.stopPropagation()
return [...state, step]
}),
[],
)
const goBack = useCallback(() => setSteps((state) => {
const newState = [...state]
newState.pop()
return newState
}), [])
const openPopup = (e: MouseEvent<HTMLButtonElement>, matchData: MatchData) => {
closeMatchPopup()
e.stopPropagation()
setMatch(matchData)
setSteps([Steps.Subscriptions])
}
const closePopup = () => {
setMatch(null)
setSteps([])
resetSubscriptions()
}
return {
close: closePopup,
currentStep: last(steps),
goBack,
goTo,
match,
onPeriodSelect,
onSubscriptionSelect,
open: openPopup,
resetSubscriptions,
selectedPeriod,
selectedSubscriptions,
subscriptions,
}
}

@ -0,0 +1,53 @@
import {
useMemo,
useState,
useEffect,
useCallback,
} from 'react'
import filter from 'lodash/filter'
import includes from 'lodash/includes'
import type { MatchSubscriptions } from 'requests'
import { SubscriptionType, getMatchSubscriptions } from 'requests'
export const useSubscriptions = () => {
const [selectedPeriod, setSelectedPeriod] = useState(SubscriptionType.Month)
const [subscriptionsList, setSubscriptionsList] = useState<MatchSubscriptions>([])
const [selectedSubscriptions, setSelectedSubscriptions] = useState<Array<number>>([])
useEffect(() => {
getMatchSubscriptions().then(setSubscriptionsList)
}, [])
const subscriptions = useMemo(
() => filter(subscriptionsList, { type: selectedPeriod }),
[selectedPeriod, subscriptionsList],
)
const onSubscriptionSelect = (id: number) => {
if (includes(selectedSubscriptions, id)) {
const newSubscriptions = filter(
selectedSubscriptions,
(subscriptionId) => subscriptionId !== id,
)
setSelectedSubscriptions(newSubscriptions)
} else {
setSelectedSubscriptions([...selectedSubscriptions, id])
}
}
const resetSubscriptions = useCallback(() => {
setSelectedPeriod(SubscriptionType.Month)
setSelectedSubscriptions([])
}, [])
return {
onPeriodSelect: setSelectedPeriod,
onSubscriptionSelect,
resetSubscriptions,
selectedPeriod,
selectedSubscriptions,
subscriptions,
}
}

@ -0,0 +1,20 @@
import type { ReactNode } from 'react'
import { createContext, useContext } from 'react'
import { useBuyMatchPopup } from './hooks'
type Context = ReturnType<typeof useBuyMatchPopup>
type Props = { children: ReactNode }
const BuyMatchPopupContext = createContext({} as Context)
export const BuyMatchPopupStore = ({ children }: Props) => {
const value = useBuyMatchPopup()
return (
<BuyMatchPopupContext.Provider value={value}>
{children}
</BuyMatchPopupContext.Provider>
)
}
export const useBuyMatchPopupStore = () => useContext(BuyMatchPopupContext)

@ -0,0 +1,39 @@
import styled from 'styled-components/macro'
import { devices } from 'config'
import { Modal as BaseModal } from 'features/Modal'
import { ModalWindow } from 'features/Modal/styled'
import { ButtonSolid } from 'features/Common'
export const Modal = styled(BaseModal)`
background-color: rgba(0, 0, 0, 0.7);
${ModalWindow} {
min-width: 517px;
min-height: 310px;
padding: 20px 0;
background-color: #3F3F3F;
border-radius: 5px;
@media ${devices.mobile} {
width: 100vw;
height: 100vh;
padding: 0;
}
}
`
export const Button = styled(ButtonSolid)`
min-width: 142px;
width: auto;
height: 50px;
padding: 0 20px;
background-color: #294FC4;
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
border-radius: 5px;
:disabled {
opacity: 0.5;
}
`

@ -0,0 +1,7 @@
export enum Steps {
CardSelection = 'CardSelection',
Confirmation = 'Confirmation',
Error = 'Error',
Subscriptions = 'Subscriptions',
Success = 'Success',
}

@ -7,6 +7,7 @@ import { ProfileTypes } from 'config'
import type { Match } from 'features/Matches'
import { SportName } from 'features/Common'
import { useMatchSwitchesStore } from 'features/MatchSwitches'
import { useBuyMatchPopupStore } from 'features/BuyMatchPopup'
import { useName } from 'features/Name'
import { NoAccessMessage } from '../NoAccessMessage'
@ -36,7 +37,12 @@ type Props = {
}
export const CardFrontside = ({
match: {
match,
onClick,
onKeyPress,
showSportName,
}: Props) => {
const {
accessibleBySubscription,
accessibleInUsersCountry,
date,
@ -49,12 +55,9 @@ export const CardFrontside = ({
team2,
time,
tournament,
},
onClick,
onKeyPress,
showSportName,
}: Props) => {
} = match
const tournamentName = useName(tournament)
const { open } = useBuyMatchPopupStore()
const { isScoreHidden } = useMatchSwitchesStore()
const { selectedMatchStatus } = useHeaderFiltersStore()
const unixTimeOfMatch = getUnixTime(date)
@ -95,7 +98,11 @@ export const CardFrontside = ({
</TeamLogos>
)
}
{!accessibleBySubscription && <BuyMatchButton />}
{!accessibleBySubscription && (
<BuyMatchButton
onClick={(e) => open(e, match)}
/>
)}
{(accessibleBySubscription && !accessibleInUsersCountry) && <NoAccessMessage />}
<MatchDate>
{formattedDate}

@ -1,8 +1,7 @@
import styled from 'styled-components/macro'
import { useMatchPopupStore } from 'features/MatchPopup/store'
import { BaseButton } from '../../styled'
import { useMatchPopupStore } from 'features/MatchPopup'
import { BaseButton } from 'features/PopupComponents'
const Button = styled(BaseButton)`
background-image: url(/images/back-icon.svg);

@ -1,13 +0,0 @@
import { Close } from 'features/Icons/Close'
import { useMatchPopupStore } from 'features/MatchPopup/store'
import { BaseButton } from '../../styled'
export const CloseButton = () => {
const { closePopup } = useMatchPopupStore()
return (
<BaseButton onClick={closePopup}>
<Close />
</BaseButton>
)
}

@ -9,8 +9,6 @@ import { FinishedPlaylistPage } from '../../components/FinishedPlaylistPage'
import { PopupPages } from '../../types'
import { Modal } from './styled'
export * from '../../store'
export const FinishedMatchPopup = () => {
const {
closePopup,

@ -6,22 +6,26 @@ import { useMatchSwitchesStore } from 'features/MatchSwitches'
import { Name } from 'features/Name'
import { MediaQuery } from 'features/MediaQuery'
import { useMatchPopupStore } from 'features/MatchPopup'
import {
CloseButton,
Header,
HeaderActions,
HeaderTitle,
} from 'features/PopupComponents'
import { SettingsButton } from '../SettingsButton'
import { CloseButton } from '../CloseButton'
import { BackButton } from '../BackButton'
import { FinishedMatchPlaylist } from '../FinishedMatchPlaylist'
import { PlayersListDesktop } from '../PlayersListDesktop'
import { PlayersListMobile } from '../PlayersListMobile'
import {
Content,
Header,
HeaderActions,
HeaderTitle,
} from '../../styled'
import { Content } from '../../styled'
export const FinishedPlaylistPage = () => {
const { match, matchPlaylists } = useMatchPopupStore()
const {
closePopup,
match,
matchPlaylists,
} = useMatchPopupStore()
const { isScoreHidden } = useMatchSwitchesStore()
if (!match) return null
@ -50,7 +54,7 @@ export const FinishedPlaylistPage = () => {
<HeaderActions position='right'>
<SettingsButton />
<MediaQuery minDevice='tablet'>
<CloseButton />
<CloseButton onClick={closePopup} />
</MediaQuery>
</HeaderActions>
</Header>

@ -1,7 +1,9 @@
import { MDASH } from 'config'
import { Name } from 'features/Name'
import { useMatchPopupStore } from 'features/MatchPopup'
import { CloseButton } from 'features/PopupComponents'
import { CloseButton } from '../CloseButton'
import { LiveMatchPlaylist } from '../LiveMatchPlaylist'
import {
@ -12,7 +14,11 @@ import {
} from './styled'
export const LivePlaylistPage = () => {
const { match, matchPlaylists } = useMatchPopupStore()
const {
closePopup,
match,
matchPlaylists,
} = useMatchPopupStore()
if (!match) return null
const { team1, team2 } = match
@ -22,12 +28,12 @@ export const LivePlaylistPage = () => {
<Header>
<HeaderTitle>
<Name nameObj={team1} />
{' '} &mdash; {' '}
{' '} {MDASH} {' '}
<Name nameObj={team2} />
</HeaderTitle>
<HeaderActions>
<CloseButton />
<CloseButton onClick={closePopup} />
</HeaderActions>
</Header>

@ -1,7 +1,7 @@
import styled from 'styled-components/macro'
import { T9n } from 'features/T9n'
import { customScrollbar } from 'features/Common'
import { popupScrollbarStyles } from 'features/PopupComponents'
import { useMatchPopupStore } from 'features/MatchPopup'
import { Teams } from '../../types'
@ -24,18 +24,7 @@ const ListsWrapper = styled.div`
flex-direction: row;
justify-content: space-around;
${customScrollbar};
::-webkit-scrollbar-thumb {
border-radius: 3px;
background: rgba(196, 196, 196, 0.3);
}
::-webkit-scrollbar-track,
::-webkit-scrollbar-corner {
border-radius: 3px;
background: rgba(103, 103, 103, 0.3);
}
${popupScrollbarStyles};
`
export const PlayersListDesktop = () => {

@ -1,8 +1,7 @@
import styled from 'styled-components/macro'
import { useMatchPopupStore } from 'features/MatchPopup/store'
import { BaseButton } from '../../styled'
import { useMatchPopupStore } from 'features/MatchPopup'
import { BaseButton } from 'features/PopupComponents'
const Button = styled(BaseButton)`
background-image: url(/images/settings.svg);

@ -2,17 +2,18 @@ import styled from 'styled-components/macro'
import { MediaQuery } from 'features/MediaQuery'
import { T9n } from 'features/T9n'
import { CloseButton } from '../CloseButton'
import { BackButton } from '../BackButton'
import { SettingsDesktop } from '../SettingsDesktop'
import { SettingsMobile } from '../SettingsMobile'
import {
Content,
CloseButton,
Header,
HeaderActions,
HeaderTitle,
} from '../../styled'
} from 'features/PopupComponents'
import { useMatchPopupStore } from '../../store'
import { BackButton } from '../BackButton'
import { SettingsDesktop } from '../SettingsDesktop'
import { SettingsMobile } from '../SettingsMobile'
import { Content } from '../../styled'
const ButtonLabel = styled(T9n)`
display: flex;
@ -23,38 +24,42 @@ const ButtonLabel = styled(T9n)`
color: rgba(255, 255, 255, 0.5);
`
export const SettingsPage = () => (
<Content height={818}>
<Header>
<HeaderActions
position='left'
marginLeft={15}
>
<BackButton />
<MediaQuery minDevice='tablet'>
<ButtonLabel t='go_back_to_match' />
export const SettingsPage = () => {
const { closePopup } = useMatchPopupStore()
return (
<Content height={818}>
<Header>
<HeaderActions
position='left'
marginLeft={15}
>
<BackButton />
<MediaQuery minDevice='tablet'>
<ButtonLabel t='go_back_to_match' />
</MediaQuery>
</HeaderActions>
<MediaQuery maxDevice='mobile'>
<HeaderTitle>
<T9n t='match_settings' />
</HeaderTitle>
</MediaQuery>
</HeaderActions>
<MediaQuery maxDevice='mobile'>
<HeaderTitle>
<T9n t='match_settings' />
</HeaderTitle>
</MediaQuery>
<MediaQuery minDevice='tablet'>
<HeaderActions position='right'>
<CloseButton onClick={closePopup} />
</HeaderActions>
</MediaQuery>
</Header>
<MediaQuery minDevice='tablet'>
<HeaderActions position='right'>
<CloseButton />
</HeaderActions>
<SettingsDesktop />
</MediaQuery>
</Header>
<MediaQuery minDevice='tablet'>
<SettingsDesktop />
</MediaQuery>
<MediaQuery maxDevice='mobile'>
<SettingsMobile />
</MediaQuery>
</Content>
)
<MediaQuery maxDevice='mobile'>
<SettingsMobile />
</MediaQuery>
</Content>
)
}

@ -1,35 +1,9 @@
import styled, { css } from 'styled-components/macro'
import styled from 'styled-components/macro'
import { devices } from 'config'
import { customScrollbar } from 'features/Common'
export const BaseButton = styled.button`
padding: 0;
border: none;
background: none;
cursor: pointer;
width: 34px;
height: 34px;
color: white;
background-color: rgba(255, 255, 255, 0.12);
background-position: center;
background-repeat: no-repeat;
border-radius: 50%;
:hover {
background-color: rgba(255, 255, 255, 0.22);
}
@media ${devices.mobile} {
width: 24px;
height: 24px;
background-color: transparent;
border-radius: 0;
}
`
type ContentProps = {
height?: number,
}
@ -51,67 +25,6 @@ export const Content = styled.div<ContentProps>`
}
`
export const Header = styled.div`
position: relative;
height: 35px;
display: flex;
align-items: center;
@media ${devices.mobile} {
height: 52px;
background-color: rgba(255, 255, 255, 0.1);
padding: 0 12px;
}
`
type HeaderActionsProps = {
marginLeft?: number,
position: 'left' | 'right',
}
export const HeaderActions = styled.div<HeaderActionsProps>`
position: absolute;
display: flex;
${({ marginLeft = 0, position }) => css`
${position}: 20px;
margin-left: ${marginLeft}px;
`}
@media ${devices.mobile} {
${({ position }) => css`
${position}: 12px;
margin-left: 0;
`}
}
${BaseButton}:not(:last-child) {
margin-right: 20px;
}
`
export const HeaderTitle = styled.h2`
position: absolute;
width: 70%;
left: 50%;
transform: translateX(-50%);
font-weight: 600;
font-size: 24px;
line-height: 42px;
color: #FFFFFF;
text-align: center;
@media ${devices.mobile} {
font-size: 19px;
line-height: 28px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
`
export const BlockTitle = styled.h3`
font-weight: normal;
font-size: 20px;

@ -0,0 +1,29 @@
import styled from 'styled-components/macro'
import { devices } from 'config'
export const BaseButton = styled.button`
padding: 0;
border: none;
background: none;
cursor: pointer;
width: 34px;
height: 34px;
color: white;
background-color: rgba(255, 255, 255, 0.12);
background-position: center;
background-repeat: no-repeat;
border-radius: 50%;
:hover {
background-color: rgba(255, 255, 255, 0.22);
}
@media ${devices.mobile} {
width: 24px;
height: 24px;
background-color: transparent;
border-radius: 0;
}
`

@ -0,0 +1,15 @@
import type { MouseEvent } from 'react'
import { Close } from 'features/Icons/Close'
import { BaseButton } from '../BaseButton'
type Props = {
onClick: (e: MouseEvent<HTMLButtonElement>) => void,
}
export const CloseButton = ({ onClick }: Props) => (
<BaseButton onClick={onClick}>
<Close />
</BaseButton>
)

@ -0,0 +1,69 @@
import styled, { css } from 'styled-components/macro'
import { devices } from 'config'
import { BaseButton } from '../BaseButton'
type HeaderProps = {
height?: number,
}
export const Header = styled.div<HeaderProps>`
position: relative;
height: ${({ height = 35 }) => height}px;
display: flex;
@media ${devices.mobile} {
height: 52px;
background-color: rgba(255, 255, 255, 0.1);
padding: 0 12px;
}
`
type HeaderActionsProps = {
marginLeft?: number,
position: 'left' | 'right',
}
export const HeaderActions = styled.div<HeaderActionsProps>`
position: absolute;
display: flex;
${({ marginLeft = 0, position }) => css`
${position}: 20px;
margin-left: ${marginLeft}px;
`}
@media ${devices.mobile} {
${({ position }) => css`
${position}: 12px;
margin-left: 0;
`}
}
${BaseButton}:not(:last-child) {
margin-right: 20px;
}
`
export const HeaderTitle = styled.h2`
position: absolute;
width: 70%;
left: 50%;
transform: translateX(-50%);
font-weight: 600;
font-size: 24px;
line-height: 42px;
color: #FFFFFF;
text-align: center;
@media ${devices.mobile} {
font-size: 19px;
line-height: 28px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
`

@ -0,0 +1,4 @@
export * from './BaseButton'
export * from './CloseButton'
export * from './Header'
export * from './popupScrollbarStyles'

@ -0,0 +1,18 @@
import { css } from 'styled-components/macro'
import { customScrollbar } from 'features/Common'
export const popupScrollbarStyles = css`
${customScrollbar}
::-webkit-scrollbar-thumb {
border-radius: 3px;
background: rgba(196, 196, 196, 0.3);
}
::-webkit-scrollbar-track,
::-webkit-scrollbar-corner {
border-radius: 3px;
background: rgba(103, 103, 103, 0.3);
}
`

@ -0,0 +1,30 @@
import { currencySymbols } from 'config'
import { T9n } from 'features/T9n'
import {
PriceWrapper,
PriceAmount,
PriceDetails,
} from './styled'
type Props = {
amount: number,
className?: string,
currency?: string,
perPeriod?: string,
}
export const Price = ({
amount,
className,
currency = currencySymbols.ruble,
perPeriod = 'month',
}: Props) => (
<PriceWrapper className={className}>
<PriceAmount>{amount}</PriceAmount>
<PriceDetails>
{currency} / <T9n t={perPeriod} />
</PriceDetails>
</PriceWrapper>
)

@ -1,7 +1,7 @@
import { Checkbox } from 'features/Common'
import { MediaQuery } from 'features/MediaQuery'
import { Price } from 'features//Price'
import { Price } from '../Price'
import {
PriceItemTitle,
PriceItem,

@ -1,7 +1,7 @@
import { Radio } from 'features/Common'
import { MediaQuery } from 'features/MediaQuery'
import { Price } from 'features/Price'
import { Price } from '../Price'
import {
SubscriptionWrapper,
SubscriptionTitle,

@ -1,31 +0,0 @@
import { useLexicsStore } from 'features/LexicsStore'
import {
PriceWrapper,
PriceAmount,
PriceDetails,
} from './styled'
type Props = {
amount: number,
currency?: string,
perPeriod?: string,
}
export const Price = ({
amount,
currency = '₽',
perPeriod = 'month',
}: Props) => {
const { translate } = useLexicsStore()
const perPeriodTranslated = translate(perPeriod)
return (
<PriceWrapper>
<PriceAmount>{amount}</PriceAmount>
<PriceDetails>
{currency} / {perPeriodTranslated}
</PriceDetails>
</PriceWrapper>
)
}

@ -1,9 +1,9 @@
import styled, { css } from 'styled-components/macro'
import styled from 'styled-components/macro'
import { devices } from 'config/devices'
import { Label } from 'features/Common/Radio/styled'
import { PriceAmount, PriceDetails } from 'features/Register/components/Price/styled'
import { PriceAmount, PriceDetails } from 'features/Price/styled'
export const CardNumberWrapper = styled.div`
display: flex;
@ -28,8 +28,8 @@ export const CardNumberWrapper = styled.div`
max-width: 415px;
${Label} {
font-size: 16px;
font-size: 16px;
&::before {
margin-left: 12px;
margin-right: 12px;
@ -76,11 +76,11 @@ export const CardNumberTextWrapper = styled(TextWrapper)`
}
`
export type Props = {
type Props = {
noMarginRight?: boolean,
}
export const priceWrapperStyles = css<Props>`
export const PriceWrapper = styled.div<Props>`
margin-left: auto;
margin-right: 24px;
@ -103,8 +103,3 @@ export const priceWrapperStyles = css<Props>`
}
}
`
export const PriceWrapper = styled.div`
${priceWrapperStyles}
`

@ -1,4 +1,4 @@
import { Price } from 'features/Register/components/Price'
import { Price } from 'features/Price'
import { Radio } from 'features/Common/Radio'
import { Checkbox } from 'features/Common/Checkbox'

@ -1,4 +1,4 @@
import { Price } from 'features/Register/components/Price'
import { Price } from 'features/Price'
import { TextNoBorderWrapper, TextNoBorderTextWrapper } from './styled'
import { PriceWrapper } from '../CardNumber/styled'

@ -1,7 +1,7 @@
import { T9n } from 'features/T9n'
import type { ObjectWithName } from 'features/Name'
import { Name } from 'features/Name'
import { Price } from 'features/Register/components/Price'
import { Price } from 'features/Price'
import {
UserAccountSubscriptionWrapper,

@ -4,7 +4,7 @@ import format from 'date-fns/format'
import type { Match } from 'features/UserAccount/hooks/useUserSubscriptions'
import { Name } from 'features/Name'
import { Price } from 'features/Register/components/Price'
import { Price } from 'features/Price'
import { T9n } from 'features/T9n'
import {

@ -0,0 +1,28 @@
import { API_ROOT } from 'config'
import { callApi } from 'helpers'
export enum SubscriptionType {
Month = 'month',
Year = 'year',
}
type MatchSubscription = {
description: string,
header: string,
price: number,
subscription_id: number,
type: SubscriptionType,
}
export type MatchSubscriptions = Array<MatchSubscription>
export const getMatchSubscriptions = (): Promise<MatchSubscriptions> => {
const config = {
method: 'GET',
}
return callApi({
config,
url: `${API_ROOT}/account/get-subscriptions`,
})
}

@ -24,3 +24,4 @@ export * from './getMatchesPreviewImages'
export * from './getSportActions'
export * from './getMatchPlaylists'
export * from './getPlayerPlaylists'
export * from './getMatchSubscriptions'

Loading…
Cancel
Save