Ott 496 get set delete subscriptions (#207)

* Ott 496 get set delete subscriptions 1 (#205)

* feat(ott-496): part of the code

* fix(ott-496): minor change in checkbo

* fix(ott-496): fixed get subscriptions types

* fix(ott-496): deleted unnecessary exports

* fix(ott-496): fixed types

* fix(ott-496): fixed types

* fix(ott-496): deleted fullwidth from click outside

* fix(ott-496): finish (#206)

* fix(ott-496): finish

* fix(ott-496): bug fix

* fix(ott-496): added switch

* fix(ott-496): bug fix according to Mirlan's comments

* fix(ott-496): finish
keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
Armen 5 years ago committed by GitHub
parent 26493b0c92
commit ee715e19e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      src/config/lexics/userAccount.tsx
  2. 1
      src/config/procedures.tsx
  3. 2
      src/features/Combobox/index.tsx
  4. 4
      src/features/Combobox/styled.tsx
  5. 10
      src/features/Common/Checkbox/index.tsx
  6. 1
      src/features/Common/Checkbox/styled.tsx
  7. 14
      src/features/Common/Radio/index.tsx
  8. 2
      src/features/Header/styled.tsx
  9. 4
      src/features/Login/index.tsx
  10. 3
      src/features/Login/styled.tsx
  11. 2
      src/features/MatchPage/MatchProfileCard/styled.tsx
  12. 6
      src/features/Modal/styled.tsx
  13. 8
      src/features/OutsideClick/index.tsx
  14. 5
      src/features/Register/components/CardStep/index.tsx
  15. 4
      src/features/Register/components/RegistrationStep/index.tsx
  16. 4
      src/features/Register/components/RegistrationSuccessful/index.tsx
  17. 2
      src/features/Register/components/SubscriptionsStep/styled.tsx
  18. 2
      src/features/UserAccount/components/CardNumber/index.tsx
  19. 2
      src/features/UserAccount/components/PageTitle/index.tsx
  20. 67
      src/features/UserAccount/components/Subscription/index.tsx
  21. 84
      src/features/UserAccount/components/Subscription/styled.tsx
  22. 98
      src/features/UserAccount/components/SubscriptionsForm/index.tsx
  23. 16
      src/features/UserAccount/components/SubscriptionsForm/styled.tsx
  24. 70
      src/features/UserAccount/components/SubscriptionsModal/index.tsx
  25. 46
      src/features/UserAccount/components/SubscriptionsModal/styled.tsx
  26. 4
      src/features/UserAccount/components/TextNoBorder/index.tsx
  27. 15
      src/features/UserAccount/components/UserAccountButton/index.tsx
  28. 29
      src/features/UserAccount/components/UserAccountSubscription/index.tsx
  29. 41
      src/features/UserAccount/components/UserAccountSubscription/styled.tsx
  30. 72
      src/features/UserAccount/components/UserAccountSubscriptionMatch/index.tsx
  31. 117
      src/features/UserAccount/components/UserAccountSubscriptionMatch/styled.tsx
  32. 31
      src/features/UserAccount/hooks/useSubscriptions.tsx
  33. 92
      src/features/UserAccount/hooks/useUserSubscriptions.tsx
  34. 88
      src/features/UserAccount/index.tsx
  35. 50
      src/features/UserAccount/styled.tsx
  36. 34
      src/requests/getSubscriptions.tsx
  37. 33
      src/requests/saveUserCustomSubscription.tsx
  38. 10
      src/requests/saveUserSubscription.tsx

@ -4,6 +4,7 @@ export const userAccountLexics = {
add_card: 8313,
change: 12614,
country: 835,
delete: 848,
delete_card: 8692,
lastname: 858,
mail: 12912,

@ -8,6 +8,7 @@ export const PROCEDURES = {
get_player_matches: 'get_player_matches',
get_players_teams_tournaments: 'get_players_teams_tournaments',
get_sport_list: 'get_sport_list',
get_subscriptions: 'get_subscriptions',
get_team_info: 'get_team_info',
get_team_matches: 'get_team_matches',
get_tournament_info: 'get_tournament_info',

@ -80,7 +80,7 @@ export const Combobox = <T extends Option>(props: Props<T>) => {
/>
)}
{isOpen && !isEmpty(options) && (
<OutsideClick fullWidth onClick={onOutsideClick}>
<OutsideClick onClick={onOutsideClick}>
<PopOver
ref={popoverRef}
>

@ -17,8 +17,8 @@ export const PopOver = styled.ul`
overflow: auto;
z-index: 2;
background: rgb(102, 102, 102);
${customScrollbar}
${customStylesMixin}
${customScrollbar};
${customStylesMixin};
`
export const ListOption = styled.li<{isHighlighted?: boolean}>`

@ -10,8 +10,7 @@ type Props = Pick<InputHTMLAttributes<HTMLInputElement>, (
| 'checked'
| 'id'
| 'name'
| 'value'
| 'onChange'
| 'onClick'
)> & {
label?: string,
}
@ -21,16 +20,15 @@ export const Checkbox = ({
id,
label,
name,
onChange,
value,
onClick,
}: Props) => (
<Wrapper>
<Input
id={id}
type='checkbox'
name={name}
value={value}
checked={checked}
onChange={onChange}
onClick={onClick}
/>
<Label htmlFor={id}>{label}</Label>
</Wrapper>

@ -13,6 +13,7 @@ export const Wrapper = styled.div`
`
export const Label = styled.label`
display: flex;
color: ${({ theme: { colors } }) => colors.text};
font-style: normal;
font-weight: bold;

@ -10,8 +10,7 @@ type Props = Pick<InputHTMLAttributes<HTMLInputElement>, (
| 'checked'
| 'id'
| 'name'
| 'value'
| 'onChange'
| 'onClick'
)> & {
label?: string,
}
@ -21,17 +20,18 @@ export const Radio = ({
id,
label = '',
name,
onChange,
value,
onClick,
}: Props) => (
<Wrapper>
<Input
id={id}
type='radio'
name={name}
value={value}
checked={checked}
onChange={onChange}
onClick={onClick}
/>
<Label htmlFor={id}>{label}</Label>
<Label htmlFor={id}>
{label}
</Label>
</Wrapper>
)

@ -10,7 +10,7 @@ export const HomeButtonLink = styled(Link)`
background-repeat: no-repeat;
background-position: center;
&:hover{
&:hover {
background-image: url('/images/home-btn-hover.svg');
cursor:pointer;
}

@ -35,9 +35,7 @@ const LoginForm = () => {
<CenterBlock>
<Logo />
<Form onSubmit={handleSubmit}>
<BlockTitle>
<T9n t='step_title_login' />
</BlockTitle>
<BlockTitle t='step_title_login' />
<Input
type='email'

@ -4,6 +4,7 @@ import styled from 'styled-components/macro'
import { devices } from 'config/devices'
import { outlineButtonStyles } from 'features/Common'
import { T9n } from 'features/T9n'
export const CenterBlock = styled.div`
display: flex;
@ -40,7 +41,7 @@ export const Form = styled.form<{forRegPage?: boolean}>`
}
`
export const BlockTitle = styled.span`
export const BlockTitle = styled(T9n)`
display: block;
font-style: normal;
font-weight: bold;

@ -27,7 +27,7 @@ export const Teams = styled.div`
export const StyledLink = styled(ProfileLink)`
font-weight: bold;
color: white;
&:hover{
&:hover {
text-decoration: underline;
}
`

@ -16,7 +16,7 @@ export const ModalContainer = styled.div`
font-weight: 600;
`
export const ModalWindow = styled.div`
background: #3F3F3F;
background-color: #313131;
position: relative;
padding: 15px;
box-shadow: 0px 5px 30px rgba(0, 0, 0, 0.7);
@ -26,7 +26,7 @@ export const ModalWindow = styled.div`
export const ModalCloseButton = styled(CloseButton)`
margin-right: 19px;
margin-top: 16px;
width: 12.82px;
height: 12.82px;
width: 16px;
height: 16px;
cursor: pointer;
`

@ -8,23 +8,19 @@ import { useOutsideClickEffect } from './hooks'
type Props = {
/** элемент, которому необходим функционал `OutsideClick` */
children: ReactNode,
fullWidth?: boolean,
/** функция-коллбек, отрабатывающая по клику вне области элемента */
onClick: (event: MouseEvent) => void,
}
const OutsideClickWrapper = styled.div<{fullWidth: boolean}>`
width: ${({ fullWidth }) => (fullWidth ? '100%' : '')};
`
const OutsideClickWrapper = styled.div``
export const OutsideClick = ({
children,
fullWidth = false,
onClick,
}: Props) => {
const wrapperRef = useOutsideClickEffect({ onClick })
return (
<OutsideClickWrapper fullWidth={fullWidth} ref={wrapperRef}>
<OutsideClickWrapper ref={wrapperRef}>
{children}
</OutsideClickWrapper>
)

@ -16,10 +16,7 @@ export const CardStep = () => {
const defaultMessage = translate('please_fill_out_this_field')
return (
<Form>
<BlockTitle>
<T9n t='step_title_card' />
</BlockTitle>
<BlockTitle t='step_title_card' />
<Card>
<Input
labelLexic='form_card_number'

@ -27,9 +27,7 @@ const Registration = () => {
return (
<Form onSubmit={handleSubmit} forRegPage>
<BlockTitle>
<T9n t='step_title_registration' />
</BlockTitle>
<BlockTitle t='step_title_registration' />
<Input
value={readFormValue(formIds.email)}
error={readFormError(formIds.email)}

@ -13,9 +13,7 @@ import {
export const RegistrationSuccessful = () => (
<Container>
<BlockTitle>
<T9n t='registration_successful' />
</BlockTitle>
<BlockTitle t='registration_successful' />
<GreenTick />
<ButtonLink to={PAGES.login}>
<T9n t='login' />

@ -41,8 +41,6 @@ export const SubscriptionsBlock = styled.div<SubscriptionsBlockProps>`
return '80px'
}};
}
`
export const BlockTitle = styled.span`

@ -21,7 +21,7 @@ export const CardNumber = ({
<Radio
label={label}
checked={checked}
onChange={() => {}}
onClick={() => {}}
/>
<VisaLogoWrapper visa={visa} />
<CardNumberTextWrapper>

@ -20,7 +20,7 @@ export const PageTitle = ({ titleText }: Props) => {
<Logo />
</Link>
<TitleTextWrapper>
<BlockTitle>{titleText}</BlockTitle>
<BlockTitle t={titleText} />
</TitleTextWrapper>
</PageTitleWrapper>
)

@ -0,0 +1,67 @@
import React from 'react'
import { Price } from 'features/Register/components/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>
)

@ -0,0 +1,84 @@
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,98 @@
import React, { 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}
inputType='radio'
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>
)
}

@ -0,0 +1,16 @@
import styled from 'styled-components/macro'
import { BlockTitle } from 'features/Login/styled'
import { T9n } from 'features/T9n'
export const UserAccountBlockTitle = styled(BlockTitle)`
align-self: flex-start;
`
export const SubscriptionTitle = styled(T9n)`
color: white;
font-weight: 500;
font-size: 25px;
align-self: flex-start;
margin-top: 40px;
`

@ -0,0 +1,70 @@
import React from 'react'
import map from 'lodash/map'
import type { SubscriptionType } from 'requests/getSubscriptions'
import { Modal } from 'features/Modal'
import { useLexicsStore } from 'features/LexicsStore'
import { Subscription } from '../Subscription'
import {
AddSubscriptionModal,
Line,
ModalTitle,
SubscriptionsWrapper,
SaveButton,
} from './styled'
type Props = {
close: () => void,
isOpen: boolean,
saveSubscription: () => void,
selectedSubscription: number | null,
setSelectedSubscription: (arg: number | null) => void,
subscriptions: Array<SubscriptionType>,
}
export const SubscriptionModal = ({
close,
isOpen,
saveSubscription,
selectedSubscription,
setSelectedSubscription,
subscriptions,
}: Props) => {
const { translate } = useLexicsStore()
return (
<Modal
isOpen={isOpen}
close={close}
>
<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>
)
}

@ -0,0 +1,46 @@
import styled from 'styled-components/macro'
import { customScrollbar, customStylesMixin } from 'features/Common'
import { T9n } from 'features/T9n'
import { OutlinedButton } from '../../styled'
export const AddSubscriptionModal = styled.div`
width: 538px;
height: 452px;
display: flex;
flex-direction: column;
align-items: center;
`
export const ModalTitle = styled(T9n)`
display: block;
font-size: 24px;
font-weight: normal;
`
export const Line = styled.hr`
position:absolute;
width: 100%;
top: 40px;
height: 1px;
border: 1px solid #3F3F3F;
`
export const SaveButton = styled(OutlinedButton)`
width: 192px;
height: 36px;
display: block;
font-weight: normal;
margin-left: auto;
margin-top: auto;
`
export const SubscriptionsWrapper = styled.div`
margin-top: 45px;
width: 100%;
height: 100%;
overflow: auto;
${customScrollbar};
${customStylesMixin};
`

@ -15,7 +15,9 @@ export const TextNoBorder = ({
text,
}: Props) => (
<TextNoBorderWrapper>
<TextNoBorderTextWrapper>{text}</TextNoBorderTextWrapper>
<TextNoBorderTextWrapper>
{text}
</TextNoBorderTextWrapper>
<PriceWrapper>
<Price amount={amount} />
</PriceWrapper>

@ -1,11 +1,20 @@
import React from 'react'
import { T9n } from 'features/T9n'
import { PlusIconWrapper } from '../PlusIcon'
import { UserAccountButtonWrapper, PlusIconTextWrapper } from './styled'
export const UserAccountButton = ({ text }: { text: string }) => (
<UserAccountButtonWrapper>
type Props = {
open?: () => void,
text: string,
}
export const UserAccountButton = ({ open, text }: Props) => (
<UserAccountButtonWrapper onClick={open}>
<PlusIconWrapper />
<PlusIconTextWrapper>{text}</PlusIconTextWrapper>
<PlusIconTextWrapper>
<T9n t={text} />
</PlusIconTextWrapper>
</UserAccountButtonWrapper>
)

@ -1,20 +1,25 @@
import React from 'react'
import { T9n } from 'features/T9n'
import type { ObjectWithName } from 'features/Name'
import { Name } from 'features/Name'
import { Price } from 'features/Register/components/Price'
import {
UserAccountSubscriptionWrapper,
UserAccountBoldTextWrapper,
UserAccountNormalTextWrapper,
Text,
UserAccountText,
UserAccountDeleteButton,
} from './styled'
import { PriceWrapper } from '../CardNumber/styled'
type Props = {
amount: number,
checked?: boolean,
deleteSubscription?: () => void,
inputType?: string,
label?: string,
label?: ObjectWithName,
noMarginBottom?: boolean,
noMarginTop?: boolean,
packageAction?: string,
@ -23,6 +28,7 @@ type Props = {
export const UserAccountSubscription = ({
amount,
deleteSubscription,
label,
noMarginBottom,
noMarginTop,
@ -33,11 +39,24 @@ export const UserAccountSubscription = ({
noMarginTop={noMarginTop}
noMarginBottom={noMarginBottom}
>
<Text>{label}</Text>
{packageName && <UserAccountBoldTextWrapper>{packageName}</UserAccountBoldTextWrapper>}
{packageAction && <UserAccountNormalTextWrapper>{packageAction}</UserAccountNormalTextWrapper>}
<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>
)

@ -10,7 +10,7 @@ type Props = {
noMarginTop?: boolean,
}
export const UserAccountSubscriptionWrapperStyles = css<Props>`
export const SubscriptionWrapperStyles = css<Props>`
display: flex;
align-items: center;
justify-content: flex-start;
@ -19,16 +19,16 @@ export const UserAccountSubscriptionWrapperStyles = css<Props>`
border-top: ${({ noMarginBottom, noMarginTop }) => (noMarginBottom && noMarginTop ? '1px solid #000' : '')};
border-bottom: ${({ noMarginBottom, noMarginTop }) => (noMarginBottom && noMarginTop ? '1px solid #000' : '')};
border-radius: ${({ noMarginBottom, noMarginTop }) => {
if (noMarginTop && noMarginBottom) {
return '0'
switch (true) {
case noMarginTop && noMarginBottom:
return '0'
case noMarginTop:
return '0 0 2px 2px'
case noMarginBottom:
return '2px 2px 0 0'
default:
return '2px'
}
if (noMarginTop) {
return '0 0 2px 2px'
}
if (noMarginBottom) {
return '2px 2px 0 0'
}
return '2px'
}};
margin-top: ${({ noMarginTop }) => (noMarginTop ? '0' : '20px')};
margin-bottom: ${({ noMarginBottom }) => (noMarginBottom ? '0' : '20px')};
@ -39,8 +39,25 @@ export const UserAccountSubscriptionWrapperStyles = css<Props>`
}
`
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`
${UserAccountSubscriptionWrapperStyles};
${SubscriptionWrapperStyles};
&:hover {
${UserAccountDeleteButton} {
display: block;
}
}
&:nth-child(n+1) {
border-bottom: ${({ noMarginBottom }) => (noMarginBottom ? '1px solid #000' : '')};
@ -60,7 +77,7 @@ export const CheckboxWrapper = styled.div`
}
`
export const Text = styled.p`
export const UserAccountText = styled.p`
color: #fff;
font-size: 18px;
cursor: default;

@ -0,0 +1,72 @@
import React, { 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/Register/components/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,
inputType?: string,
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>
)

@ -0,0 +1,117 @@
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,31 @@
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,41 +1,99 @@
import {
useEffect,
useState,
useCallback,
} from 'react'
import map from 'lodash/map'
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 { useLexicsStore } from 'features/LexicsStore'
import { useToggle } from 'hooks'
export type Team = {
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 [subscriptions, setSubscriptions] = useState<Array<Team>>([])
const { suffix } = useLexicsStore()
const [userSubscriptions, setUserSubscriptions] = useState<Array<UserSubscriptions>>([])
const [selectedSubscription, setSelectedSubscription] = useState<number | null>(null)
const [selectedSubscriptionLexic, setSelectedSubscriptionLexic] = useState<string>('')
const [sportList, setSportList] = useState<SportList>([])
type Names = 'name_eng' | 'name_rus'
const {
close,
isOpen,
open,
} = useToggle()
useEffect(() => {
getUserSubscriptions().then((res) => {
setSubscriptions(res.custom?.[0].teams)
setUserSubscriptions(res.custom)
setSelectedSubscription(res.id)
setSelectedSubscriptionLexic(`${res.lexic}`)
})
getSportList().then(setSportList)
}, [])
const normalizeSubscriptions = useCallback(() => {
const nameKey = `name_${suffix}` as Names
const saveSubscription = async () => {
await saveUserSubscription(selectedSubscription)
close()
await getUserSubscriptions().then((res) => {
setSelectedSubscription(res.id)
setSelectedSubscriptionLexic(`${res.lexic}`)
})
}
return map(subscriptions, (team) => ({
...team,
name: team[nameKey],
}))
}, [subscriptions, suffix])
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 normalizeSubscriptions()
return {
close,
deleteUserSubscription,
isOpen,
open,
saveSubscription,
selectedSubscription,
selectedSubscriptionLexic,
setSelectedSubscription,
sportList,
userSubscriptions,
}
}

@ -1,7 +1,5 @@
import React from 'react'
import map from 'lodash/map'
import { userAccountLexics } from 'config/lexics/userAccount'
import { formIds } from 'config/form'
@ -10,24 +8,26 @@ import { Input } from 'features/Common'
import { Form } from 'features/Login/styled'
import { T9n } from 'features/T9n'
import { Error } from 'features/Common/Input/styled'
import { useLexicsStore, useLexicsConfig } from 'features/LexicsStore'
import { useLexicsConfig } from 'features/LexicsStore'
import { useUserInfo } from './hooks/useUserInfo'
import { useUserSubscriptions } from './hooks/useUserSubscriptions'
import { useSubscriptions } from './hooks/useSubscriptions'
import { CardNumber } from './components/CardNumber'
import { UserAccountButton } from './components/UserAccountButton'
import { PageTitle } from './components/PageTitle'
import { UserAccountSubscription } from './components/UserAccountSubscription'
import { TextNoBorder } from './components/TextNoBorder'
import { useUserInfo } from './hooks/useUserInfo'
import { useUserSubscriptions } from './hooks/useUserSubscriptions'
import { SubscriptionModal } from './components/SubscriptionsModal'
import { SubscriptionsForm } from './components/SubscriptionsForm'
import {
FormWrapper,
OutlinedButton,
UserAccountWrapper,
UserAccountFormWrapper,
UserAccountBlockTitle,
UserAccountComponentWrapper,
ButtonWrapper,
UserAccountBlockTitle,
} from './styled'
const labelWidth = 110
@ -35,8 +35,6 @@ const labelWidth = 110
export const UserAccount = () => {
useLexicsConfig(userAccountLexics)
const { translate } = useLexicsStore()
const {
cities,
countries,
@ -51,18 +49,31 @@ export const UserAccount = () => {
updateFormValue,
} = useUserInfo()
const subscriptions = useUserSubscriptions()
const {
close,
deleteUserSubscription,
isOpen,
open,
saveSubscription,
selectedSubscription,
selectedSubscriptionLexic,
setSelectedSubscription,
sportList,
userSubscriptions,
} = useUserSubscriptions()
const {
subscriptions,
} = useSubscriptions()
return (
<UserAccountComponentWrapper>
<UserAccountWrapper>
<PageTitle titleText={translate('user_account')} />
<PageTitle titleText='user_account' />
<UserAccountFormWrapper>
<FormWrapper>
<Form>
<UserAccountBlockTitle>
<T9n t='main' />
</UserAccountBlockTitle>
<UserAccountBlockTitle t='main' />
<Input
value={readFormValue(formIds.firstname)}
labelLexic='name'
@ -169,45 +180,38 @@ export const UserAccount = () => {
</FormWrapper>
<FormWrapper>
<Form>
<UserAccountBlockTitle>
<T9n t='payment' />
</UserAccountBlockTitle>
<UserAccountBlockTitle t='payment' />
<CardNumber visa label='1234 1234 1234 1234' />
<CardNumber checked label='1234 1234 1234 1234' />
<CardNumber label='1234 1234 1234 1234' />
<UserAccountButton text={translate('add_card')} />
<UserAccountButton text='add_card' />
</Form>
</FormWrapper>
<FormWrapper>
<Form>
<UserAccountBlockTitle>
<T9n t='subscriptions' />
</UserAccountBlockTitle>
<UserAccountSubscription
amount={1999}
inputType='radio'
packageName='Базовая'
// packageAction={translate('add_card')}
// Ещё не решили что делать с add card
/>
{map(subscriptions, (subscription) => (
<UserAccountSubscription
key={subscription.id}
noMarginBottom
amount={1999}
inputType='checkbox'
label={subscription.name}
/>
))}
<UserAccountButton text={translate('select_subscription')} />
<TextNoBorder
text={`${translate('next_debit')} 31.02.2020`}
amount={4796}
<SubscriptionsForm
selectedSubscriptionLexic={selectedSubscriptionLexic}
userSubscriptions={userSubscriptions}
sportList={sportList}
deleteUserSubscription={deleteUserSubscription}
open={open}
selectedSubscription={selectedSubscription}
/>
</Form>
</FormWrapper>
</UserAccountFormWrapper>
</UserAccountWrapper>
{/* Select subscription modal */}
<SubscriptionModal
close={close}
isOpen={isOpen}
saveSubscription={saveSubscription}
selectedSubscription={selectedSubscription}
setSelectedSubscription={setSelectedSubscription}
subscriptions={subscriptions}
/>
</UserAccountComponentWrapper>
)
}

@ -1,7 +1,8 @@
import styled from 'styled-components/macro'
import { BlockTitle, Form } from 'features/Login/styled'
import { Form, BlockTitle } from 'features/Login/styled'
import { outlineButtonStyles } from 'features/Common/Button'
import { customScrollbar, customStylesMixin } from 'features/Common'
export const OutlinedButton = styled.button`
${outlineButtonStyles};
@ -18,6 +19,10 @@ export const OutlinedButton = styled.button`
}
`
export const UserAccountBlockTitle = styled(BlockTitle)`
align-self: flex-start;
`
export const UserAccountFormWrapper = styled.div`
display: flex;
justify-content: center;
@ -36,10 +41,6 @@ export const UserAccountWrapper = styled.div`
margin-top: 140px;
`
export const UserAccountBlockTitle = styled(BlockTitle)`
align-self: flex-start;
`
export const UserAccountComponentWrapper = styled.div``
export const FormWrapper = styled.div`
@ -53,3 +54,42 @@ export const FormWrapper = styled.div`
margin-right: 0;
}
`
export const AddSubscriptionModal = styled.div`
width: 538px;
height: 452px;
display: flex;
flex-direction: column;
align-items: center;
`
export const ModalTitle = styled.p`
font-size: 24px;
font-weight: normal;
`
export const Line = styled.hr`
position:absolute;
width: 100%;
top: 40px;
height: 1px;
border: 1px solid #3F3F3F;
`
export const SaveButton = styled(OutlinedButton)`
width: 192px;
height: 36px;
display: block;
font-weight: normal;
margin-left: auto;
margin-top: auto;
`
export const SubscriptionsWrapper = styled.div`
margin-top: 45px;
width: 100%;
height: 100%;
overflow: auto;
${customScrollbar}
${customStylesMixin}
`

@ -0,0 +1,34 @@
import {
DATA_URL,
PROCEDURES,
} from 'config'
import { callApi } from 'helpers'
const proc = PROCEDURES.get_subscriptions
type Tournament = {
id: number,
name_eng: string,
name_rus: string,
sport: number,
}
export type SubscriptionType = {
id: number,
lexic: number,
tournaments: Array<Tournament>,
}
export const getSubscriptions = (): Promise<Array<SubscriptionType>> => {
const config = {
body: {
params: {},
proc,
},
}
return callApi({
config,
url: DATA_URL,
})
}

@ -1,31 +1,48 @@
import {
DATA_URL,
PROCEDURES,
ProfileTypes,
SportTypes,
} from 'config'
import { callApi } from 'helpers'
const proc = PROCEDURES.save_user_custom_subscription
export enum SubscriptionAction {
ADD = 1,
REMOVE = 2,
}
type Response = {
_p_error: string | null,
_p_status: 1 | 2,
}
type Args = {
action: SubscriptionAction,
id: number,
sport: SportTypes,
type: ProfileTypes,
}
const responseStatus = {
FAILURE: 2,
SUCCESS: 1,
}
export const saveUserCustomSubscription = async () => {
export const saveUserCustomSubscription = async ({
action,
id,
sport,
type,
} : Args) => {
const config = {
body: {
params: {
_p_action: 1,
_p_id: 1,
_p_sport: 1,
_p_status: 1,
_p_type: 1,
_p_user_id: 1,
_p_action: action,
_p_id: id,
_p_sport: sport,
_p_type: type,
},
proc,
},
@ -37,7 +54,7 @@ export const saveUserCustomSubscription = async () => {
})
if (response._p_status === responseStatus.SUCCESS) {
return Promise.resolve(response)
return Promise.resolve()
}
return Promise.reject(response._p_error)
}

@ -6,10 +6,6 @@ import { callApi } from 'helpers'
const proc = PROCEDURES.save_user_subscription
type Type = {
subscriptionId: number,
}
type Response = {
_p_error: string | null,
_p_status: 1 | 2,
@ -20,11 +16,11 @@ const responseStatus = {
SUCCESS: 1,
}
export const saveUserSubscription = async ({ subscriptionId }: Type) => {
export const saveUserSubscription = async (subscriptionId : number | null) => {
const config = {
body: {
params: {
p_subscription_id: subscriptionId,
_p_subscription_id: subscriptionId,
},
proc,
},
@ -36,7 +32,7 @@ export const saveUserSubscription = async ({ subscriptionId }: Type) => {
})
if (response._p_status === responseStatus.SUCCESS) {
return Promise.resolve(response)
return Promise.resolve()
}
return Promise.reject(response._p_error)
}

Loading…
Cancel
Save