Merge pull request #10 from instat/OTT-37-registration-layout
commit
09568e1b65
@ -1,3 +1,4 @@ |
|||||||
export const PAGES = { |
export const PAGES = { |
||||||
login: '/login', |
login: '/login', |
||||||
|
register: '/register', |
||||||
} |
} |
||||||
|
|||||||
@ -1,12 +1,36 @@ |
|||||||
import React from 'react' |
import React from 'react' |
||||||
|
import { |
||||||
|
Router, |
||||||
|
Route, |
||||||
|
Redirect, |
||||||
|
Switch, |
||||||
|
} from 'react-router-dom' |
||||||
|
import { createBrowserHistory } from 'history' |
||||||
|
|
||||||
|
import { PAGES } from 'config' |
||||||
|
import { GlobalStyles } from 'features/GlobalStyles' |
||||||
import { Theme } from 'features/Theme' |
import { Theme } from 'features/Theme' |
||||||
import { Login } from 'features/Login' |
import { Login } from 'features/Login' |
||||||
import { GlobalStyles } from 'features/GlobalStyles' |
import { Register } from 'features/Register' |
||||||
|
|
||||||
|
const history = createBrowserHistory() |
||||||
|
|
||||||
export const App = () => ( |
export const App = () => ( |
||||||
<Theme> |
<Router history={history}> |
||||||
<GlobalStyles /> |
<Theme> |
||||||
<Login /> |
<GlobalStyles /> |
||||||
</Theme> |
|
||||||
|
<Switch> |
||||||
|
<Route path={PAGES.login}> |
||||||
|
<Login /> |
||||||
|
</Route> |
||||||
|
|
||||||
|
<Route path={PAGES.register}> |
||||||
|
<Register /> |
||||||
|
</Route> |
||||||
|
|
||||||
|
<Redirect to={PAGES.login} /> |
||||||
|
</Switch> |
||||||
|
</Theme> |
||||||
|
</Router> |
||||||
) |
) |
||||||
|
|||||||
@ -0,0 +1,27 @@ |
|||||||
|
import React from 'react' |
||||||
|
|
||||||
|
import { Checkbox } from 'features/Common' |
||||||
|
|
||||||
|
import { Price } from '../Price' |
||||||
|
import { |
||||||
|
PriceItemTitle, |
||||||
|
PriceItem, |
||||||
|
PriceItemCol, |
||||||
|
} from './styled' |
||||||
|
|
||||||
|
type TAdditionalSubscription = { |
||||||
|
price: number, |
||||||
|
title: string, |
||||||
|
} |
||||||
|
|
||||||
|
export const AdditionalSubscription = ({ price, title }: TAdditionalSubscription) => ( |
||||||
|
<PriceItem> |
||||||
|
<PriceItemCol> |
||||||
|
<Checkbox name='additionalSubscription' id={title} /> |
||||||
|
</PriceItemCol> |
||||||
|
<PriceItemCol> |
||||||
|
<PriceItemTitle>{title}</PriceItemTitle> |
||||||
|
<Price amount={price} /> |
||||||
|
</PriceItemCol> |
||||||
|
</PriceItem> |
||||||
|
) |
||||||
@ -0,0 +1,29 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
export const PriceItem = styled.div` |
||||||
|
position: relative; |
||||||
|
width: 288px; |
||||||
|
height: 176px; |
||||||
|
padding: 24px 25px 40px; |
||||||
|
margin: 0; |
||||||
|
display: flex; |
||||||
|
flex-direction: row; |
||||||
|
background: #3F3F3F; |
||||||
|
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.4); |
||||||
|
border-radius: 2px; |
||||||
|
` |
||||||
|
|
||||||
|
export const PriceItemTitle = styled.span` |
||||||
|
font-style: normal; |
||||||
|
font-weight: bold; |
||||||
|
font-size: 18px; |
||||||
|
line-height: 24px; |
||||||
|
color: ${({ theme: { colors } }) => colors.text}; |
||||||
|
margin: 3px 5px 0 0; |
||||||
|
` |
||||||
|
|
||||||
|
export const PriceItemCol = styled.div` |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: space-between; |
||||||
|
` |
||||||
@ -0,0 +1,27 @@ |
|||||||
|
import React from 'react' |
||||||
|
|
||||||
|
import { Radio } from 'features/Common' |
||||||
|
|
||||||
|
import { Price } from '../Price' |
||||||
|
import { |
||||||
|
SubscriptionWrapper, |
||||||
|
SubscriptionTitle, |
||||||
|
Row, |
||||||
|
} from '../Steps/Subscriptions/styled' |
||||||
|
|
||||||
|
type TMainSubscription = { |
||||||
|
price: number, |
||||||
|
title: string, |
||||||
|
} |
||||||
|
|
||||||
|
export const MainSubscription = ({ price, title }: TMainSubscription) => ( |
||||||
|
<SubscriptionWrapper> |
||||||
|
<Row> |
||||||
|
<Radio name='mainSubscription' id={title} /> |
||||||
|
<SubscriptionTitle>{title}</SubscriptionTitle> |
||||||
|
</Row> |
||||||
|
<Row left={70} bottom={100}> |
||||||
|
<Price amount={price} /> |
||||||
|
</Row> |
||||||
|
</SubscriptionWrapper> |
||||||
|
) |
||||||
@ -0,0 +1,24 @@ |
|||||||
|
import React from 'react' |
||||||
|
|
||||||
|
import { |
||||||
|
PriceWrapper, |
||||||
|
PriceAmount, |
||||||
|
PriceDetails, |
||||||
|
} from './styled' |
||||||
|
|
||||||
|
type TPrice = { |
||||||
|
amount: number, |
||||||
|
currency?: string, |
||||||
|
perPeriod?: string, |
||||||
|
} |
||||||
|
|
||||||
|
export const Price = ({ |
||||||
|
amount, |
||||||
|
currency = '₽', |
||||||
|
perPeriod = 'мес', |
||||||
|
}: TPrice) => ( |
||||||
|
<PriceWrapper> |
||||||
|
<PriceAmount>{amount}</PriceAmount> |
||||||
|
<PriceDetails>{currency} / {perPeriod}</PriceDetails> |
||||||
|
</PriceWrapper> |
||||||
|
) |
||||||
@ -0,0 +1,24 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
export const PriceWrapper = styled.div` |
||||||
|
display: flex; |
||||||
|
align-items: flex-start; |
||||||
|
` |
||||||
|
|
||||||
|
export const PriceAmount = styled.span` |
||||||
|
font-style: normal; |
||||||
|
font-weight: 600; |
||||||
|
font-size: 48px; |
||||||
|
line-height: 40px; |
||||||
|
color: ${({ theme: { colors } }) => colors.text}; |
||||||
|
` |
||||||
|
|
||||||
|
export const PriceDetails = styled.span` |
||||||
|
margin-left: 5px; |
||||||
|
font-style: normal; |
||||||
|
font-weight: normal; |
||||||
|
font-size: 18px; |
||||||
|
line-height: 21px; |
||||||
|
color: ${({ theme: { colors } }) => colors.text}; |
||||||
|
text-transform: uppercase; |
||||||
|
` |
||||||
@ -0,0 +1,48 @@ |
|||||||
|
import React from 'react' |
||||||
|
|
||||||
|
import { Input } from 'features/Common' |
||||||
|
import { |
||||||
|
BlockTitle, |
||||||
|
ButtonsBlock, |
||||||
|
Form, |
||||||
|
} from 'features/Login/styled' |
||||||
|
|
||||||
|
import { |
||||||
|
NextButton, |
||||||
|
Card, |
||||||
|
Row, |
||||||
|
} from '../../styled' |
||||||
|
|
||||||
|
export const CardStep = () => ( |
||||||
|
<Form> |
||||||
|
<BlockTitle>Привязка карты</BlockTitle> |
||||||
|
|
||||||
|
<Card> |
||||||
|
<Input |
||||||
|
id='cardNumber' |
||||||
|
label='Номер карты' |
||||||
|
paddingX={21} |
||||||
|
/> |
||||||
|
<Row> |
||||||
|
<Input |
||||||
|
id='expiration' |
||||||
|
label='Срок действия' |
||||||
|
wrapperWidth={280} |
||||||
|
inputWidth={85} |
||||||
|
paddingX={21} |
||||||
|
/> |
||||||
|
<Input |
||||||
|
id='code' |
||||||
|
label='CVC / CVV' |
||||||
|
wrapperWidth={184} |
||||||
|
inputWidth={30} |
||||||
|
maxLength={3} |
||||||
|
paddingX={18.6} |
||||||
|
/> |
||||||
|
</Row> |
||||||
|
</Card> |
||||||
|
<ButtonsBlock> |
||||||
|
<NextButton to='subscriptions'>Далее</NextButton> |
||||||
|
</ButtonsBlock> |
||||||
|
</Form> |
||||||
|
) |
||||||
@ -0,0 +1,57 @@ |
|||||||
|
import React from 'react' |
||||||
|
|
||||||
|
import { PAGES } from 'config' |
||||||
|
|
||||||
|
import { Input } from 'features/Common' |
||||||
|
import { |
||||||
|
BlockTitle, |
||||||
|
ButtonsBlock, |
||||||
|
Form, |
||||||
|
} from 'features/Login/styled' |
||||||
|
|
||||||
|
import { NextButton } from '../../styled' |
||||||
|
|
||||||
|
const labelWidth = 78 |
||||||
|
|
||||||
|
export const Registration = () => ( |
||||||
|
<Form> |
||||||
|
<BlockTitle>Регистрация</BlockTitle> |
||||||
|
|
||||||
|
<Input |
||||||
|
id='firstname' |
||||||
|
label='Имя' |
||||||
|
labelWidth={labelWidth} |
||||||
|
/> |
||||||
|
<Input |
||||||
|
id='lastname' |
||||||
|
label='Фамилия' |
||||||
|
labelWidth={labelWidth} |
||||||
|
/> |
||||||
|
<Input |
||||||
|
id='phone' |
||||||
|
label='Телефон' |
||||||
|
labelWidth={labelWidth} |
||||||
|
/> |
||||||
|
<Input |
||||||
|
id='email' |
||||||
|
type='email' |
||||||
|
label='E-mail' |
||||||
|
labelWidth={labelWidth} |
||||||
|
/> |
||||||
|
{/* TODO: it should be Dropdown */} |
||||||
|
<Input |
||||||
|
id='country' |
||||||
|
label='Страна' |
||||||
|
labelWidth={labelWidth} |
||||||
|
/> |
||||||
|
<Input |
||||||
|
id='address' |
||||||
|
label='Адрес' |
||||||
|
labelWidth={labelWidth} |
||||||
|
/> |
||||||
|
|
||||||
|
<ButtonsBlock> |
||||||
|
<NextButton to={`${PAGES.register}/card`}>Далее</NextButton> |
||||||
|
</ButtonsBlock> |
||||||
|
</Form> |
||||||
|
) |
||||||
@ -0,0 +1,57 @@ |
|||||||
|
import React, { Fragment } from 'react' |
||||||
|
|
||||||
|
import { ButtonSolid } from 'features/Common/Button' |
||||||
|
import { ArrowLeft, ArrowRight } from 'features/Common/Arrows' |
||||||
|
import { ButtonsBlock } from 'features/Login/styled' |
||||||
|
|
||||||
|
import { MainSubscription } from 'features/Register/MainSubscription' |
||||||
|
import { AdditionalSubscription } from 'features/Register/AdditionalSubscription' |
||||||
|
|
||||||
|
import { |
||||||
|
SubscriptionsBlock, |
||||||
|
AdditionalBlockTitle, |
||||||
|
BlockTitle, |
||||||
|
SubscriptionList, |
||||||
|
SubscriptionListItem, |
||||||
|
PricesBlock, |
||||||
|
TotalInfoBlock, |
||||||
|
TotalInfoText, |
||||||
|
TotalPriceAmmount, |
||||||
|
TotalPriceDetails, |
||||||
|
} from './styled' |
||||||
|
|
||||||
|
export const SubscriptionStep = () => ( |
||||||
|
<Fragment> |
||||||
|
<SubscriptionsBlock> |
||||||
|
<BlockTitle>Выбор подписки</BlockTitle> |
||||||
|
<SubscriptionList> |
||||||
|
<SubscriptionListItem> |
||||||
|
<MainSubscription title='Бесплатная' price={0} /> |
||||||
|
</SubscriptionListItem> |
||||||
|
<SubscriptionListItem> |
||||||
|
<MainSubscription title='Базовая' price={1999} /> |
||||||
|
</SubscriptionListItem> |
||||||
|
</SubscriptionList> |
||||||
|
</SubscriptionsBlock> |
||||||
|
<SubscriptionsBlock forAdditionalTitle> |
||||||
|
<AdditionalBlockTitle>Дополнительно</AdditionalBlockTitle> |
||||||
|
<PricesBlock> |
||||||
|
<ArrowLeft /> |
||||||
|
<AdditionalSubscription title='Российская премьер-лига' price={1999} /> |
||||||
|
<AdditionalSubscription title='Primera División' price={1999} /> |
||||||
|
<AdditionalSubscription title='Manchester United' price={999} /> |
||||||
|
<AdditionalSubscription title='Василий Березуцкий' price={299} /> |
||||||
|
<ArrowRight /> |
||||||
|
</PricesBlock> |
||||||
|
</SubscriptionsBlock> |
||||||
|
<ButtonsBlock forSubsPage> |
||||||
|
<ButtonSolid>Готово</ButtonSolid> |
||||||
|
<TotalInfoBlock> |
||||||
|
<TotalInfoText>Базовая + 2 дополнительно за |
||||||
|
<TotalPriceAmmount>6997</TotalPriceAmmount> |
||||||
|
<TotalPriceDetails>₽ / МЕС</TotalPriceDetails> |
||||||
|
</TotalInfoText> |
||||||
|
</TotalInfoBlock> |
||||||
|
</ButtonsBlock> |
||||||
|
</Fragment> |
||||||
|
) |
||||||
@ -0,0 +1,97 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
export const SubscriptionsBlock = styled.div<{forAdditionalTitle?: boolean}>` |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: center; |
||||||
|
margin-top: ${({ forAdditionalTitle }) => (forAdditionalTitle ? '75px' : '80px')}; |
||||||
|
` |
||||||
|
|
||||||
|
export const BlockTitle = styled.span` |
||||||
|
display: block; |
||||||
|
font-style: normal; |
||||||
|
font-weight: bold; |
||||||
|
font-size: 36px; |
||||||
|
line-height: 24px; |
||||||
|
color: ${({ theme: { colors } }) => colors.text}; |
||||||
|
transition: color 0.3s ease-in-out; |
||||||
|
` |
||||||
|
|
||||||
|
export const AdditionalBlockTitle = styled(BlockTitle)` |
||||||
|
font-size: 32px; |
||||||
|
margin-bottom: 40px; |
||||||
|
` |
||||||
|
|
||||||
|
export const SubscriptionList = styled.ul` |
||||||
|
display: flex; |
||||||
|
margin-top: 40px; |
||||||
|
` |
||||||
|
|
||||||
|
export const SubscriptionListItem = styled.li`` |
||||||
|
|
||||||
|
export const SubscriptionWrapper = styled.div` |
||||||
|
position: relative; |
||||||
|
width: 288px; |
||||||
|
height: 216px; |
||||||
|
padding: 24px; |
||||||
|
margin: 0 8px; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
background: #3F3F3F; |
||||||
|
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.4); |
||||||
|
border-radius: 2px; |
||||||
|
` |
||||||
|
|
||||||
|
export const SubscriptionTitle = styled.span` |
||||||
|
font-style: normal; |
||||||
|
font-weight: bold; |
||||||
|
font-size: 18px; |
||||||
|
line-height: 21px; |
||||||
|
color: ${({ theme: { colors } }) => colors.text}; |
||||||
|
` |
||||||
|
|
||||||
|
type TRow = { |
||||||
|
bottom?: number, |
||||||
|
left?: number, |
||||||
|
} |
||||||
|
|
||||||
|
export const Row = styled.div<TRow>` |
||||||
|
position: absolute; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
left: ${({ left }) => left}px; |
||||||
|
bottom: ${({ bottom }) => bottom}px; |
||||||
|
` |
||||||
|
|
||||||
|
export const PricesBlock = styled.div` |
||||||
|
width: 1200px; |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
position: relative; |
||||||
|
` |
||||||
|
|
||||||
|
export const TotalInfoBlock = styled.div` |
||||||
|
width: 201px; |
||||||
|
position: absolute; |
||||||
|
display: flex; |
||||||
|
flex-wrap: wrap; |
||||||
|
top: 4px; |
||||||
|
left: 294px; |
||||||
|
` |
||||||
|
|
||||||
|
export const TotalInfoText = styled.span` |
||||||
|
font-weight: normal; |
||||||
|
font-size: 14px; |
||||||
|
line-height: 22px; |
||||||
|
color: rgba(255, 255, 255, 0.3); |
||||||
|
` |
||||||
|
|
||||||
|
export const TotalPriceAmmount = styled(TotalInfoText)` |
||||||
|
font-weight: bold; |
||||||
|
margin-left: 6px; |
||||||
|
` |
||||||
|
|
||||||
|
export const TotalPriceDetails = styled(TotalInfoText)` |
||||||
|
text-transform: uppercase; |
||||||
|
margin-left: 7px; |
||||||
|
` |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
export * from './Registration' |
||||||
|
export * from './Card' |
||||||
|
export * from './Subscriptions' |
||||||
@ -0,0 +1,31 @@ |
|||||||
|
import React from 'react' |
||||||
|
import { Route } from 'react-router' |
||||||
|
|
||||||
|
import { PAGES } from 'config' |
||||||
|
|
||||||
|
import { Background } from 'features/Background' |
||||||
|
import { Logo } from 'features/Logo' |
||||||
|
import { CenterBlock } from 'features/Login/styled' |
||||||
|
|
||||||
|
import { |
||||||
|
Registration, |
||||||
|
CardStep, |
||||||
|
SubscriptionStep, |
||||||
|
} from './Steps' |
||||||
|
|
||||||
|
export const Register = () => ( |
||||||
|
<Background> |
||||||
|
<CenterBlock> |
||||||
|
<Logo /> |
||||||
|
<Route exact path={`${PAGES.register}`}> |
||||||
|
<Registration /> |
||||||
|
</Route> |
||||||
|
<Route exact path={`${PAGES.register}/card`}> |
||||||
|
<CardStep /> |
||||||
|
</Route> |
||||||
|
<Route exact path={`${PAGES.register}/subscriptions`}> |
||||||
|
<SubscriptionStep /> |
||||||
|
</Route> |
||||||
|
</CenterBlock> |
||||||
|
</Background> |
||||||
|
) |
||||||
@ -0,0 +1,34 @@ |
|||||||
|
import { Link } from 'react-router-dom' |
||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import { solidButtonStyles } from 'features/Common' |
||||||
|
|
||||||
|
export const NextButton = styled(Link)` |
||||||
|
${solidButtonStyles} |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
` |
||||||
|
|
||||||
|
export const Card = styled.div` |
||||||
|
width: 546px; |
||||||
|
height: 340px; |
||||||
|
margin: 20px 0; |
||||||
|
padding: 0 32px; |
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1); |
||||||
|
box-sizing: border-box; |
||||||
|
border-radius: 16px; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
` |
||||||
|
|
||||||
|
export const Row = styled.div` |
||||||
|
width: 100%; |
||||||
|
display: flex; |
||||||
|
|
||||||
|
& div:last-child { |
||||||
|
margin-left: 16px; |
||||||
|
} |
||||||
|
` |
||||||
Loading…
Reference in new issue