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 fixkeep-around/af30b88d367751c9e05a735e4a0467a96238ef47
parent
9fcff60af8
commit
75f6911da1
@ -0,0 +1,4 @@ |
||||
export const currencySymbols = { |
||||
dollar: '$', |
||||
ruble: '₽', |
||||
} |
||||
@ -0,0 +1 @@ |
||||
export const MDASH = '\u2014' |
||||
@ -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', |
||||
} |
||||
@ -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> |
||||
) |
||||
} |
||||
@ -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,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> |
||||
) |
||||
} |
||||
@ -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`, |
||||
}) |
||||
} |
||||
Loading…
Reference in new issue