Ott 817 user account redesign (#303)
* Ott 817 part 1 (#297) * refactor(817): BankCard component * refactor(817): split sections into Page components * Ott 817 part 2 (#298) * feat(817): page navigation * fix(817): fixed icon in input * fix(817): bank card page redisign (#299) * Ott 817 part 4 (#300) * fix(817): form width fix * fix(817): removed not needed components * fix(817): pr comments * Ott 817 part 5 (#301) * refactor(817): component SportName * refactor(817): component PaymentPeriods -> PaymentPeriodTabs * fix(817): added display error props to Combobox * Ott 817 part 6 (#302) * fix(817): redesign of user subscriptions * fix(817): ui micro fixeskeep-around/af30b88d367751c9e05a735e4a0467a96238ef47
parent
082fa10967
commit
b33773cd94
|
After Width: | Height: | Size: 446 B |
@ -0,0 +1,44 @@ |
|||||||
|
import { SolidButton } from 'features/UserAccount/styled' |
||||||
|
|
||||||
|
import { |
||||||
|
Form, |
||||||
|
Column, |
||||||
|
ButtonsBlock, |
||||||
|
Input, |
||||||
|
} from './styled' |
||||||
|
|
||||||
|
export const AddCardForm = () => ( |
||||||
|
<Form> |
||||||
|
<Column> |
||||||
|
<Input |
||||||
|
labelWidth={70} |
||||||
|
wrapperWidth={560} |
||||||
|
label='Номер' |
||||||
|
labelLexic='form_card_number' |
||||||
|
/> |
||||||
|
<Input |
||||||
|
labelWidth={70} |
||||||
|
wrapperWidth={560} |
||||||
|
label='Имя' |
||||||
|
/> |
||||||
|
<Input |
||||||
|
maxLength={5} |
||||||
|
labelWidth={120} |
||||||
|
wrapperWidth={275} |
||||||
|
labelLexic='form_card_expiration' |
||||||
|
/> |
||||||
|
<Input |
||||||
|
maxLength={3} |
||||||
|
labelWidth={140} |
||||||
|
wrapperWidth={275} |
||||||
|
label='CVC / CVV' |
||||||
|
labelLexic='form_card_code' |
||||||
|
/> |
||||||
|
</Column> |
||||||
|
<ButtonsBlock> |
||||||
|
<SolidButton type='submit'> |
||||||
|
Сохранить |
||||||
|
</SolidButton> |
||||||
|
</ButtonsBlock> |
||||||
|
</Form> |
||||||
|
) |
||||||
@ -0,0 +1,34 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import { Input as InputBase } from 'features/Common' |
||||||
|
import { InputWrapper } from 'features/Common/Input/styled' |
||||||
|
|
||||||
|
export const Form = styled.form`` |
||||||
|
|
||||||
|
export const Column = styled.div` |
||||||
|
display: flex; |
||||||
|
flex-direction: row; |
||||||
|
justify-content: space-between; |
||||||
|
flex-wrap: wrap; |
||||||
|
` |
||||||
|
|
||||||
|
export const ButtonsBlock = styled.div` |
||||||
|
display: flex; |
||||||
|
margin-top: 40px; |
||||||
|
` |
||||||
|
|
||||||
|
export const Input = styled(InputBase).attrs(() => ({ |
||||||
|
withError: false, |
||||||
|
}))` |
||||||
|
width: auto; |
||||||
|
|
||||||
|
${InputWrapper} { |
||||||
|
height: 50px; |
||||||
|
padding: 0 24px; |
||||||
|
margin-top: 10px; |
||||||
|
} |
||||||
|
|
||||||
|
:first-child ${InputWrapper} { |
||||||
|
margin-top: 0; |
||||||
|
} |
||||||
|
` |
||||||
@ -1,59 +0,0 @@ |
|||||||
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> |
|
||||||
) |
|
||||||
} |
|
||||||
@ -1,19 +1,18 @@ |
|||||||
import { SportTypes } from 'config' |
import { SportTypes } from 'config' |
||||||
|
|
||||||
import { getSportColor, getSportLexic } from 'helpers' |
import { getSportLexic } from 'helpers' |
||||||
|
|
||||||
import { useLexicsStore } from 'features/LexicsStore' |
|
||||||
|
|
||||||
import { Text } from './styled' |
import { Text } from './styled' |
||||||
|
|
||||||
type SportNameProps = { sport: SportTypes } |
type SportNameProps = { |
||||||
|
className?: string, |
||||||
export const SportName = ({ sport }: SportNameProps) => { |
sport: SportTypes, |
||||||
const { translate } = useLexicsStore() |
|
||||||
|
|
||||||
return ( |
|
||||||
<Text color={getSportColor(sport)}> |
|
||||||
{translate(getSportLexic(sport))} |
|
||||||
</Text> |
|
||||||
) |
|
||||||
} |
} |
||||||
|
|
||||||
|
export const SportName = ({ className, sport }: SportNameProps) => ( |
||||||
|
<Text |
||||||
|
className={className} |
||||||
|
sport={sport} |
||||||
|
t={getSportLexic(sport)} |
||||||
|
/> |
||||||
|
) |
||||||
|
|||||||
@ -0,0 +1,65 @@ |
|||||||
|
import styled, { css } from 'styled-components/macro' |
||||||
|
|
||||||
|
import { SubscriptionType } from 'requests' |
||||||
|
|
||||||
|
import { T9n } from 'features/T9n' |
||||||
|
|
||||||
|
const List = styled.ul` |
||||||
|
display: flex; |
||||||
|
padding: 0 35px; |
||||||
|
margin-top: 9px; |
||||||
|
` |
||||||
|
|
||||||
|
type ItemProps = { |
||||||
|
active?: boolean, |
||||||
|
} |
||||||
|
|
||||||
|
export 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; |
||||||
|
` |
||||||
|
: '' |
||||||
|
)} |
||||||
|
` |
||||||
|
|
||||||
|
type Props = { |
||||||
|
className?: string, |
||||||
|
onPeriodSelect: (period: SubscriptionType) => void, |
||||||
|
selectedPeriod: SubscriptionType, |
||||||
|
} |
||||||
|
|
||||||
|
export const PaymentPeriodTabs = ({ |
||||||
|
className, |
||||||
|
onPeriodSelect, |
||||||
|
selectedPeriod, |
||||||
|
}: Props) => ( |
||||||
|
<List className={className}> |
||||||
|
<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,27 @@ |
|||||||
|
import { Radio } from 'features/Common/Radio' |
||||||
|
|
||||||
|
import { InlineButton } from '../../styled' |
||||||
|
import { CardNumberWrapper } from './styled' |
||||||
|
|
||||||
|
type Props = { |
||||||
|
checked?: boolean, |
||||||
|
number: string, |
||||||
|
type: 'visa' | 'mastercard', |
||||||
|
} |
||||||
|
|
||||||
|
export const BankCard = ({ |
||||||
|
checked, |
||||||
|
number, |
||||||
|
type, |
||||||
|
}: Props) => ( |
||||||
|
<CardNumberWrapper> |
||||||
|
<Radio |
||||||
|
label={`${type} ${number}`} |
||||||
|
checked={checked} |
||||||
|
onClick={() => {}} |
||||||
|
/> |
||||||
|
<InlineButton> |
||||||
|
Удалить |
||||||
|
</InlineButton> |
||||||
|
</CardNumberWrapper> |
||||||
|
) |
||||||
@ -0,0 +1,52 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import { devices } from 'config/devices' |
||||||
|
|
||||||
|
import { Label } from 'features/Common/Radio/styled' |
||||||
|
import { RadioSvg } from 'features/Common/Radio/Icon' |
||||||
|
|
||||||
|
import { InlineButton } from '../../styled' |
||||||
|
|
||||||
|
export const CardNumberWrapper = styled.div` |
||||||
|
width: 100%; |
||||||
|
height: 50px; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
background-color: #3F3F3F; |
||||||
|
border-radius: 2px; |
||||||
|
margin-bottom: 10px; |
||||||
|
overflow: hidden; |
||||||
|
|
||||||
|
${Label} { |
||||||
|
font-size: 20px; |
||||||
|
line-height: 24px; |
||||||
|
margin-left: 25px; |
||||||
|
text-transform: capitalize; |
||||||
|
} |
||||||
|
|
||||||
|
${RadioSvg} { |
||||||
|
margin-right: 24px; |
||||||
|
} |
||||||
|
|
||||||
|
@media ${devices.tablet} { |
||||||
|
max-width: 415px; |
||||||
|
|
||||||
|
${Label} { |
||||||
|
font-size: 16px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@media ${devices.mobile} { |
||||||
|
max-width: 335px; |
||||||
|
|
||||||
|
${Label} { |
||||||
|
font-size: 14px; |
||||||
|
line-height: 24px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
:hover ${InlineButton} { |
||||||
|
transform: translateX(0); |
||||||
|
} |
||||||
|
` |
||||||
@ -1,29 +0,0 @@ |
|||||||
import { Radio } from 'features/Common/Radio' |
|
||||||
import { T9n } from 'features/T9n' |
|
||||||
|
|
||||||
import { VisaLogoWrapper } from '../VisaLogo' |
|
||||||
import { CardNumberWrapper, CardNumberTextWrapper } from './styled' |
|
||||||
|
|
||||||
type Props = { |
|
||||||
checked?: boolean, |
|
||||||
label: string, |
|
||||||
visa?: boolean, |
|
||||||
} |
|
||||||
|
|
||||||
export const CardNumber = ({ |
|
||||||
checked, |
|
||||||
label, |
|
||||||
visa, |
|
||||||
}: Props) => ( |
|
||||||
<CardNumberWrapper> |
|
||||||
<Radio |
|
||||||
label={label} |
|
||||||
checked={checked} |
|
||||||
onClick={() => {}} |
|
||||||
/> |
|
||||||
<VisaLogoWrapper visa={visa} /> |
|
||||||
<CardNumberTextWrapper> |
|
||||||
<T9n t='delete_card' /> |
|
||||||
</CardNumberTextWrapper> |
|
||||||
</CardNumberWrapper> |
|
||||||
) |
|
||||||
@ -1,105 +0,0 @@ |
|||||||
import styled from 'styled-components/macro' |
|
||||||
|
|
||||||
import { devices } from 'config/devices' |
|
||||||
|
|
||||||
import { Label } from 'features/Common/Radio/styled' |
|
||||||
import { PriceAmount, PriceDetails } from 'features/Price/styled' |
|
||||||
|
|
||||||
export const CardNumberWrapper = styled.div` |
|
||||||
display: flex; |
|
||||||
align-items: center; |
|
||||||
justify-content: space-between; |
|
||||||
height: 48px; |
|
||||||
background-color: #3F3F3F; |
|
||||||
border-radius: 2px; |
|
||||||
margin: 20px 0; |
|
||||||
width: 100%; |
|
||||||
|
|
||||||
${Label} { |
|
||||||
font-size: 20px; |
|
||||||
line-height: 24px; |
|
||||||
|
|
||||||
&::before { |
|
||||||
margin-left: 22px; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@media ${devices.tablet} { |
|
||||||
max-width: 415px; |
|
||||||
|
|
||||||
${Label} { |
|
||||||
font-size: 16px; |
|
||||||
|
|
||||||
&::before { |
|
||||||
margin-left: 12px; |
|
||||||
margin-right: 12px; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@media ${devices.mobile} { |
|
||||||
max-width: 335px; |
|
||||||
margin: 10px 0; |
|
||||||
|
|
||||||
${Label} { |
|
||||||
font-size: 14px; |
|
||||||
line-height: 24px; |
|
||||||
|
|
||||||
&::before { |
|
||||||
margin-left: 6px; |
|
||||||
margin-right: 6px; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const TextWrapper = styled.p` |
|
||||||
font-family: Montserrat, sans-serif; |
|
||||||
font-style: normal; |
|
||||||
font-weight: normal; |
|
||||||
font-size: 14px; |
|
||||||
line-height: 24px; |
|
||||||
color: #666666; |
|
||||||
white-space: nowrap; |
|
||||||
margin-right: 0; |
|
||||||
|
|
||||||
&:hover { |
|
||||||
cursor: pointer; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const CardNumberTextWrapper = styled(TextWrapper)` |
|
||||||
margin-right: 24px; |
|
||||||
|
|
||||||
@media ${devices.mobile} { |
|
||||||
margin-right: 5px; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
type Props = { |
|
||||||
noMarginRight?: boolean, |
|
||||||
} |
|
||||||
|
|
||||||
export const PriceWrapper = styled.div<Props>` |
|
||||||
margin-left: auto; |
|
||||||
margin-right: 24px; |
|
||||||
|
|
||||||
${PriceAmount} { |
|
||||||
font-size: 24px; |
|
||||||
line-height: 21px; |
|
||||||
} |
|
||||||
|
|
||||||
${PriceDetails} { |
|
||||||
font-size: 12px; |
|
||||||
line-height: 12px; |
|
||||||
} |
|
||||||
|
|
||||||
@media ${devices.mobile} { |
|
||||||
${PriceAmount} { |
|
||||||
font-size: 17px; |
|
||||||
} |
|
||||||
${PriceDetails} { |
|
||||||
font-size: 10px; |
|
||||||
} |
|
||||||
} |
|
||||||
` |
|
||||||
@ -0,0 +1,33 @@ |
|||||||
|
import { useToggle } from 'hooks' |
||||||
|
|
||||||
|
import { T9n } from 'features/T9n' |
||||||
|
import { AddCardForm } from 'features/AddCardForm' |
||||||
|
|
||||||
|
import { BankCard } from '../BankCard' |
||||||
|
import { OutlineButton, Icon } from '../../styled' |
||||||
|
import { FormWrapper, Wrapper } from './styled' |
||||||
|
|
||||||
|
export const PageBankCards = () => { |
||||||
|
const { isOpen, toggle } = useToggle() |
||||||
|
|
||||||
|
return ( |
||||||
|
<Wrapper> |
||||||
|
<BankCard type='mastercard' number='•••• 4432' checked /> |
||||||
|
<BankCard type='mastercard' number='•••• 4432' /> |
||||||
|
<BankCard type='mastercard' number='•••• 4432' /> |
||||||
|
<FormWrapper> |
||||||
|
{isOpen |
||||||
|
? <AddCardForm /> |
||||||
|
: ( |
||||||
|
<OutlineButton |
||||||
|
type='button' |
||||||
|
onClick={toggle} |
||||||
|
> |
||||||
|
<Icon src='plusIcon' /> |
||||||
|
<T9n t='add_card' /> |
||||||
|
</OutlineButton> |
||||||
|
)} |
||||||
|
</FormWrapper> |
||||||
|
</Wrapper> |
||||||
|
) |
||||||
|
} |
||||||
@ -0,0 +1,14 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import { devices } from 'config' |
||||||
|
|
||||||
|
export const Wrapper = styled.div`` |
||||||
|
|
||||||
|
export const FormWrapper = styled.div` |
||||||
|
width: 560px; |
||||||
|
margin-top: 40px; |
||||||
|
|
||||||
|
@media ${devices.tablet} { |
||||||
|
max-width: auto; |
||||||
|
} |
||||||
|
` |
||||||
@ -0,0 +1,57 @@ |
|||||||
|
import { |
||||||
|
Table, |
||||||
|
THead, |
||||||
|
Th, |
||||||
|
TBody, |
||||||
|
TRow, |
||||||
|
Td, |
||||||
|
} from './styled' |
||||||
|
|
||||||
|
export const PagePaymentsHistory = () => ( |
||||||
|
<Table> |
||||||
|
<THead> |
||||||
|
<Th> |
||||||
|
Дата платежа |
||||||
|
</Th> |
||||||
|
<Th> |
||||||
|
Подписка |
||||||
|
</Th> |
||||||
|
<Th> |
||||||
|
Тип |
||||||
|
</Th> |
||||||
|
<Th> |
||||||
|
Сумма |
||||||
|
</Th> |
||||||
|
</THead> |
||||||
|
<TBody> |
||||||
|
<TRow> |
||||||
|
<Td> |
||||||
|
12.01.21 |
||||||
|
</Td> |
||||||
|
<Td> |
||||||
|
Матч Спартак-Динамо |
||||||
|
</Td> |
||||||
|
<Td> |
||||||
|
На год |
||||||
|
</Td> |
||||||
|
<Td> |
||||||
|
1999 руб. |
||||||
|
</Td> |
||||||
|
</TRow> |
||||||
|
<TRow> |
||||||
|
<Td> |
||||||
|
22.12.20 |
||||||
|
</Td> |
||||||
|
<Td> |
||||||
|
Все матчи Спартака |
||||||
|
</Td> |
||||||
|
<Td> |
||||||
|
На месяц |
||||||
|
</Td> |
||||||
|
<Td> |
||||||
|
999 руб. |
||||||
|
</Td> |
||||||
|
</TRow> |
||||||
|
</TBody> |
||||||
|
</Table> |
||||||
|
) |
||||||
@ -0,0 +1,58 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import { devices } from 'config' |
||||||
|
|
||||||
|
export const Table = styled.table`` |
||||||
|
|
||||||
|
export const THead = styled.thead`` |
||||||
|
|
||||||
|
export const Th = styled.th` |
||||||
|
width: 250px; |
||||||
|
padding: 0; |
||||||
|
padding-bottom: 25px; |
||||||
|
font-weight: 500; |
||||||
|
font-size: 18px; |
||||||
|
line-height: 22px; |
||||||
|
text-transform: uppercase; |
||||||
|
color: rgba(255, 255, 255, 0.6); |
||||||
|
text-align: start; |
||||||
|
|
||||||
|
:nth-child(1) { |
||||||
|
width: 250px; |
||||||
|
} |
||||||
|
|
||||||
|
:nth-child(2) { |
||||||
|
width: 312px; |
||||||
|
} |
||||||
|
|
||||||
|
:nth-child(3) { |
||||||
|
width: 190px; |
||||||
|
} |
||||||
|
|
||||||
|
@media ${devices.tablet} { |
||||||
|
:nth-child(1) { |
||||||
|
width: 200px; |
||||||
|
} |
||||||
|
|
||||||
|
:nth-child(2) { |
||||||
|
width: 270px; |
||||||
|
} |
||||||
|
|
||||||
|
:nth-child(3) { |
||||||
|
width: 150px; |
||||||
|
} |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
export const TBody = styled.tbody`` |
||||||
|
|
||||||
|
export const TRow = styled.tr`` |
||||||
|
|
||||||
|
export const Td = styled.td` |
||||||
|
padding: 0; |
||||||
|
padding-bottom: 20px; |
||||||
|
font-size: 18px; |
||||||
|
line-height: 22px; |
||||||
|
text-align: start; |
||||||
|
color: #FFFFFF; |
||||||
|
` |
||||||
@ -0,0 +1,151 @@ |
|||||||
|
import { formIds } from 'config/form' |
||||||
|
|
||||||
|
import { Combobox } from 'features/Combobox' |
||||||
|
import { Input } from 'features/Common' |
||||||
|
import { T9n } from 'features/T9n' |
||||||
|
import { Error } from 'features/Common/Input/styled' |
||||||
|
|
||||||
|
import { useUserInfo } from './hooks/useUserInfo' |
||||||
|
|
||||||
|
import { SolidButton } from '../../styled' |
||||||
|
import { Form, ButtonWrapper } from './styled' |
||||||
|
|
||||||
|
const labelWidth = 76 |
||||||
|
|
||||||
|
const { |
||||||
|
address1, |
||||||
|
address2, |
||||||
|
city, |
||||||
|
country, |
||||||
|
firstname, |
||||||
|
formError, |
||||||
|
lastname, |
||||||
|
password, |
||||||
|
phone, |
||||||
|
region, |
||||||
|
} = formIds |
||||||
|
|
||||||
|
export const PagePersonalInfo = () => { |
||||||
|
const { |
||||||
|
cities, |
||||||
|
countries, |
||||||
|
handleSubmit, |
||||||
|
onCitySelect, |
||||||
|
onCountrySelect, |
||||||
|
onPhoneBlur, |
||||||
|
onRegionOrCityChange, |
||||||
|
readFormError, |
||||||
|
readFormValue, |
||||||
|
saveButton, |
||||||
|
updateFormValue, |
||||||
|
} = useUserInfo() |
||||||
|
|
||||||
|
return ( |
||||||
|
<Form> |
||||||
|
<Input |
||||||
|
value={readFormValue(firstname)} |
||||||
|
labelLexic='name' |
||||||
|
autoComplete='given-name' |
||||||
|
labelWidth={labelWidth} |
||||||
|
onChange={updateFormValue(firstname)} |
||||||
|
editIcon |
||||||
|
maxLength={500} |
||||||
|
withError={false} |
||||||
|
/> |
||||||
|
<Input |
||||||
|
value={readFormValue(lastname)} |
||||||
|
labelLexic='lastname' |
||||||
|
autoComplete='family-name' |
||||||
|
labelWidth={labelWidth} |
||||||
|
onChange={updateFormValue(lastname)} |
||||||
|
editIcon |
||||||
|
maxLength={500} |
||||||
|
withError={false} |
||||||
|
/> |
||||||
|
<Input |
||||||
|
value={readFormValue(password)} |
||||||
|
error={readFormError(password)} |
||||||
|
type='password' |
||||||
|
autoComplete='new-password' |
||||||
|
labelLexic='form_password' |
||||||
|
labelWidth={labelWidth} |
||||||
|
onChange={updateFormValue(password)} |
||||||
|
editIcon |
||||||
|
maxLength={500} |
||||||
|
withError={false} |
||||||
|
/> |
||||||
|
<Input |
||||||
|
onBlur={onPhoneBlur} |
||||||
|
value={readFormValue(phone)} |
||||||
|
labelLexic='phone' |
||||||
|
autoComplete='tel' |
||||||
|
labelWidth={labelWidth} |
||||||
|
onChange={updateFormValue(phone)} |
||||||
|
error={readFormError(phone)} |
||||||
|
editIcon |
||||||
|
maxLength={100} |
||||||
|
withError={false} |
||||||
|
/> |
||||||
|
<Combobox |
||||||
|
value={readFormValue(country)} |
||||||
|
labelLexic='form_country' |
||||||
|
labelWidth={labelWidth} |
||||||
|
onChange={updateFormValue(country)} |
||||||
|
options={countries} |
||||||
|
onSelect={onCountrySelect} |
||||||
|
withArrow |
||||||
|
withError={false} |
||||||
|
/> |
||||||
|
<Input |
||||||
|
value={readFormValue(region)} |
||||||
|
labelLexic='form_region' |
||||||
|
labelWidth={labelWidth} |
||||||
|
onChange={onRegionOrCityChange(region)} |
||||||
|
editIcon |
||||||
|
maxLength={500} |
||||||
|
withError={false} |
||||||
|
/> |
||||||
|
<Combobox |
||||||
|
value={readFormValue(city)} |
||||||
|
labelLexic='form_city' |
||||||
|
labelWidth={labelWidth} |
||||||
|
onChange={onRegionOrCityChange(city)} |
||||||
|
options={cities} |
||||||
|
onSelect={onCitySelect} |
||||||
|
maxLength={500} |
||||||
|
withArrow |
||||||
|
withError={false} |
||||||
|
/> |
||||||
|
<Input |
||||||
|
value={readFormValue(address1)} |
||||||
|
labelLexic='form_address1' |
||||||
|
labelWidth={labelWidth} |
||||||
|
autoComplete='address-line1' |
||||||
|
onChange={updateFormValue(address1)} |
||||||
|
editIcon |
||||||
|
maxLength={500} |
||||||
|
withError={false} |
||||||
|
/> |
||||||
|
<Input |
||||||
|
value={readFormValue(address2)} |
||||||
|
labelLexic='form_address2' |
||||||
|
labelWidth={labelWidth} |
||||||
|
autoComplete='address-line2' |
||||||
|
onChange={updateFormValue(address2)} |
||||||
|
editIcon |
||||||
|
maxLength={500} |
||||||
|
withError={false} |
||||||
|
/> |
||||||
|
<ButtonWrapper> |
||||||
|
<SolidButton |
||||||
|
type='button' |
||||||
|
onClick={handleSubmit} |
||||||
|
ref={saveButton} |
||||||
|
> |
||||||
|
<T9n t='save_changes' /> |
||||||
|
</SolidButton> |
||||||
|
<Error t={readFormError(formError) || ''} /> |
||||||
|
</ButtonWrapper> |
||||||
|
</Form> |
||||||
|
) |
||||||
|
} |
||||||
@ -0,0 +1,37 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import { devices } from 'config/devices' |
||||||
|
|
||||||
|
import { Column, InputWrapper } from 'features/Common/Input/styled' |
||||||
|
|
||||||
|
export const Form = styled.div` |
||||||
|
min-width: 560px; |
||||||
|
|
||||||
|
${Column}:first-child ${InputWrapper} { |
||||||
|
margin-top: 0; |
||||||
|
} |
||||||
|
|
||||||
|
${InputWrapper} { |
||||||
|
height: 50px; |
||||||
|
margin-top: 10px; |
||||||
|
} |
||||||
|
|
||||||
|
@media ${devices.tablet} { |
||||||
|
min-width: auto; |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
export const ButtonWrapper = styled.div` |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: start; |
||||||
|
margin-top: 35px; |
||||||
|
|
||||||
|
@media ${devices.tablet} { |
||||||
|
align-self: center; |
||||||
|
} |
||||||
|
|
||||||
|
@media ${devices.mobile} { |
||||||
|
width: 335px; |
||||||
|
} |
||||||
|
` |
||||||
@ -0,0 +1,97 @@ |
|||||||
|
import map from 'lodash/map' |
||||||
|
|
||||||
|
import { SportTypes } from 'config' |
||||||
|
|
||||||
|
import type { MatchSubscriptions } from 'requests' |
||||||
|
import { SubscriptionType } from 'requests' |
||||||
|
|
||||||
|
import { useToggle } from 'hooks' |
||||||
|
|
||||||
|
import { SubscriptionModal } from '../SubscriptionsModal' |
||||||
|
import { UserSubscriptionsList } from '../UserSubscriptionsList' |
||||||
|
import { Wrapper, SubscriptionsWrapper } from './styled' |
||||||
|
import { SolidButton, Icon } from '../../styled' |
||||||
|
|
||||||
|
const data: Record<SportTypes, MatchSubscriptions> = { |
||||||
|
[SportTypes.FOOTBALL]: [ |
||||||
|
{ |
||||||
|
description: 'Доступ к прямой трансляции, записи и хайлайты матча', |
||||||
|
header: 'подписка на матч спартак-динамо', |
||||||
|
price: 999, |
||||||
|
subscription_id: 1, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
{ |
||||||
|
description: 'все матчи спартака в сезоне 2020-2021', |
||||||
|
header: 'подписка на матч спартак-динамо', |
||||||
|
price: 999, |
||||||
|
subscription_id: 2, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
{ |
||||||
|
description: 'Доступ к прямой трансляции, записи и хайлайты матча', |
||||||
|
header: 'подписка на матч спартак-динамо', |
||||||
|
price: 999, |
||||||
|
subscription_id: 3, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
], |
||||||
|
[SportTypes.BASKETBALL]: [], |
||||||
|
[SportTypes.HOCKEY]: [ |
||||||
|
{ |
||||||
|
description: 'все матчи спартака в сезоне 2020-2021', |
||||||
|
header: 'подписка на матч спартак-динамо', |
||||||
|
price: 999, |
||||||
|
subscription_id: 4, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
{ |
||||||
|
description: 'Доступ к прямой трансляции, записи и хайлайты матча', |
||||||
|
header: 'подписка на матч спартак-динамо', |
||||||
|
price: 999, |
||||||
|
subscription_id: 5, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
{ |
||||||
|
description: 'Доступ к прямой трансляции, записи и хайлайты матча', |
||||||
|
header: 'подписка на матч спартак-динамо', |
||||||
|
price: 999, |
||||||
|
subscription_id: 6, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
], |
||||||
|
} |
||||||
|
|
||||||
|
export const PageSubscriptions = () => { |
||||||
|
const { |
||||||
|
close, |
||||||
|
isOpen, |
||||||
|
open, |
||||||
|
} = useToggle() |
||||||
|
|
||||||
|
return ( |
||||||
|
<Wrapper> |
||||||
|
<SubscriptionsWrapper> |
||||||
|
{ |
||||||
|
map(data, (subscriptions, sport: SportTypes) => ( |
||||||
|
<UserSubscriptionsList |
||||||
|
key={sport} |
||||||
|
list={subscriptions} |
||||||
|
sport={sport} |
||||||
|
/> |
||||||
|
)) |
||||||
|
} |
||||||
|
</SubscriptionsWrapper> |
||||||
|
|
||||||
|
<SolidButton onClick={open}> |
||||||
|
<Icon src='plusIcon' /> |
||||||
|
Выбрать подписку |
||||||
|
</SolidButton> |
||||||
|
|
||||||
|
<SubscriptionModal |
||||||
|
close={close} |
||||||
|
isOpen={isOpen} |
||||||
|
/> |
||||||
|
</Wrapper> |
||||||
|
) |
||||||
|
} |
||||||
@ -0,0 +1,16 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import { popupScrollbarStyles } from 'features/PopupComponents' |
||||||
|
|
||||||
|
export const Wrapper = styled.div` |
||||||
|
width: 100%; |
||||||
|
` |
||||||
|
|
||||||
|
export const SubscriptionsWrapper = styled.div` |
||||||
|
width: 100%; |
||||||
|
height: 480px; |
||||||
|
overflow-y: auto; |
||||||
|
margin-bottom: 28px; |
||||||
|
|
||||||
|
${popupScrollbarStyles} |
||||||
|
` |
||||||
@ -1,26 +0,0 @@ |
|||||||
import { Link, useLocation } from 'react-router-dom' |
|
||||||
|
|
||||||
import { PAGES } from 'config' |
|
||||||
|
|
||||||
import { Logo } from 'features/Logo' |
|
||||||
import { BlockTitle } from 'features/Login/styled' |
|
||||||
|
|
||||||
import { PageTitleWrapper, TitleTextWrapper } from './styled' |
|
||||||
|
|
||||||
type Props = { |
|
||||||
titleText: string, |
|
||||||
} |
|
||||||
|
|
||||||
export const PageTitle = ({ titleText }: Props) => { |
|
||||||
const location = useLocation() |
|
||||||
return ( |
|
||||||
<PageTitleWrapper> |
|
||||||
<Link to={`${PAGES.home}${location.search}`}> |
|
||||||
<Logo /> |
|
||||||
</Link> |
|
||||||
<TitleTextWrapper> |
|
||||||
<BlockTitle t={titleText} /> |
|
||||||
</TitleTextWrapper> |
|
||||||
</PageTitleWrapper> |
|
||||||
) |
|
||||||
} |
|
||||||
@ -1,30 +0,0 @@ |
|||||||
import styled from 'styled-components/macro' |
|
||||||
|
|
||||||
import { devices } from 'config/devices' |
|
||||||
|
|
||||||
import { BlockTitle } from 'features/Login/styled' |
|
||||||
|
|
||||||
export const PageTitleWrapper = styled.div` |
|
||||||
display: flex; |
|
||||||
justify-content: flex-start; |
|
||||||
align-items: flex-end; |
|
||||||
|
|
||||||
@media ${devices.tablet} { |
|
||||||
flex-direction: column; |
|
||||||
align-items: center; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const TitleTextWrapper = styled.div` |
|
||||||
margin-left: 14px; |
|
||||||
|
|
||||||
${BlockTitle} { |
|
||||||
margin-bottom: 0; |
|
||||||
line-height: 28px; |
|
||||||
} |
|
||||||
|
|
||||||
@media ${devices.tablet} { |
|
||||||
margin-left: 0; |
|
||||||
margin-top: 20px; |
|
||||||
} |
|
||||||
` |
|
||||||
@ -1 +0,0 @@ |
|||||||
export * from './styled' |
|
||||||
@ -1,15 +0,0 @@ |
|||||||
import styled from 'styled-components/macro' |
|
||||||
|
|
||||||
import { devices } from 'config/devices' |
|
||||||
|
|
||||||
export const PlusIconWrapper = styled.span` |
|
||||||
width: 20px; |
|
||||||
height: 20px; |
|
||||||
margin-right: 22px; |
|
||||||
margin-left: 10px; |
|
||||||
background: url('/images/plusIcon.svg') no-repeat; |
|
||||||
|
|
||||||
@media ${devices.laptop} { |
|
||||||
background: url('/images/plusIcon-gray.svg') no-repeat; |
|
||||||
} |
|
||||||
` |
|
||||||
@ -1,65 +0,0 @@ |
|||||||
import { Price } from 'features/Price' |
|
||||||
import { Radio } from 'features/Common/Radio' |
|
||||||
import { Checkbox } from 'features/Common/Checkbox' |
|
||||||
|
|
||||||
import { |
|
||||||
CheckboxWrapper, |
|
||||||
SubscriptionWrapper, |
|
||||||
BoldTextWrapper, |
|
||||||
NormalTextWrapper, |
|
||||||
} from './styled' |
|
||||||
import { PriceWrapper } from '../CardNumber/styled' |
|
||||||
|
|
||||||
type Props = { |
|
||||||
amount: number, |
|
||||||
checked?: boolean, |
|
||||||
id: string, |
|
||||||
inputType?: string, |
|
||||||
label?: string, |
|
||||||
noMarginBottom?: boolean, |
|
||||||
noMarginTop?: boolean, |
|
||||||
packageAction?: string, |
|
||||||
packageName?: string, |
|
||||||
selectSubscription: () => void, |
|
||||||
} |
|
||||||
|
|
||||||
export const Subscription = ({ |
|
||||||
amount, |
|
||||||
checked, |
|
||||||
id, |
|
||||||
inputType, |
|
||||||
label, |
|
||||||
noMarginBottom, |
|
||||||
noMarginTop, |
|
||||||
packageAction, |
|
||||||
packageName, |
|
||||||
selectSubscription, |
|
||||||
}: Props) => ( |
|
||||||
<SubscriptionWrapper |
|
||||||
noMarginTop={noMarginTop} |
|
||||||
noMarginBottom={noMarginBottom} |
|
||||||
> |
|
||||||
{inputType === 'radio' && ( |
|
||||||
<Radio |
|
||||||
id={id} |
|
||||||
checked={checked} |
|
||||||
onClick={selectSubscription} |
|
||||||
label={label} |
|
||||||
/> |
|
||||||
)} |
|
||||||
{inputType === 'checkbox' && ( |
|
||||||
<CheckboxWrapper> |
|
||||||
<Checkbox |
|
||||||
checked={checked} |
|
||||||
onClick={selectSubscription} |
|
||||||
label={label} |
|
||||||
/> |
|
||||||
</CheckboxWrapper> |
|
||||||
)} |
|
||||||
{packageName && <BoldTextWrapper>{packageName}</BoldTextWrapper>} |
|
||||||
{packageAction && <NormalTextWrapper>{packageAction}</NormalTextWrapper>} |
|
||||||
<PriceWrapper> |
|
||||||
<Price amount={amount} /> |
|
||||||
</PriceWrapper> |
|
||||||
</SubscriptionWrapper> |
|
||||||
) |
|
||||||
@ -1,84 +0,0 @@ |
|||||||
import styled, { css } from 'styled-components/macro' |
|
||||||
|
|
||||||
import { Label as CheckboxLabel } from 'features/Common/Checkbox/styled' |
|
||||||
import { Label as RadioLabel } from 'features/Common/Radio/styled' |
|
||||||
|
|
||||||
import { TextWrapper } from '../CardNumber/styled' |
|
||||||
|
|
||||||
type Props = { |
|
||||||
noMarginBottom?: boolean, |
|
||||||
noMarginTop?: boolean, |
|
||||||
} |
|
||||||
|
|
||||||
export const SubscriptionWrapperStyles = css<Props>` |
|
||||||
display: flex; |
|
||||||
align-items: center; |
|
||||||
justify-content: flex-start; |
|
||||||
height: 48px; |
|
||||||
background-color: #3F3F3F; |
|
||||||
border-top: ${({ noMarginBottom, noMarginTop }) => (noMarginBottom && noMarginTop ? '1px solid #000' : '')}; |
|
||||||
border-bottom: ${({ noMarginBottom, noMarginTop }) => (noMarginBottom && noMarginTop ? '1px solid #000' : '')}; |
|
||||||
border-radius: ${({ noMarginBottom, noMarginTop }) => { |
|
||||||
switch (true) { |
|
||||||
case noMarginTop && noMarginBottom: |
|
||||||
return '0' |
|
||||||
case noMarginTop: |
|
||||||
return '0 0 2px 2px' |
|
||||||
case noMarginBottom: |
|
||||||
return '2px 2px 0 0' |
|
||||||
default: |
|
||||||
return '2px' |
|
||||||
} |
|
||||||
}}; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
margin-top: ${({ noMarginTop }) => (noMarginTop ? '0' : '20px')}; |
|
||||||
margin-bottom: ${({ noMarginBottom }) => (noMarginBottom ? '0' : '20px')}; |
|
||||||
width: 100%; |
|
||||||
${RadioLabel}::before { |
|
||||||
margin-left: 22px; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const SubscriptionWrapper = styled.div` |
|
||||||
${SubscriptionWrapperStyles}; |
|
||||||
|
|
||||||
label{ |
|
||||||
font-size: 16px; |
|
||||||
} |
|
||||||
&:nth-child(n+1) { |
|
||||||
border-bottom: ${({ noMarginBottom }) => (noMarginBottom ? '1px solid #000' : '')}; |
|
||||||
border-top: ${({ noMarginBottom, noMarginTop }) => (noMarginBottom && noMarginTop ? 'none' : '')}; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const CheckboxWrapper = styled.div` |
|
||||||
${CheckboxLabel} { |
|
||||||
font-weight: bold; |
|
||||||
font-size: 16px; |
|
||||||
line-height: 24px; |
|
||||||
|
|
||||||
&::before { |
|
||||||
margin-left: 22px; |
|
||||||
} |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const BoldTextWrapper = styled(TextWrapper)` |
|
||||||
color: #fff; |
|
||||||
font-weight: bold; |
|
||||||
font-size: 20px; |
|
||||||
margin-right: 24px; |
|
||||||
|
|
||||||
&:hover { |
|
||||||
cursor: default; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const NormalTextWrapper = styled(TextWrapper)` |
|
||||||
color: #fff; |
|
||||||
font-weight: normal; |
|
||||||
font-size: 16px; |
|
||||||
margin-right: 24px; |
|
||||||
` |
|
||||||
@ -0,0 +1,105 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import map from 'lodash/map' |
||||||
|
|
||||||
|
import { SportTypes } from 'config' |
||||||
|
|
||||||
|
import { SubscriptionType } from 'requests' |
||||||
|
|
||||||
|
import { popupScrollbarStyles } from 'features/PopupComponents' |
||||||
|
|
||||||
|
import { SubscriptionsList } from '../SubscriptionsList' |
||||||
|
|
||||||
|
type Subscription = { |
||||||
|
header: string, |
||||||
|
id: number, |
||||||
|
price: number, |
||||||
|
type: SubscriptionType, |
||||||
|
} |
||||||
|
|
||||||
|
export type Subscriptions = Array<Subscription> |
||||||
|
|
||||||
|
const Wrapper = styled.div` |
||||||
|
width: 100%; |
||||||
|
height: 474px; |
||||||
|
overflow-y: auto; |
||||||
|
margin-top: 36px; |
||||||
|
|
||||||
|
${popupScrollbarStyles} |
||||||
|
` |
||||||
|
|
||||||
|
const data: Record<SportTypes, Subscriptions> = { |
||||||
|
[SportTypes.FOOTBALL]: [ |
||||||
|
{ |
||||||
|
header: 'Российская премьер-лига', |
||||||
|
id: 1, |
||||||
|
price: 199, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
{ |
||||||
|
header: 'Primera División', |
||||||
|
id: 2, |
||||||
|
price: 999, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
{ |
||||||
|
header: 'Manchester United', |
||||||
|
id: 3, |
||||||
|
price: 999, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
{ |
||||||
|
header: 'Российская премьер-лига', |
||||||
|
id: 4, |
||||||
|
price: 199, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
], |
||||||
|
[SportTypes.HOCKEY]: [ |
||||||
|
{ |
||||||
|
header: 'Российская премьер-лига', |
||||||
|
id: 1, |
||||||
|
price: 199, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
{ |
||||||
|
header: 'Primera División', |
||||||
|
id: 2, |
||||||
|
price: 999, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
{ |
||||||
|
header: 'Manchester United', |
||||||
|
id: 3, |
||||||
|
price: 999, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
{ |
||||||
|
header: 'Российская премьер-лига', |
||||||
|
id: 4, |
||||||
|
price: 199, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
{ |
||||||
|
header: 'Российская премьер-лига', |
||||||
|
id: 5, |
||||||
|
price: 199, |
||||||
|
type: SubscriptionType.Month, |
||||||
|
}, |
||||||
|
], |
||||||
|
[SportTypes.BASKETBALL]: [], |
||||||
|
} |
||||||
|
|
||||||
|
export const SubscriptionsBySport = () => ( |
||||||
|
<Wrapper> |
||||||
|
{ |
||||||
|
map(data, (subscriptions, sport: SportTypes) => ( |
||||||
|
<SubscriptionsList |
||||||
|
key={sport} |
||||||
|
list={subscriptions} |
||||||
|
sport={sport} |
||||||
|
/> |
||||||
|
)) |
||||||
|
} |
||||||
|
</Wrapper> |
||||||
|
) |
||||||
@ -1,97 +0,0 @@ |
|||||||
import { Fragment } from 'react' |
|
||||||
|
|
||||||
import map from 'lodash/map' |
|
||||||
import isNumber from 'lodash/isNumber' |
|
||||||
import isArray from 'lodash/isArray' |
|
||||||
import find from 'lodash/find' |
|
||||||
|
|
||||||
import type { SportList } from 'requests/getSportList' |
|
||||||
|
|
||||||
import { useLexicsStore } from 'features/LexicsStore' |
|
||||||
|
|
||||||
import type { Subscription, UserSubscriptions } from '../../hooks/useUserSubscriptions' |
|
||||||
import { UserAccountButton } from '../UserAccountButton' |
|
||||||
import { UserAccountSubscription } from '../UserAccountSubscription' |
|
||||||
import { UserAccountSubscriptionMatch } from '../UserAccountSubscriptionMatch' |
|
||||||
import { TextNoBorder } from '../TextNoBorder' |
|
||||||
|
|
||||||
import { |
|
||||||
UserAccountBlockTitle, |
|
||||||
SubscriptionTitle, |
|
||||||
} from './styled' |
|
||||||
|
|
||||||
type Props = { |
|
||||||
deleteUserSubscription: (subscription: Subscription, sport: number) => void, |
|
||||||
open: () => void, |
|
||||||
selectedSubscription: number | null, |
|
||||||
selectedSubscriptionLexic: string, |
|
||||||
sportList: SportList, |
|
||||||
userSubscriptions: any, |
|
||||||
} |
|
||||||
|
|
||||||
export const SubscriptionsForm = ({ |
|
||||||
deleteUserSubscription, |
|
||||||
open, |
|
||||||
selectedSubscription, |
|
||||||
selectedSubscriptionLexic, |
|
||||||
sportList, |
|
||||||
userSubscriptions, |
|
||||||
}: Props) => { |
|
||||||
const { translate } = useLexicsStore() |
|
||||||
|
|
||||||
return ( |
|
||||||
<Fragment> |
|
||||||
<UserAccountBlockTitle t='subscriptions' /> |
|
||||||
{isNumber(selectedSubscription) && ( |
|
||||||
<UserAccountSubscription |
|
||||||
amount={1999} |
|
||||||
packageName={selectedSubscriptionLexic} |
|
||||||
/> |
|
||||||
)} |
|
||||||
{map(userSubscriptions, (subscription) => { |
|
||||||
const sportName = find(sportList, (item) => subscription.sport === item.id) |
|
||||||
return ( |
|
||||||
<Fragment key={subscription.sport}> |
|
||||||
{sportName && <SubscriptionTitle t={sportName.lexic} />} |
|
||||||
{map(subscription, (item: UserSubscriptions) => { |
|
||||||
if (isArray(item)) { |
|
||||||
return map(item, (subscriptionObj) => { |
|
||||||
if (subscriptionObj.date) { |
|
||||||
return ( |
|
||||||
<UserAccountSubscriptionMatch |
|
||||||
key={subscriptionObj.id} |
|
||||||
noMarginBottom |
|
||||||
amount={1999} |
|
||||||
matchData={subscriptionObj} |
|
||||||
deleteSubscription={ |
|
||||||
() => deleteUserSubscription(subscriptionObj, subscription.sport) |
|
||||||
} |
|
||||||
/> |
|
||||||
) |
|
||||||
} |
|
||||||
return ( |
|
||||||
<UserAccountSubscription |
|
||||||
key={subscriptionObj.id} |
|
||||||
noMarginBottom |
|
||||||
amount={1999} |
|
||||||
label={subscriptionObj} |
|
||||||
deleteSubscription={ |
|
||||||
() => deleteUserSubscription(subscriptionObj, subscription.sport) |
|
||||||
} |
|
||||||
/> |
|
||||||
) |
|
||||||
}) |
|
||||||
} |
|
||||||
return null |
|
||||||
})} |
|
||||||
</Fragment> |
|
||||||
) |
|
||||||
})} |
|
||||||
<UserAccountButton text='select_subscription' open={open} /> |
|
||||||
<TextNoBorder |
|
||||||
text={`${translate('next_debit')} 31.02.2020`} |
|
||||||
amount={4796} |
|
||||||
/> |
|
||||||
</Fragment> |
|
||||||
) |
|
||||||
} |
|
||||||
@ -1,22 +0,0 @@ |
|||||||
import styled from 'styled-components/macro' |
|
||||||
|
|
||||||
import { devices } from 'config/devices' |
|
||||||
|
|
||||||
import { BlockTitle } from 'features/Login/styled' |
|
||||||
import { T9n } from 'features/T9n' |
|
||||||
|
|
||||||
export const UserAccountBlockTitle = styled(BlockTitle)` |
|
||||||
align-self: flex-start; |
|
||||||
|
|
||||||
@media ${devices.tablet} { |
|
||||||
align-self: center; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const SubscriptionTitle = styled(T9n)` |
|
||||||
color: white; |
|
||||||
font-weight: 500; |
|
||||||
font-size: 25px; |
|
||||||
align-self: flex-start; |
|
||||||
margin-top: 40px; |
|
||||||
` |
|
||||||
@ -0,0 +1,48 @@ |
|||||||
|
import isEmpty from 'lodash/isEmpty' |
||||||
|
import map from 'lodash/map' |
||||||
|
|
||||||
|
import { SportTypes } from 'config' |
||||||
|
|
||||||
|
import type { Subscriptions } from '../SubscriptionsBySport' |
||||||
|
import { |
||||||
|
Wrapper, |
||||||
|
SportName, |
||||||
|
Header, |
||||||
|
Count, |
||||||
|
List, |
||||||
|
Item, |
||||||
|
Checkbox, |
||||||
|
Price, |
||||||
|
} from './styled' |
||||||
|
|
||||||
|
type Props = { |
||||||
|
list: Subscriptions, |
||||||
|
sport: SportTypes, |
||||||
|
} |
||||||
|
|
||||||
|
export const SubscriptionsList = ({ list, sport }: Props) => { |
||||||
|
if (isEmpty(list)) return null |
||||||
|
return ( |
||||||
|
<Wrapper> |
||||||
|
<Header> |
||||||
|
<SportName sport={sport} /> |
||||||
|
<Count>2</Count> |
||||||
|
</Header> |
||||||
|
<List> |
||||||
|
{ |
||||||
|
map(list, ({ |
||||||
|
header, |
||||||
|
id, |
||||||
|
price, |
||||||
|
type, |
||||||
|
}) => ( |
||||||
|
<Item key={id}> |
||||||
|
<Checkbox label={header} checked /> |
||||||
|
<Price amount={price} perPeriod={`per_${type}`} /> |
||||||
|
</Item> |
||||||
|
)) |
||||||
|
} |
||||||
|
</List> |
||||||
|
</Wrapper> |
||||||
|
) |
||||||
|
} |
||||||
@ -0,0 +1,83 @@ |
|||||||
|
import styled, { css } from 'styled-components/macro' |
||||||
|
|
||||||
|
import { Checkbox as CheckboxBase, SportName as SportNameBase } from 'features/Common' |
||||||
|
import { CheckboxSvg } from 'features/Common/Checkbox/Icon' |
||||||
|
import { Label } from 'features/Common/Checkbox/styled' |
||||||
|
|
||||||
|
import { Price as BasePrice } from 'features/Price' |
||||||
|
import { PriceAmount, PriceDetails } from 'features/Price/styled' |
||||||
|
|
||||||
|
export const Wrapper = styled.div` |
||||||
|
:not(:first-child) { |
||||||
|
margin-top: 21px; |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
export const Header = styled.div` |
||||||
|
display: flex; |
||||||
|
padding: 0 90px; |
||||||
|
` |
||||||
|
|
||||||
|
const textStyles = css` |
||||||
|
font-style: normal; |
||||||
|
font-weight: normal; |
||||||
|
font-size: 20px; |
||||||
|
line-height: 21px; |
||||||
|
` |
||||||
|
|
||||||
|
export const SportName = styled(SportNameBase)` |
||||||
|
color: #fff; |
||||||
|
${textStyles} |
||||||
|
` |
||||||
|
|
||||||
|
export const Count = styled.span` |
||||||
|
color: rgba(255, 255, 255, 0.5); |
||||||
|
${textStyles} |
||||||
|
` |
||||||
|
|
||||||
|
export const List = styled.ul` |
||||||
|
margin-top: 4px; |
||||||
|
padding-left: 40px; |
||||||
|
padding-right: 32px; |
||||||
|
` |
||||||
|
|
||||||
|
export const Item = styled.li` |
||||||
|
height: 50px; |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
align-items: center; |
||||||
|
font-weight: 600; |
||||||
|
font-size: 20px; |
||||||
|
line-height: 50px; |
||||||
|
color: #fff; |
||||||
|
` |
||||||
|
|
||||||
|
export const Checkbox = styled(CheckboxBase)` |
||||||
|
align-items: center; |
||||||
|
|
||||||
|
${CheckboxSvg} { |
||||||
|
margin-right: 25px; |
||||||
|
align-self: center; |
||||||
|
} |
||||||
|
|
||||||
|
${Label} { |
||||||
|
font-style: normal; |
||||||
|
font-weight: 600; |
||||||
|
font-size: 20px; |
||||||
|
line-height: 50px; |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
` |
||||||
@ -1,68 +1,39 @@ |
|||||||
import map from 'lodash/map' |
import { SubscriptionType } from 'requests' |
||||||
|
|
||||||
import type { SubscriptionType } from 'requests/getSubscriptions' |
|
||||||
|
|
||||||
import { Modal } from 'features/Modal' |
|
||||||
import { useLexicsStore } from 'features/LexicsStore' |
|
||||||
|
|
||||||
import { Subscription } from '../Subscription' |
|
||||||
|
|
||||||
|
import { SubscriptionsBySport } from '../SubscriptionsBySport' |
||||||
import { |
import { |
||||||
AddSubscriptionModal, |
Modal, |
||||||
Line, |
PaymentPeriodTabs, |
||||||
ModalTitle, |
Header, |
||||||
SubscriptionsWrapper, |
ButtonsWrapper, |
||||||
SaveButton, |
SaveButton, |
||||||
|
CancelButton, |
||||||
} from './styled' |
} from './styled' |
||||||
|
|
||||||
type Props = { |
type Props = { |
||||||
close: () => void, |
close: () => void, |
||||||
isOpen: boolean, |
isOpen: boolean, |
||||||
saveSubscription: () => void, |
|
||||||
selectedSubscription: number | null, |
|
||||||
setSelectedSubscription: (arg: number | null) => void, |
|
||||||
subscriptions: Array<SubscriptionType>, |
|
||||||
} |
} |
||||||
|
|
||||||
export const SubscriptionModal = ({ |
export const SubscriptionModal = ({ |
||||||
close, |
close, |
||||||
isOpen, |
isOpen, |
||||||
saveSubscription, |
}: Props) => ( |
||||||
selectedSubscription, |
<Modal |
||||||
setSelectedSubscription, |
isOpen={isOpen} |
||||||
subscriptions, |
close={close} |
||||||
}: Props) => { |
withCloseButton={false} |
||||||
const { translate } = useLexicsStore() |
> |
||||||
|
<Header t='select_subscription' /> |
||||||
|
<PaymentPeriodTabs |
||||||
|
onPeriodSelect={() => {}} |
||||||
|
selectedPeriod={SubscriptionType.Month} |
||||||
|
/> |
||||||
|
<SubscriptionsBySport /> |
||||||
|
|
||||||
return ( |
<ButtonsWrapper> |
||||||
<Modal |
<CancelButton onClick={close}>Отменить</CancelButton> |
||||||
isOpen={isOpen} |
<SaveButton onClick={close}>Сохранить</SaveButton> |
||||||
close={close} |
</ButtonsWrapper> |
||||||
> |
</Modal> |
||||||
<AddSubscriptionModal> |
) |
||||||
<ModalTitle t='select_subscription' /> |
|
||||||
<Line /> |
|
||||||
<SubscriptionsWrapper> |
|
||||||
{map(subscriptions, (subscription) => ( |
|
||||||
<Subscription |
|
||||||
id={`${subscription.id}`} |
|
||||||
checked={selectedSubscription === subscription.id} |
|
||||||
key={`${subscription.id}`} |
|
||||||
noMarginBottom |
|
||||||
noMarginTop |
|
||||||
amount={1999} |
|
||||||
inputType='radio' |
|
||||||
label={translate(`${subscription.lexic}`)} |
|
||||||
selectSubscription={() => { |
|
||||||
setSelectedSubscription(subscription.id) |
|
||||||
}} |
|
||||||
/> |
|
||||||
))} |
|
||||||
</SubscriptionsWrapper> |
|
||||||
<SaveButton onClick={saveSubscription}> |
|
||||||
Save |
|
||||||
</SaveButton> |
|
||||||
</AddSubscriptionModal> |
|
||||||
</Modal> |
|
||||||
) |
|
||||||
} |
|
||||||
|
|||||||
@ -1,23 +0,0 @@ |
|||||||
import { Price } from 'features/Price' |
|
||||||
|
|
||||||
import { TextNoBorderWrapper, TextNoBorderTextWrapper } from './styled' |
|
||||||
import { PriceWrapper } from '../CardNumber/styled' |
|
||||||
|
|
||||||
type Props = { |
|
||||||
amount: number, |
|
||||||
text: string, |
|
||||||
} |
|
||||||
|
|
||||||
export const TextNoBorder = ({ |
|
||||||
amount, |
|
||||||
text, |
|
||||||
}: Props) => ( |
|
||||||
<TextNoBorderWrapper> |
|
||||||
<TextNoBorderTextWrapper> |
|
||||||
{text} |
|
||||||
</TextNoBorderTextWrapper> |
|
||||||
<PriceWrapper> |
|
||||||
<Price amount={amount} /> |
|
||||||
</PriceWrapper> |
|
||||||
</TextNoBorderWrapper> |
|
||||||
) |
|
||||||
@ -1,40 +0,0 @@ |
|||||||
import styled from 'styled-components/macro' |
|
||||||
|
|
||||||
import { devices } from 'config/devices' |
|
||||||
|
|
||||||
import { PriceWrapper, TextWrapper } from '../CardNumber/styled' |
|
||||||
|
|
||||||
export const TextNoBorderWrapper = styled.div` |
|
||||||
display: flex; |
|
||||||
align-items: center; |
|
||||||
justify-content: space-between; |
|
||||||
height: 48px; |
|
||||||
background-color: transparent; |
|
||||||
border: none; |
|
||||||
margin-top: 20px; |
|
||||||
width: 100%; |
|
||||||
|
|
||||||
${PriceWrapper} { |
|
||||||
margin-right: 0; |
|
||||||
} |
|
||||||
|
|
||||||
@media ${devices.laptop} { |
|
||||||
margin-top: 38px; |
|
||||||
} |
|
||||||
|
|
||||||
@media ${devices.tablet} { |
|
||||||
max-width: 415px; |
|
||||||
} |
|
||||||
|
|
||||||
@media ${devices.mobile} { |
|
||||||
max-width: 335px; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const TextNoBorderTextWrapper = styled(TextWrapper)` |
|
||||||
font-size: 20px; |
|
||||||
|
|
||||||
@media ${devices.tablet} { |
|
||||||
font-size: 14px; |
|
||||||
} |
|
||||||
` |
|
||||||
@ -1,18 +0,0 @@ |
|||||||
import { T9n } from 'features/T9n' |
|
||||||
|
|
||||||
import { PlusIconWrapper } from '../PlusIcon' |
|
||||||
import { UserAccountButtonWrapper, PlusIconTextWrapper } from './styled' |
|
||||||
|
|
||||||
type Props = { |
|
||||||
open?: () => void, |
|
||||||
text: string, |
|
||||||
} |
|
||||||
|
|
||||||
export const UserAccountButton = ({ open, text }: Props) => ( |
|
||||||
<UserAccountButtonWrapper onClick={open}> |
|
||||||
<PlusIconWrapper /> |
|
||||||
<PlusIconTextWrapper> |
|
||||||
<T9n t={text} /> |
|
||||||
</PlusIconTextWrapper> |
|
||||||
</UserAccountButtonWrapper> |
|
||||||
) |
|
||||||
@ -1,51 +0,0 @@ |
|||||||
import styled from 'styled-components/macro' |
|
||||||
|
|
||||||
import { devices } from 'config/devices' |
|
||||||
|
|
||||||
import { outlineButtonStyles } from 'features/Common/Button' |
|
||||||
|
|
||||||
import { TextWrapper } from '../CardNumber/styled' |
|
||||||
|
|
||||||
export const UserAccountButtonWrapper = styled.div` |
|
||||||
${outlineButtonStyles}; |
|
||||||
width: 288px; |
|
||||||
margin-top: 20px; |
|
||||||
display: flex; |
|
||||||
align-items: center; |
|
||||||
align-self: flex-start; |
|
||||||
color: white; |
|
||||||
font-weight: bold; |
|
||||||
border-color: #0033CC; |
|
||||||
background-color: #0033CC; |
|
||||||
|
|
||||||
&:hover { |
|
||||||
cursor: pointer; |
|
||||||
} |
|
||||||
|
|
||||||
@media ${devices.laptop} { |
|
||||||
background-color: transparent; |
|
||||||
width: 100%; |
|
||||||
color: #494949; |
|
||||||
border-color: #494949; |
|
||||||
} |
|
||||||
|
|
||||||
@media ${devices.tablet} { |
|
||||||
max-width: 415px; |
|
||||||
align-self: center; |
|
||||||
} |
|
||||||
|
|
||||||
@media ${devices.mobile} { |
|
||||||
max-width: 335px; |
|
||||||
align-self: center; |
|
||||||
margin-top: 10px; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const PlusIconTextWrapper = styled(TextWrapper)` |
|
||||||
font-size: 20px; |
|
||||||
color: white; |
|
||||||
|
|
||||||
@media ${devices.laptop} { |
|
||||||
color: #494949; |
|
||||||
} |
|
||||||
` |
|
||||||
@ -1,58 +0,0 @@ |
|||||||
import { T9n } from 'features/T9n' |
|
||||||
import type { ObjectWithName } from 'features/Name' |
|
||||||
import { Name } from 'features/Name' |
|
||||||
import { Price } from 'features/Price' |
|
||||||
|
|
||||||
import { |
|
||||||
UserAccountSubscriptionWrapper, |
|
||||||
UserAccountBoldTextWrapper, |
|
||||||
UserAccountNormalTextWrapper, |
|
||||||
UserAccountText, |
|
||||||
UserAccountDeleteButton, |
|
||||||
} from './styled' |
|
||||||
import { PriceWrapper } from '../CardNumber/styled' |
|
||||||
|
|
||||||
type Props = { |
|
||||||
amount: number, |
|
||||||
deleteSubscription?: () => void, |
|
||||||
label?: ObjectWithName, |
|
||||||
noMarginBottom?: boolean, |
|
||||||
noMarginTop?: boolean, |
|
||||||
packageAction?: string, |
|
||||||
packageName?: string, |
|
||||||
} |
|
||||||
|
|
||||||
export const UserAccountSubscription = ({ |
|
||||||
amount, |
|
||||||
deleteSubscription, |
|
||||||
label, |
|
||||||
noMarginBottom, |
|
||||||
noMarginTop, |
|
||||||
packageAction, |
|
||||||
packageName, |
|
||||||
}: Props) => ( |
|
||||||
<UserAccountSubscriptionWrapper |
|
||||||
noMarginTop={noMarginTop} |
|
||||||
noMarginBottom={noMarginBottom} |
|
||||||
> |
|
||||||
<UserAccountText> |
|
||||||
<Name nameObj={label || {}} /> |
|
||||||
</UserAccountText> |
|
||||||
{packageName |
|
||||||
&& ( |
|
||||||
<UserAccountBoldTextWrapper> |
|
||||||
<T9n t={packageName} /> |
|
||||||
</UserAccountBoldTextWrapper> |
|
||||||
)} |
|
||||||
{packageAction |
|
||||||
&& <UserAccountNormalTextWrapper>{packageAction}</UserAccountNormalTextWrapper>} |
|
||||||
<PriceWrapper> |
|
||||||
<Price amount={amount} /> |
|
||||||
</PriceWrapper> |
|
||||||
{deleteSubscription && ( |
|
||||||
<UserAccountDeleteButton type='button' onClick={deleteSubscription}> |
|
||||||
<T9n t='delete' /> |
|
||||||
</UserAccountDeleteButton> |
|
||||||
)} |
|
||||||
</UserAccountSubscriptionWrapper> |
|
||||||
) |
|
||||||
@ -1,112 +0,0 @@ |
|||||||
import styled, { css } from 'styled-components/macro' |
|
||||||
|
|
||||||
import { devices } from 'config/devices' |
|
||||||
|
|
||||||
import { Label as CheckboxLabel } from 'features/Common/Checkbox/styled' |
|
||||||
import { Label as RadioLabel } from 'features/Common/Radio/styled' |
|
||||||
|
|
||||||
import { TextWrapper } from '../CardNumber/styled' |
|
||||||
|
|
||||||
type Props = { |
|
||||||
noMarginBottom?: boolean, |
|
||||||
noMarginTop?: boolean, |
|
||||||
} |
|
||||||
|
|
||||||
export const SubscriptionWrapperStyles = css<Props>` |
|
||||||
display: flex; |
|
||||||
align-items: center; |
|
||||||
justify-content: flex-start; |
|
||||||
height: 48px; |
|
||||||
background-color: #3F3F3F; |
|
||||||
border-top: ${({ noMarginBottom, noMarginTop }) => (noMarginBottom && noMarginTop ? '1px solid #000' : '')}; |
|
||||||
border-bottom: ${({ noMarginBottom, noMarginTop }) => (noMarginBottom && noMarginTop ? '1px solid #000' : '')}; |
|
||||||
border-radius: ${({ noMarginBottom, noMarginTop }) => { |
|
||||||
switch (true) { |
|
||||||
case noMarginTop && noMarginBottom: |
|
||||||
return '0' |
|
||||||
case noMarginTop: |
|
||||||
return '0 0 2px 2px' |
|
||||||
case noMarginBottom: |
|
||||||
return '2px 2px 0 0' |
|
||||||
default: |
|
||||||
return '2px' |
|
||||||
} |
|
||||||
}}; |
|
||||||
margin-top: ${({ noMarginTop }) => (noMarginTop ? '0' : '20px')}; |
|
||||||
margin-bottom: ${({ noMarginBottom }) => (noMarginBottom ? '0' : '20px')}; |
|
||||||
padding-left: 20px; |
|
||||||
width: 100%; |
|
||||||
${RadioLabel}::before { |
|
||||||
margin-left: 22px; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const UserAccountDeleteButton = styled.button` |
|
||||||
width: 80px; |
|
||||||
height: 100%; |
|
||||||
background: red; |
|
||||||
cursor: pointer; |
|
||||||
border: none; |
|
||||||
color: white; |
|
||||||
font-size: 15px; |
|
||||||
font-weight: 600; |
|
||||||
display: none; |
|
||||||
` |
|
||||||
|
|
||||||
export const UserAccountSubscriptionWrapper = styled.div` |
|
||||||
${SubscriptionWrapperStyles}; |
|
||||||
&:hover { |
|
||||||
${UserAccountDeleteButton} { |
|
||||||
display: block; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
&:nth-child(n+1) { |
|
||||||
border-bottom: ${({ noMarginBottom }) => (noMarginBottom ? '1px solid #000' : '')}; |
|
||||||
border-top: ${({ noMarginBottom, noMarginTop }) => (noMarginBottom && noMarginTop ? 'none' : '')}; |
|
||||||
} |
|
||||||
|
|
||||||
@media ${devices.tablet} { |
|
||||||
max-width: 415px; |
|
||||||
} |
|
||||||
|
|
||||||
@media ${devices.mobile} { |
|
||||||
max-width: 355px; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const CheckboxWrapper = styled.div` |
|
||||||
${CheckboxLabel} { |
|
||||||
font-weight: bold; |
|
||||||
font-size: 16px; |
|
||||||
line-height: 24px; |
|
||||||
|
|
||||||
&::before { |
|
||||||
margin-left: 22px; |
|
||||||
} |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const UserAccountText = styled.p` |
|
||||||
color: #fff; |
|
||||||
font-size: 18px; |
|
||||||
cursor: default; |
|
||||||
` |
|
||||||
|
|
||||||
export const UserAccountBoldTextWrapper = styled(TextWrapper)` |
|
||||||
color: #fff; |
|
||||||
font-weight: bold; |
|
||||||
font-size: 20px; |
|
||||||
margin-right: 24px; |
|
||||||
|
|
||||||
&:hover { |
|
||||||
cursor: default; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const UserAccountNormalTextWrapper = styled(TextWrapper)` |
|
||||||
color: #fff; |
|
||||||
font-weight: normal; |
|
||||||
font-size: 16px; |
|
||||||
margin-right: 24px; |
|
||||||
` |
|
||||||
@ -1,71 +0,0 @@ |
|||||||
import { Fragment } from 'react' |
|
||||||
|
|
||||||
import format from 'date-fns/format' |
|
||||||
|
|
||||||
import type { Match } from 'features/UserAccount/hooks/useUserSubscriptions' |
|
||||||
import { Name } from 'features/Name' |
|
||||||
import { Price } from 'features/Price' |
|
||||||
import { T9n } from 'features/T9n' |
|
||||||
|
|
||||||
import { |
|
||||||
UserAccountSubscriptionWrapper, |
|
||||||
UserAccountBoldTextWrapper, |
|
||||||
UserAccountTextLeftPart, |
|
||||||
UserAccountNormalTextWrapper, |
|
||||||
UserAccountText, |
|
||||||
UserAccountDate, |
|
||||||
UserAccountDeleteButton, |
|
||||||
UserAccountTeams, |
|
||||||
} from './styled' |
|
||||||
import { PriceWrapper } from '../CardNumber/styled' |
|
||||||
|
|
||||||
type Props = { |
|
||||||
amount: number, |
|
||||||
deleteSubscription?: () => void, |
|
||||||
matchData: Match, |
|
||||||
noMarginBottom?: boolean, |
|
||||||
noMarginTop?: boolean, |
|
||||||
packageAction?: string, |
|
||||||
packageName?: string, |
|
||||||
} |
|
||||||
|
|
||||||
export const UserAccountSubscriptionMatch = ({ |
|
||||||
amount, |
|
||||||
deleteSubscription, |
|
||||||
matchData, |
|
||||||
noMarginBottom, |
|
||||||
noMarginTop, |
|
||||||
packageAction, |
|
||||||
packageName, |
|
||||||
}: Props) => ( |
|
||||||
<UserAccountSubscriptionWrapper |
|
||||||
noMarginTop={noMarginTop} |
|
||||||
noMarginBottom={noMarginBottom} |
|
||||||
> |
|
||||||
<UserAccountTextLeftPart> |
|
||||||
<Fragment> |
|
||||||
<UserAccountDate> |
|
||||||
{format(new Date(matchData.date), 'dd.MM.yyyy')} |
|
||||||
</UserAccountDate> |
|
||||||
<UserAccountText> |
|
||||||
<Name nameObj={matchData.tournament} /> |
|
||||||
</UserAccountText> |
|
||||||
</Fragment> |
|
||||||
<UserAccountTeams> |
|
||||||
<Name nameObj={matchData.team1} /> - <Name nameObj={matchData.team2} /> |
|
||||||
</UserAccountTeams> |
|
||||||
</UserAccountTextLeftPart> |
|
||||||
{packageName |
|
||||||
&& <UserAccountBoldTextWrapper>{packageName}</UserAccountBoldTextWrapper>} |
|
||||||
{packageAction |
|
||||||
&& <UserAccountNormalTextWrapper>{packageAction}</UserAccountNormalTextWrapper>} |
|
||||||
<PriceWrapper> |
|
||||||
<Price amount={amount} /> |
|
||||||
</PriceWrapper> |
|
||||||
{deleteSubscription && ( |
|
||||||
<UserAccountDeleteButton type='button' onClick={deleteSubscription}> |
|
||||||
<T9n t='delete' /> |
|
||||||
</UserAccountDeleteButton> |
|
||||||
)} |
|
||||||
</UserAccountSubscriptionWrapper> |
|
||||||
) |
|
||||||
@ -1,117 +0,0 @@ |
|||||||
import styled, { css } from 'styled-components/macro' |
|
||||||
|
|
||||||
import { Label as CheckboxLabel } from 'features/Common/Checkbox/styled' |
|
||||||
import { Label as RadioLabel } from 'features/Common/Radio/styled' |
|
||||||
|
|
||||||
import { TextWrapper } from '../CardNumber/styled' |
|
||||||
|
|
||||||
type Props = { |
|
||||||
noMarginBottom?: boolean, |
|
||||||
noMarginTop?: boolean, |
|
||||||
} |
|
||||||
|
|
||||||
export const SubscriptionWrapperStyles = css<Props>` |
|
||||||
display: flex; |
|
||||||
align-items: center; |
|
||||||
justify-content: flex-start; |
|
||||||
height: 75px; |
|
||||||
background-color: #3F3F3F; |
|
||||||
border-top: ${({ noMarginBottom, noMarginTop }) => (noMarginBottom && noMarginTop ? '1px solid #000' : '')}; |
|
||||||
border-bottom: ${({ noMarginBottom, noMarginTop }) => (noMarginBottom && noMarginTop ? '1px solid #000' : '')}; |
|
||||||
border-radius: ${({ noMarginBottom, noMarginTop }) => { |
|
||||||
switch (true) { |
|
||||||
case noMarginTop && noMarginBottom: |
|
||||||
return '0' |
|
||||||
case noMarginTop: |
|
||||||
return '0 0 2px 2px' |
|
||||||
case noMarginBottom: |
|
||||||
return '2px 2px 0 0' |
|
||||||
default: |
|
||||||
return '2px' |
|
||||||
} |
|
||||||
}}; |
|
||||||
margin-top: ${({ noMarginTop }) => (noMarginTop ? '0' : '20px')}; |
|
||||||
margin-bottom: ${({ noMarginBottom }) => (noMarginBottom ? '0' : '20px')}; |
|
||||||
padding-left: 20px; |
|
||||||
width: 100%; |
|
||||||
${RadioLabel}::before { |
|
||||||
margin-left: 22px; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const UserAccountDeleteButton = styled.button` |
|
||||||
width: 80px; |
|
||||||
height: 100%; |
|
||||||
background: red; |
|
||||||
cursor: pointer; |
|
||||||
border: none; |
|
||||||
color: white; |
|
||||||
font-size: 15px; |
|
||||||
font-weight: 600; |
|
||||||
display: none; |
|
||||||
` |
|
||||||
export const UserAccountTextLeftPart = styled.div`` |
|
||||||
|
|
||||||
export const UserAccountSubscriptionWrapper = styled.div` |
|
||||||
${SubscriptionWrapperStyles}; |
|
||||||
&:hover { |
|
||||||
${UserAccountDeleteButton} { |
|
||||||
display: block; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
&:nth-child(n+1) { |
|
||||||
border-bottom: ${({ noMarginBottom }) => (noMarginBottom ? '1px solid #000' : '')}; |
|
||||||
border-top: ${({ noMarginBottom, noMarginTop }) => (noMarginBottom && noMarginTop ? 'none' : '')}; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const CheckboxWrapper = styled.div` |
|
||||||
${CheckboxLabel} { |
|
||||||
font-weight: bold; |
|
||||||
font-size: 16px; |
|
||||||
line-height: 24px; |
|
||||||
|
|
||||||
&::before { |
|
||||||
margin-left: 22px; |
|
||||||
} |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const UserAccountDate = styled.span` |
|
||||||
color: #fff; |
|
||||||
font-size: 17px; |
|
||||||
cursor: default; |
|
||||||
` |
|
||||||
export const UserAccountText = styled.span` |
|
||||||
color: #fff; |
|
||||||
font-size: 18px; |
|
||||||
cursor: default; |
|
||||||
font-weight: 800; |
|
||||||
margin-left: 20px; |
|
||||||
` |
|
||||||
|
|
||||||
export const UserAccountTeams = styled.p` |
|
||||||
color: #fff; |
|
||||||
font-size: 18px; |
|
||||||
cursor: default; |
|
||||||
margin-top: 15px; |
|
||||||
` |
|
||||||
|
|
||||||
export const UserAccountBoldTextWrapper = styled(TextWrapper)` |
|
||||||
color: #fff; |
|
||||||
font-weight: bold; |
|
||||||
font-size: 20px; |
|
||||||
margin-right: 24px; |
|
||||||
|
|
||||||
&:hover { |
|
||||||
cursor: default; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const UserAccountNormalTextWrapper = styled(TextWrapper)` |
|
||||||
color: #fff; |
|
||||||
font-weight: normal; |
|
||||||
font-size: 16px; |
|
||||||
margin-right: 24px; |
|
||||||
` |
|
||||||
@ -0,0 +1,68 @@ |
|||||||
|
import isEmpty from 'lodash/isEmpty' |
||||||
|
import map from 'lodash/map' |
||||||
|
|
||||||
|
import { SportTypes } from 'config' |
||||||
|
|
||||||
|
import type { MatchSubscriptions } from 'requests' |
||||||
|
|
||||||
|
import { InlineButton } from '../../styled' |
||||||
|
import { |
||||||
|
Wrapper, |
||||||
|
SportName, |
||||||
|
List, |
||||||
|
Item, |
||||||
|
Subscription, |
||||||
|
InfoWrapper, |
||||||
|
Header, |
||||||
|
Description, |
||||||
|
Price, |
||||||
|
SubscriptionEnd, |
||||||
|
ActionsWrapper, |
||||||
|
} from './styled' |
||||||
|
|
||||||
|
type Props = { |
||||||
|
list: MatchSubscriptions, |
||||||
|
sport: SportTypes, |
||||||
|
} |
||||||
|
|
||||||
|
export const UserSubscriptionsList = ({ list, sport }: Props) => { |
||||||
|
if (isEmpty(list)) return null |
||||||
|
return ( |
||||||
|
<Wrapper> |
||||||
|
<SportName sport={sport} /> |
||||||
|
<List> |
||||||
|
{ |
||||||
|
map(list, ({ |
||||||
|
description, |
||||||
|
header, |
||||||
|
price, |
||||||
|
subscription_id, |
||||||
|
type, |
||||||
|
}) => ( |
||||||
|
<Item key={subscription_id}> |
||||||
|
<Subscription> |
||||||
|
<InfoWrapper> |
||||||
|
<Header> |
||||||
|
{header} |
||||||
|
</Header> |
||||||
|
<Description> |
||||||
|
{description} |
||||||
|
</Description> |
||||||
|
</InfoWrapper> |
||||||
|
|
||||||
|
<ActionsWrapper> |
||||||
|
<Price amount={price} perPeriod={`per_${type}`} /> |
||||||
|
|
||||||
|
<InlineButton> |
||||||
|
Удалить |
||||||
|
</InlineButton> |
||||||
|
</ActionsWrapper> |
||||||
|
</Subscription> |
||||||
|
<SubscriptionEnd>Следующее списание 31.02.2020</SubscriptionEnd> |
||||||
|
</Item> |
||||||
|
)) |
||||||
|
} |
||||||
|
</List> |
||||||
|
</Wrapper> |
||||||
|
) |
||||||
|
} |
||||||
@ -0,0 +1,109 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import { SportName as SportNameBase } from 'features/Common/SportName' |
||||||
|
import { Price as BasePrice } from 'features/Price' |
||||||
|
import { PriceAmount, PriceDetails } from 'features/Price/styled' |
||||||
|
|
||||||
|
import { InlineButton } from '../../styled' |
||||||
|
|
||||||
|
export const Wrapper = styled.div` |
||||||
|
:not(:first-child) { |
||||||
|
margin-top: 24px; |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
export const SportName = styled(SportNameBase)` |
||||||
|
font-style: normal; |
||||||
|
font-weight: 500; |
||||||
|
font-size: 18px; |
||||||
|
line-height: 22px; |
||||||
|
color: #fff; |
||||||
|
` |
||||||
|
|
||||||
|
export const List = styled.ul` |
||||||
|
margin-top: 6px; |
||||||
|
` |
||||||
|
|
||||||
|
export const Item = styled.li` |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
` |
||||||
|
|
||||||
|
export const Price = styled(BasePrice)` |
||||||
|
margin-right: 20px; |
||||||
|
|
||||||
|
${PriceAmount} { |
||||||
|
font-size: 24px; |
||||||
|
line-height: 24px; |
||||||
|
font-weight: normal; |
||||||
|
} |
||||||
|
|
||||||
|
${PriceDetails} { |
||||||
|
font-weight: 500; |
||||||
|
font-size: 12px; |
||||||
|
line-height: 18px; |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
export const ActionsWrapper = styled.div` |
||||||
|
height: 100%; |
||||||
|
display: flex; |
||||||
|
justify-content: end; |
||||||
|
align-items: center; |
||||||
|
transform: translateX(83px); |
||||||
|
transition: transform 0.3s ease-in-out; |
||||||
|
|
||||||
|
${InlineButton} { |
||||||
|
transform: translateX(0); |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
export const Subscription = styled.div` |
||||||
|
width: 800px; |
||||||
|
height: 70px; |
||||||
|
display: flex; |
||||||
|
margin: 5px 0; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
background-color: #3F3F3F; |
||||||
|
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); |
||||||
|
border-radius: 2px; |
||||||
|
overflow: hidden; |
||||||
|
|
||||||
|
:hover ${ActionsWrapper} { |
||||||
|
transform: translateX(0); |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
export const InfoWrapper = styled.div` |
||||||
|
width: 68%; |
||||||
|
display: flex; |
||||||
|
padding: 14px 0 14px 20px; |
||||||
|
flex-direction: column; |
||||||
|
color: #fff; |
||||||
|
` |
||||||
|
|
||||||
|
export const Header = styled.span` |
||||||
|
font-style: normal; |
||||||
|
font-weight: 600; |
||||||
|
font-size: 16px; |
||||||
|
line-height: 23px; |
||||||
|
text-transform: uppercase; |
||||||
|
` |
||||||
|
|
||||||
|
export const Description = styled.p` |
||||||
|
font-style: normal; |
||||||
|
font-weight: 500; |
||||||
|
font-size: 16px; |
||||||
|
line-height: 20px; |
||||||
|
text-transform: capitalize; |
||||||
|
` |
||||||
|
|
||||||
|
export const SubscriptionEnd = styled.span` |
||||||
|
margin-left: 24px; |
||||||
|
font-style: normal; |
||||||
|
font-weight: 500; |
||||||
|
font-size: 16px; |
||||||
|
line-height: 24px; |
||||||
|
color: rgba(255, 255, 255, 0.3); |
||||||
|
` |
||||||
@ -1 +0,0 @@ |
|||||||
export * from './styled' |
|
||||||
@ -1,22 +0,0 @@ |
|||||||
import styled, { css } from 'styled-components/macro' |
|
||||||
|
|
||||||
import { devices } from 'config/devices' |
|
||||||
|
|
||||||
type Props = { |
|
||||||
visa?: boolean, |
|
||||||
} |
|
||||||
|
|
||||||
export const CardLogoStyles = css<Props>` |
|
||||||
width: ${({ visa }) => `${visa ? 37 : 30}px`}; |
|
||||||
height: ${({ visa }) => `${visa ? 12 : 19}px`}; |
|
||||||
margin-right: 82px; |
|
||||||
background: ${({ visa }) => `url(/images/${visa ? 'visaLogo.png' : 'masterLogo.png'}) no-repeat`}; |
|
||||||
|
|
||||||
@media ${devices.tablet} { |
|
||||||
margin-right: 5px; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const VisaLogoWrapper = styled.span<Props>` |
|
||||||
${CardLogoStyles} |
|
||||||
` |
|
||||||
@ -1,31 +0,0 @@ |
|||||||
import { |
|
||||||
useEffect, |
|
||||||
useState, |
|
||||||
} from 'react' |
|
||||||
|
|
||||||
import map from 'lodash/map' |
|
||||||
|
|
||||||
import type { SubscriptionType } from 'requests/getSubscriptions' |
|
||||||
import { getSubscriptions } from 'requests/getSubscriptions' |
|
||||||
|
|
||||||
import { useLexicsStore } from 'features/LexicsStore' |
|
||||||
|
|
||||||
export const useSubscriptions = () => { |
|
||||||
const [subscriptions, setSubscriptions] = useState<Array<SubscriptionType>>([]) |
|
||||||
|
|
||||||
const { addLexicsConfig } = useLexicsStore() |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
getSubscriptions().then((res) => { |
|
||||||
const lexicsArray = map(res, (subscription) => ( |
|
||||||
String(subscription.lexic) |
|
||||||
)) |
|
||||||
addLexicsConfig(lexicsArray) |
|
||||||
setSubscriptions(res) |
|
||||||
}) |
|
||||||
}, [addLexicsConfig]) |
|
||||||
|
|
||||||
return { |
|
||||||
subscriptions, |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,99 +0,0 @@ |
|||||||
import { |
|
||||||
useEffect, |
|
||||||
useState, |
|
||||||
} from 'react' |
|
||||||
|
|
||||||
import type { SportList } from 'requests/getSportList' |
|
||||||
import { |
|
||||||
SubscriptionAction, |
|
||||||
saveUserCustomSubscription, |
|
||||||
} from 'requests/saveUserCustomSubscription' |
|
||||||
import { getSportList } from 'requests/getSportList' |
|
||||||
import { getUserSubscriptions } from 'requests/getUserSubscriptions' |
|
||||||
import { saveUserSubscription } from 'requests/saveUserSubscription' |
|
||||||
|
|
||||||
import { useToggle } from 'hooks' |
|
||||||
|
|
||||||
export type Subscription = { |
|
||||||
id: number, |
|
||||||
name_eng: string, |
|
||||||
name_rus: string, |
|
||||||
type?: number, |
|
||||||
} |
|
||||||
|
|
||||||
type Name = { |
|
||||||
name_eng: string, |
|
||||||
name_rus: string, |
|
||||||
} |
|
||||||
|
|
||||||
export type Match = { |
|
||||||
date: Date, |
|
||||||
id: number, |
|
||||||
team1: Name, |
|
||||||
team2: Name, |
|
||||||
tournament: Name, |
|
||||||
} |
|
||||||
|
|
||||||
export type UserSubscriptions = { |
|
||||||
matches?: Array<Match>, |
|
||||||
sport: number, |
|
||||||
teams?: Array<Subscription>, |
|
||||||
tournaments?: Array<Subscription>, |
|
||||||
} |
|
||||||
|
|
||||||
export const useUserSubscriptions = () => { |
|
||||||
const [userSubscriptions, setUserSubscriptions] = useState<Array<UserSubscriptions>>([]) |
|
||||||
const [selectedSubscription, setSelectedSubscription] = useState<number | null>(null) |
|
||||||
const [selectedSubscriptionLexic, setSelectedSubscriptionLexic] = useState<string>('') |
|
||||||
const [sportList, setSportList] = useState<SportList>([]) |
|
||||||
|
|
||||||
const { |
|
||||||
close, |
|
||||||
isOpen, |
|
||||||
open, |
|
||||||
} = useToggle() |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
getUserSubscriptions().then((res) => { |
|
||||||
setUserSubscriptions(res.custom) |
|
||||||
setSelectedSubscription(res.id) |
|
||||||
setSelectedSubscriptionLexic(`${res.lexic}`) |
|
||||||
}) |
|
||||||
|
|
||||||
getSportList().then(setSportList) |
|
||||||
}, []) |
|
||||||
|
|
||||||
const saveSubscription = async () => { |
|
||||||
await saveUserSubscription(selectedSubscription) |
|
||||||
close() |
|
||||||
await getUserSubscriptions().then((res) => { |
|
||||||
setSelectedSubscription(res.id) |
|
||||||
setSelectedSubscriptionLexic(`${res.lexic}`) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
const deleteUserSubscription = async (subscription: Subscription, sport: number) => { |
|
||||||
await saveUserCustomSubscription({ |
|
||||||
action: SubscriptionAction.REMOVE, |
|
||||||
id: subscription.id, |
|
||||||
sport, |
|
||||||
type: subscription.type as number, |
|
||||||
}) |
|
||||||
await getUserSubscriptions().then((res) => { |
|
||||||
setUserSubscriptions(res.custom) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
return { |
|
||||||
close, |
|
||||||
deleteUserSubscription, |
|
||||||
isOpen, |
|
||||||
open, |
|
||||||
saveSubscription, |
|
||||||
selectedSubscription, |
|
||||||
selectedSubscriptionLexic, |
|
||||||
setSelectedSubscription, |
|
||||||
sportList, |
|
||||||
userSubscriptions, |
|
||||||
} |
|
||||||
} |
|
||||||
Loading…
Reference in new issue