diff --git a/package.json b/package.json index a1076adc..a0e041a5 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,12 @@ "build-storybook": "build-storybook -s public" }, "dependencies": { + "history": "^4.10.1", "lodash": "^4.17.15", "react": "^16.13.1", "react-dom": "^16.13.1", + "react-router": "^5.2.0", + "react-router-dom": "^5.2.0", "react-scripts": "3.4.1", "styled-components": "^5.1.1" }, @@ -32,11 +35,14 @@ "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", + "@types/history": "^4.7.6", "@types/jest": "^24.0.0", "@types/lodash": "^4.14.154", "@types/node": "^12.0.0", "@types/react": "^16.9.0", "@types/react-dom": "^16.9.0", + "@types/react-router": "^5.1.7", + "@types/react-router-dom": "^5.1.5", "@types/styled-components": "^5.1.0", "commitizen": "^4.1.2", "eslint": "6.8.0", diff --git a/src/config/pages.tsx b/src/config/pages.tsx index f960c655..570ecc08 100644 --- a/src/config/pages.tsx +++ b/src/config/pages.tsx @@ -1,3 +1,4 @@ export const PAGES = { login: '/login', + register: '/register', } diff --git a/src/features/App/index.tsx b/src/features/App/index.tsx index 153f5549..b4eb6673 100644 --- a/src/features/App/index.tsx +++ b/src/features/App/index.tsx @@ -1,12 +1,36 @@ 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 { Login } from 'features/Login' -import { GlobalStyles } from 'features/GlobalStyles' +import { Register } from 'features/Register' + +const history = createBrowserHistory() export const App = () => ( - - - - + + + + + + + + + + + + + + + + + ) diff --git a/src/features/Background/styled.tsx b/src/features/Background/styled.tsx index 45fd69af..3bc49b1b 100644 --- a/src/features/Background/styled.tsx +++ b/src/features/Background/styled.tsx @@ -1,8 +1,8 @@ import styled from 'styled-components/macro' const Container = styled.div` - width: 100vw; - height: 100vh; + width: 100%; + min-height: 100vh; ` export const ImageBackground = styled(Container)` @@ -21,5 +21,4 @@ export const CenterBlock = styled.div` display: flex; flex-direction: column; align-items: center; - margin-top: 140px; ` diff --git a/src/features/Common/Arrows/index.tsx b/src/features/Common/Arrows/index.tsx index 4302a0c0..c8f1575e 100644 --- a/src/features/Common/Arrows/index.tsx +++ b/src/features/Common/Arrows/index.tsx @@ -9,6 +9,9 @@ const ArrowStyled = styled.button` background-color: transparent; background-position: center; outline: none; + z-index: 1; + position: absolute; + cursor: pointer; :active { background-color: rgba(117, 117, 117, 1); @@ -21,8 +24,14 @@ const ArrowStyled = styled.button` export const ArrowLeft = styled(ArrowStyled)` background-image: url(/images/arrowLeft.svg); + top: 50%; + left: 0px; + transform: translate(-10px, -50%); ` export const ArrowRight = styled(ArrowStyled)` background-image: url(/images/arrowRight.svg); + top: 50%; + right: 0px; + transform: translate(10px, -50%); ` diff --git a/src/features/Common/Button/styled.tsx b/src/features/Common/Button/styled.tsx index 04a2c45a..5669f9f1 100644 --- a/src/features/Common/Button/styled.tsx +++ b/src/features/Common/Button/styled.tsx @@ -27,10 +27,9 @@ export const outlineButtonStyles = css` export const solidButtonStyles = css` ${baseButtonStyles} - padding-top: 18.5px; - padding-bottom: 13px; - color: #FFFFFF; + color: #fff; font-weight: bold; + cursor: pointer; border-color: transparent; background: ${({ theme: { colors } }) => colors.primary}; ` diff --git a/src/features/Common/Checkbox/styled.tsx b/src/features/Common/Checkbox/styled.tsx index 6c62dff1..29b41c8c 100644 --- a/src/features/Common/Checkbox/styled.tsx +++ b/src/features/Common/Checkbox/styled.tsx @@ -1,7 +1,6 @@ import styled from 'styled-components/macro' export const Wrapper = styled.div` - ` export const Label = styled.label` @@ -32,6 +31,7 @@ export const Input = styled.input` background-repeat: no-repeat; background-position: center center; background-image: url(/images/checkboxUnchecked.svg); + cursor: pointer; } &:checked+${Label}::before { diff --git a/src/features/Common/Radio/index.tsx b/src/features/Common/Radio/index.tsx index 7ef499cf..cd95ecbc 100644 --- a/src/features/Common/Radio/index.tsx +++ b/src/features/Common/Radio/index.tsx @@ -19,7 +19,7 @@ type TCheckbox = Pick, ( export const Radio = ({ checked, id, - label, + label = '', name, onChange, value, diff --git a/src/features/Common/Radio/styled.tsx b/src/features/Common/Radio/styled.tsx index 9a98a8e6..eae7aa32 100644 --- a/src/features/Common/Radio/styled.tsx +++ b/src/features/Common/Radio/styled.tsx @@ -32,6 +32,7 @@ export const Input = styled.input` background-repeat: no-repeat; background-position: center center; background-image: url(/images/radioUnchecked.svg); + cursor: pointer; } &:checked+${Label}::before { diff --git a/src/features/Login/index.tsx b/src/features/Login/index.tsx index 4ba48171..972d5af5 100644 --- a/src/features/Login/index.tsx +++ b/src/features/Login/index.tsx @@ -1,11 +1,12 @@ import React from 'react' +import { PAGES } from 'config' + import { Background } from 'features/Background' import { Logo } from 'features/Logo' import { Input, ButtonSolid, - ButtonOutline, } from 'features/Common' import { @@ -13,6 +14,7 @@ import { CenterBlock, ButtonsBlock, Form, + RegisterButton, } from './styled' const labelWidth = 60 @@ -41,9 +43,9 @@ export const Login = () => ( Войти - + Зарегистрироваться - + diff --git a/src/features/Login/styled.tsx b/src/features/Login/styled.tsx index b7f9bffb..bc2837a3 100644 --- a/src/features/Login/styled.tsx +++ b/src/features/Login/styled.tsx @@ -1,15 +1,19 @@ +import { Link } from 'react-router-dom' import styled from 'styled-components/macro' +import { outlineButtonStyles } from 'features/Common' + export const CenterBlock = styled.div` display: flex; flex-direction: column; align-items: center; + justify-content: flex-start; margin-top: 140px; ` export const Form = styled.form` width: 544px; - margin-top: 80px; + margin: 80px 0 140px 0; display: flex; flex-direction: column; align-items: center; @@ -26,12 +30,18 @@ export const BlockTitle = styled.span` transition: color 0.3s ease-in-out; ` -export const ButtonsBlock = styled.div` +export const ButtonsBlock = styled.div<{forSubsPage?: boolean}>` display: flex; flex-direction: column; - margin-top: 60px; + margin-top: ${({ forSubsPage }) => (forSubsPage ? '80px' : '60px')}; + margin-bottom: ${({ forSubsPage }) => (forSubsPage ? '96px' : '')}; + position: relative; +` - & > * { - margin-bottom: 40px; - } +export const RegisterButton = styled(Link)` + ${outlineButtonStyles} + margin-top: 40px; + display: flex; + align-items: center; + justify-content: center; ` diff --git a/src/features/Register/AdditionalSubscription/index.tsx b/src/features/Register/AdditionalSubscription/index.tsx new file mode 100644 index 00000000..43640193 --- /dev/null +++ b/src/features/Register/AdditionalSubscription/index.tsx @@ -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) => ( + + + + + + {title} + + + +) diff --git a/src/features/Register/AdditionalSubscription/styled.tsx b/src/features/Register/AdditionalSubscription/styled.tsx new file mode 100644 index 00000000..c73bbb30 --- /dev/null +++ b/src/features/Register/AdditionalSubscription/styled.tsx @@ -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; +` diff --git a/src/features/Register/MainSubscription/index.tsx b/src/features/Register/MainSubscription/index.tsx new file mode 100644 index 00000000..9685a56f --- /dev/null +++ b/src/features/Register/MainSubscription/index.tsx @@ -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) => ( + + + + {title} + + + + + +) diff --git a/src/features/Register/Price/index.tsx b/src/features/Register/Price/index.tsx new file mode 100644 index 00000000..d5f23214 --- /dev/null +++ b/src/features/Register/Price/index.tsx @@ -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) => ( + + {amount} + {currency} / {perPeriod} + +) diff --git a/src/features/Register/Price/styled.tsx b/src/features/Register/Price/styled.tsx new file mode 100644 index 00000000..cdd64c3d --- /dev/null +++ b/src/features/Register/Price/styled.tsx @@ -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; +` diff --git a/src/features/Register/Steps/Card/index.tsx b/src/features/Register/Steps/Card/index.tsx new file mode 100644 index 00000000..3da20959 --- /dev/null +++ b/src/features/Register/Steps/Card/index.tsx @@ -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 = () => ( +
+ Привязка карты + + + + + + + + + + Далее + +
+) diff --git a/src/features/Register/Steps/Registration/index.tsx b/src/features/Register/Steps/Registration/index.tsx new file mode 100644 index 00000000..9e5a5fe8 --- /dev/null +++ b/src/features/Register/Steps/Registration/index.tsx @@ -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 = () => ( +
+ Регистрация + + + + + + {/* TODO: it should be Dropdown */} + + + + + Далее + +
+) diff --git a/src/features/Register/Steps/Subscriptions/index.tsx b/src/features/Register/Steps/Subscriptions/index.tsx new file mode 100644 index 00000000..ba620420 --- /dev/null +++ b/src/features/Register/Steps/Subscriptions/index.tsx @@ -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 = () => ( + + + Выбор подписки + + + + + + + + + + + Дополнительно + + + + + + + + + + + Готово + + Базовая + 2 дополнительно за + 6997 + ₽ / МЕС + + + + +) diff --git a/src/features/Register/Steps/Subscriptions/styled.tsx b/src/features/Register/Steps/Subscriptions/styled.tsx new file mode 100644 index 00000000..ebb1aba6 --- /dev/null +++ b/src/features/Register/Steps/Subscriptions/styled.tsx @@ -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` + 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; +` diff --git a/src/features/Register/Steps/index.tsx b/src/features/Register/Steps/index.tsx new file mode 100644 index 00000000..ceb3df99 --- /dev/null +++ b/src/features/Register/Steps/index.tsx @@ -0,0 +1,3 @@ +export * from './Registration' +export * from './Card' +export * from './Subscriptions' diff --git a/src/features/Register/index.tsx b/src/features/Register/index.tsx new file mode 100644 index 00000000..657a8773 --- /dev/null +++ b/src/features/Register/index.tsx @@ -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 = () => ( + + + + + + + + + + + + + + +) diff --git a/src/features/Register/styled.tsx b/src/features/Register/styled.tsx new file mode 100644 index 00000000..12833bf6 --- /dev/null +++ b/src/features/Register/styled.tsx @@ -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; + } +`