diff --git a/public/index.html b/public/index.html
index 9a8ef8f..5d57a79 100644
--- a/public/index.html
+++ b/public/index.html
@@ -8,7 +8,7 @@
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
-
React App
+ Яндекс.Почта
diff --git a/src/app/app.css b/src/app/app.css
index 1c4d511..69bbb16 100644
--- a/src/app/app.css
+++ b/src/app/app.css
@@ -1,27 +1,29 @@
-.app {
- text-align: center;
+@font-face {
+ font-family: YandexSansBold;
+ src: url(fonts/YandexSansDisplay-Bold.ttf);
}
-.app-header {
- display: flex;
- min-height: 100vh;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- background-color: #282c34;
- color: #fff;
- font-size: calc(10px + 2vmin);
+@font-face {
+ font-family: YandexSansThin;
+ src: url(/src/app/fonts/YandexSansDisplay-Thin.ttf);
}
-.app-link {
- color: #61dafb;
+@font-face {
+ font-family: HelveticaNeue;
+ src: url(/src/app/fonts/HelveticaNeueCyr-Medium.otf);
}
-@keyframes app-logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
+@font-face {
+ font-family: HelveticaNeueLight;
+ src: url(/src/app/fonts/HelveticaNeueCyr-Light.otf);
+}
+
+body {
+ position: relative;
+
+ min-width: 750px;
+ max-width: 1600px;
+ padding: 0;
+ margin: 0 auto;
+ background: #e5eaf0;
}
diff --git a/src/app/app.jsx b/src/app/app.jsx
index f759eed..9574d3e 100644
--- a/src/app/app.jsx
+++ b/src/app/app.jsx
@@ -1,24 +1,17 @@
import React, { Component } from 'react';
import './app.css';
+import { Header } from './structure/header/header';
+import { Menu } from './structure/menu/menu';
+import { MainContent } from './structure/main-content/mainContent';
export class App extends Component {
render() {
return (
);
}
diff --git a/src/app/fonts/HelveticaNeueCyr-Light.otf b/src/app/fonts/HelveticaNeueCyr-Light.otf
new file mode 100755
index 0000000..7ced49a
Binary files /dev/null and b/src/app/fonts/HelveticaNeueCyr-Light.otf differ
diff --git a/src/app/fonts/HelveticaNeueCyr-Medium.otf b/src/app/fonts/HelveticaNeueCyr-Medium.otf
new file mode 100755
index 0000000..a2cde16
Binary files /dev/null and b/src/app/fonts/HelveticaNeueCyr-Medium.otf differ
diff --git a/src/app/fonts/YandexSansDisplay-Bold.ttf b/src/app/fonts/YandexSansDisplay-Bold.ttf
new file mode 100755
index 0000000..d901f4b
Binary files /dev/null and b/src/app/fonts/YandexSansDisplay-Bold.ttf differ
diff --git a/src/app/fonts/YandexSansDisplay-Thin.ttf b/src/app/fonts/YandexSansDisplay-Thin.ttf
new file mode 100755
index 0000000..3b8e196
Binary files /dev/null and b/src/app/fonts/YandexSansDisplay-Thin.ttf differ
diff --git a/src/app/structure/header/header.css b/src/app/structure/header/header.css
new file mode 100644
index 0000000..edc064c
--- /dev/null
+++ b/src/app/structure/header/header.css
@@ -0,0 +1,35 @@
+/*Start SearchInput*/
+
+.header {
+ margin-top: 7px;
+ margin-bottom: 18px;
+ margin-left: 22px;
+}
+
+.header__lines,
+.header__main-logo {
+ margin: 0;
+ float: left;
+}
+
+.header__lines {
+ margin-top: 12px;
+}
+
+.header__line {
+ width: 20px;
+ height: 3px;
+ margin-top: 4px;
+ background-color: #000000;
+}
+
+.header__main-logo {
+ margin-top: 7px;
+ margin-left: 11px;
+}
+
+.clearfix:after {
+ display: table;
+ clear: both;
+ content: '';
+}
diff --git a/src/app/structure/header/header.jsx b/src/app/structure/header/header.jsx
new file mode 100644
index 0000000..6267f69
--- /dev/null
+++ b/src/app/structure/header/header.jsx
@@ -0,0 +1,23 @@
+import React, { Component } from 'react';
+
+import './header.css';
+import logo from './images/logo.png';
+import { SearchInput } from './searchInput/searchInput';
+
+export class Header extends Component {
+ render() {
+ return (
+
+
+
+

+
+
+
+ );
+ }
+}
diff --git a/src/app/structure/header/images/logo.png b/src/app/structure/header/images/logo.png
new file mode 100644
index 0000000..e79b98c
Binary files /dev/null and b/src/app/structure/header/images/logo.png differ
diff --git a/src/app/structure/header/images/reset.png b/src/app/structure/header/images/reset.png
new file mode 100644
index 0000000..ab907a0
Binary files /dev/null and b/src/app/structure/header/images/reset.png differ
diff --git a/src/app/structure/header/searchInput/searchInput.css b/src/app/structure/header/searchInput/searchInput.css
new file mode 100644
index 0000000..9904a40
--- /dev/null
+++ b/src/app/structure/header/searchInput/searchInput.css
@@ -0,0 +1,32 @@
+.header__search {
+ width: 37%;
+ height: 32px;
+ margin-top: 11px;
+ margin-left: 114px;
+ background: #f2f5f8;
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);
+ float: left;
+}
+
+.header__input {
+ display: inline-block;
+ width: calc(100% - 50px);
+ height: 26px;
+ margin-left: 16px;
+
+ border: none;
+ background: none;
+ outline: none;
+ vertical-align: center;
+}
+
+.header__button {
+ width: 12px;
+ height: 12px;
+ padding: 0;
+ margin: 10px;
+
+ border: none;
+ background: #f2f5f8;
+ float: right;
+}
diff --git a/src/app/structure/header/searchInput/searchInput.jsx b/src/app/structure/header/searchInput/searchInput.jsx
new file mode 100644
index 0000000..abee1a7
--- /dev/null
+++ b/src/app/structure/header/searchInput/searchInput.jsx
@@ -0,0 +1,31 @@
+import React from 'react';
+
+import './searchInput.css';
+import reset from '../images/reset.png';
+
+export class SearchInput extends React.Component {
+ constructor(props) {
+ super(props);
+ this.inputVal = '';
+ }
+
+ resetForm = () => {
+ this.inputVal.value = '';
+ };
+
+ render() {
+ return (
+
+
(this.inputVal = el)}
+ placeholder="Поиск"
+ className="header__input"
+ />
+
+
+ );
+ }
+}
diff --git a/src/app/structure/main-content/all-functions/Button/Button.css b/src/app/structure/main-content/all-functions/Button/Button.css
new file mode 100644
index 0000000..e082e9f
--- /dev/null
+++ b/src/app/structure/main-content/all-functions/Button/Button.css
@@ -0,0 +1,13 @@
+.main-block__ref-func {
+ border: none;
+ background: none;
+ color: #cccccc;
+ font-family: "'HelveticaNeue'", sans-serif;
+ font-size: 13px;
+ font-weight: 500;
+ text-decoration: none;
+}
+
+.main-block__ref-func:hover {
+ border-bottom: 2px solid #cccccc;
+}
diff --git a/src/app/structure/main-content/all-functions/Button/Button.jsx b/src/app/structure/main-content/all-functions/Button/Button.jsx
new file mode 100644
index 0000000..95f48f5
--- /dev/null
+++ b/src/app/structure/main-content/all-functions/Button/Button.jsx
@@ -0,0 +1,25 @@
+import React, { Component } from 'react';
+
+import './Button.css';
+
+export class Button extends Component {
+ constructor(props) {
+ super(props);
+ this.action = this.props.action.bind(this);
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/src/app/structure/main-content/all-functions/allFunctions.css b/src/app/structure/main-content/all-functions/allFunctions.css
new file mode 100644
index 0000000..b785a7f
--- /dev/null
+++ b/src/app/structure/main-content/all-functions/allFunctions.css
@@ -0,0 +1,37 @@
+.clearfix:after {
+ display: table;
+ clear: both;
+ content: '';
+}
+
+.check {
+ width: 16px;
+ height: 16px;
+ margin: 12px;
+
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ background-color: #ffffff;
+ border-radius: 3px;
+ float: left;
+}
+
+.hidden-check {
+ display: none;
+}
+
+.main-block__mail-functions {
+ height: 40px;
+
+ border-bottom: 2px solid rgba(0, 0, 0, 0.15);
+}
+
+.main-block__all-function {
+ padding-top: 6px;
+ margin: 0;
+}
+
+.main-block__func {
+ display: inline-block;
+ margin-left: 20px;
+ list-style: none;
+}
diff --git a/src/app/structure/main-content/all-functions/allFunctions.jsx b/src/app/structure/main-content/all-functions/allFunctions.jsx
new file mode 100644
index 0000000..dcbdc94
--- /dev/null
+++ b/src/app/structure/main-content/all-functions/allFunctions.jsx
@@ -0,0 +1,72 @@
+import React, { Component } from 'react';
+
+import './allFunctions.css';
+import { Button } from './Button/Button';
+
+export class AllFunctions extends Component {
+ constructor(props) {
+ super(props);
+ this.newMailOnClick = this.props.newMailOnClick.bind(this);
+ this.deleteLetter = this.props.deleteLetter.bind(this);
+ this.selectAll = this.props.selectAll.bind(this);
+ }
+
+ doNothing = () => {};
+
+ render() {
+ return (
+
+
{
+ if (!this.props.isLetterOpened) this.selectAll();
+ }}
+ />
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ );
+ }
+}
diff --git a/src/app/structure/main-content/footer/footer.css b/src/app/structure/main-content/footer/footer.css
new file mode 100644
index 0000000..2a868f3
--- /dev/null
+++ b/src/app/structure/main-content/footer/footer.css
@@ -0,0 +1,20 @@
+.footer {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+
+ width: 100%;
+ height: 26px;
+ padding-top: 5px;
+
+ border-top: 2px solid rgba(140, 140, 140, 0.45);
+ background-color: white;
+ color: #9b9b9b;
+ font-family: "'HelveticaNeue'", sans-serif;
+ font-size: 0.7em;
+}
+
+.footer__texts {
+ margin-right: 20px;
+ float: right;
+}
diff --git a/src/app/structure/main-content/footer/footer.jsx b/src/app/structure/main-content/footer/footer.jsx
new file mode 100644
index 0000000..9e317a3
--- /dev/null
+++ b/src/app/structure/main-content/footer/footer.jsx
@@ -0,0 +1,18 @@
+import React, { Component } from 'react';
+
+import './footer.css';
+import { FooterText } from './footerText/footerText';
+
+export class Footer extends Component {
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/src/app/structure/main-content/footer/footerText/footerText.css b/src/app/structure/main-content/footer/footerText/footerText.css
new file mode 100644
index 0000000..f9d6c77
--- /dev/null
+++ b/src/app/structure/main-content/footer/footerText/footerText.css
@@ -0,0 +1,5 @@
+.footer__ref {
+ margin-right: 10px;
+ color: #9b9b9b;
+ text-decoration: none;
+}
diff --git a/src/app/structure/main-content/footer/footerText/footerText.jsx b/src/app/structure/main-content/footer/footerText/footerText.jsx
new file mode 100644
index 0000000..2513a08
--- /dev/null
+++ b/src/app/structure/main-content/footer/footerText/footerText.jsx
@@ -0,0 +1,13 @@
+import React, { Component } from 'react';
+
+import './footerText.css';
+
+export class FooterText extends Component {
+ render() {
+ return (
+
+ {this.props.text}
+
+ );
+ }
+}
diff --git a/src/app/structure/main-content/letters/letter-page/img/reset.png b/src/app/structure/main-content/letters/letter-page/img/reset.png
new file mode 100644
index 0000000..ab907a0
Binary files /dev/null and b/src/app/structure/main-content/letters/letter-page/img/reset.png differ
diff --git a/src/app/structure/main-content/letters/letter-page/letterPage.css b/src/app/structure/main-content/letters/letter-page/letterPage.css
new file mode 100644
index 0000000..95ebd5e
--- /dev/null
+++ b/src/app/structure/main-content/letters/letter-page/letterPage.css
@@ -0,0 +1,25 @@
+.main-block__letter-content {
+ position: absolute;
+ top: 42px;
+
+ overflow: scroll;
+ width: 100%;
+ height: calc(100% - 70px);
+ padding: 0;
+ background: #ffffff;
+ color: #000000;
+ float: left;
+ font-family: "'HelveticaNeue'", sans-serif;
+ font-size: 0.8em;
+ font-weight: 700;
+}
+
+.main-block__paragraph {
+ padding: 10px;
+ margin-top: 10px;
+}
+
+.close {
+ padding: 15px;
+ float: right;
+}
diff --git a/src/app/structure/main-content/letters/letter-page/letterPage.jsx b/src/app/structure/main-content/letters/letter-page/letterPage.jsx
new file mode 100644
index 0000000..829d0cc
--- /dev/null
+++ b/src/app/structure/main-content/letters/letter-page/letterPage.jsx
@@ -0,0 +1,28 @@
+import React, { Component } from 'react';
+
+import './letterPage.css';
+import reset from './img/reset.png';
+
+export class LetterPage extends Component {
+ constructor(props) {
+ super(props);
+ this.closeLetter = this.props.closeLetter.bind(this);
+ }
+
+ render() {
+ return (
+
+

{
+ this.closeLetter();
+ }}
+ />
+
{this.props.text}
+
+ );
+ }
+}
diff --git a/src/app/structure/main-content/letters/letters-list/letter/icons/ebay.png b/src/app/structure/main-content/letters/letters-list/letter/icons/ebay.png
new file mode 100644
index 0000000..c9edef4
Binary files /dev/null and b/src/app/structure/main-content/letters/letters-list/letter/icons/ebay.png differ
diff --git a/src/app/structure/main-content/letters/letters-list/letter/icons/facebook.png b/src/app/structure/main-content/letters/letters-list/letter/icons/facebook.png
new file mode 100644
index 0000000..2d7290c
Binary files /dev/null and b/src/app/structure/main-content/letters/letters-list/letter/icons/facebook.png differ
diff --git a/src/app/structure/main-content/letters/letters-list/letter/icons/live.png b/src/app/structure/main-content/letters/letters-list/letter/icons/live.png
new file mode 100644
index 0000000..19f8a27
Binary files /dev/null and b/src/app/structure/main-content/letters/letters-list/letter/icons/live.png differ
diff --git a/src/app/structure/main-content/letters/letters-list/letter/icons/reddit.png b/src/app/structure/main-content/letters/letters-list/letter/icons/reddit.png
new file mode 100644
index 0000000..a297ce9
Binary files /dev/null and b/src/app/structure/main-content/letters/letters-list/letter/icons/reddit.png differ
diff --git a/src/app/structure/main-content/letters/letters-list/letter/icons/twitter.png b/src/app/structure/main-content/letters/letters-list/letter/icons/twitter.png
new file mode 100644
index 0000000..41e07c1
Binary files /dev/null and b/src/app/structure/main-content/letters/letters-list/letter/icons/twitter.png differ
diff --git a/src/app/structure/main-content/letters/letters-list/letter/icons/yandex.png b/src/app/structure/main-content/letters/letters-list/letter/icons/yandex.png
new file mode 100644
index 0000000..df4059c
Binary files /dev/null and b/src/app/structure/main-content/letters/letters-list/letter/icons/yandex.png differ
diff --git a/src/app/structure/main-content/letters/letters-list/letter/icons/youtube.png b/src/app/structure/main-content/letters/letters-list/letter/icons/youtube.png
new file mode 100644
index 0000000..f06f858
Binary files /dev/null and b/src/app/structure/main-content/letters/letters-list/letter/icons/youtube.png differ
diff --git a/src/app/structure/main-content/letters/letters-list/letter/letter.css b/src/app/structure/main-content/letters/letters-list/letter/letter.css
new file mode 100644
index 0000000..eee2846
--- /dev/null
+++ b/src/app/structure/main-content/letters/letters-list/letter/letter.css
@@ -0,0 +1,78 @@
+.check {
+ width: 16px;
+ height: 16px;
+ margin: 12px;
+
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ background-color: #ffffff;
+ border-radius: 3px;
+ float: left;
+}
+
+.main-block__topic {
+ overflow: hidden;
+ width: 30%;
+ min-width: 30px;
+ height: 18px;
+ margin-top: 11px;
+ margin-left: 2%;
+ color: #000000;
+ float: left;
+ font-family: "'HelveticaNeue'", sans-serif;
+ font-size: 0.8em;
+}
+
+.main-block__letter {
+ height: 40px;
+
+ border-bottom: 2px solid #e2e2e2;
+ list-style: none;
+}
+
+.main-block__img {
+ height: 30px;
+ margin-top: 5px;
+ margin-left: 2%;
+ float: left;
+ text-align: center;
+}
+
+.main-block__mail-from {
+ overflow: hidden;
+ width: 29%;
+ height: 18px;
+ margin: 10px;
+ float: left;
+ font-family: "'HelveticaNeue'", sans-serif;
+ font-size: 0.8em;
+}
+
+.main-block__mail-not-read {
+ width: 10px;
+ height: 10px;
+ margin-top: 15px;
+ margin-left: 10px;
+ background: #6287bd;
+ border-radius: 50%;
+ float: left;
+}
+
+.hidden {
+ visibility: hidden;
+}
+
+.bold-text {
+ font-weight: 700;
+}
+
+.main-block__date {
+ overflow: hidden;
+ width: 6%;
+ height: 15px;
+ margin-top: 12px;
+ margin-right: 2%;
+ color: #9b9b9b;
+ float: right;
+ font-family: "'HelveticaNeue'", sans-serif;
+ font-size: 11px;
+}
diff --git a/src/app/structure/main-content/letters/letters-list/letter/letter.jsx b/src/app/structure/main-content/letters/letters-list/letter/letter.jsx
new file mode 100644
index 0000000..4cfbc41
--- /dev/null
+++ b/src/app/structure/main-content/letters/letters-list/letter/letter.jsx
@@ -0,0 +1,53 @@
+import React, { Component } from 'react';
+
+import './letter.css';
+import logo1 from './icons/ebay.png';
+import logo2 from './icons/yandex.png';
+import logo3 from './icons/live.png';
+import logo4 from './icons/facebook.png';
+import logo5 from './icons/twitter.png';
+import logo6 from './icons/reddit.png';
+import logo7 from './icons/youtube.png';
+
+export class Letter extends Component {
+ constructor(props) {
+ super(props);
+ this.onCheckboxChange = this.props.onCheckboxChange.bind(this);
+ this.openLetter = this.props.openLetter.bind(this);
+ this.firms = {
+ ebay: logo1,
+ yandex: logo2,
+ live: logo3,
+ facebook: logo4,
+ twitter: logo5,
+ reddit: logo6,
+ youtube: logo7
+ };
+ }
+
+ render() {
+ return (
+
+
+
this.onCheckboxChange(this.props.id)}
+ checked={this.props.isChecked}
+ />
+
this.openLetter(this.props.text)}>
+
+

+
+
{this.props.author}
+
+
{this.props.topic}
+
+
+
+
+ );
+ }
+}
diff --git a/src/app/structure/main-content/letters/letters-list/letterList.jsx b/src/app/structure/main-content/letters/letters-list/letterList.jsx
new file mode 100644
index 0000000..8342e4e
--- /dev/null
+++ b/src/app/structure/main-content/letters/letters-list/letterList.jsx
@@ -0,0 +1,29 @@
+import React, { Component } from 'react';
+
+import './lettersList.css';
+import { Letter } from './letter/letter';
+
+export class LetterList extends Component {
+ render() {
+ return (
+
+ {this.props.letters.map(letter => {
+ if (letter.isVisible)
+ return (
+
+ );
+ })}
+
+ );
+ }
+}
diff --git a/src/app/structure/main-content/letters/letters-list/lettersList.css b/src/app/structure/main-content/letters/letters-list/lettersList.css
new file mode 100644
index 0000000..fd91245
--- /dev/null
+++ b/src/app/structure/main-content/letters/letters-list/lettersList.css
@@ -0,0 +1,45 @@
+.main-block__all-letters {
+ overflow: scroll;
+ height: calc(100vh - 14px);
+ padding: 0;
+ margin: 0;
+}
+
+.animation-insert {
+ animation: inserting 0.5s linear;
+}
+
+.all-letter-down {
+ animation: down 0.6s linear;
+}
+
+.animation-delete {
+ animation: deleting 0.6s linear;
+}
+
+@keyframes inserting {
+ 0% {
+ transform: scale(0.5);
+ }
+ 100% {
+ transform: scale(1);
+ }
+}
+
+@keyframes down {
+ 0% {
+ transform: translateY(-40px);
+ }
+ 100% {
+ opacity: 1;
+ }
+}
+
+@keyframes deleting {
+ 0% {
+ transform: scale(1);
+ }
+ 100% {
+ transform: scale(0.5);
+ }
+}
diff --git a/src/app/structure/main-content/letters/letters.css b/src/app/structure/main-content/letters/letters.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/structure/main-content/letters/letters.jsx b/src/app/structure/main-content/letters/letters.jsx
new file mode 100644
index 0000000..eb1002e
--- /dev/null
+++ b/src/app/structure/main-content/letters/letters.jsx
@@ -0,0 +1,20 @@
+import React, { Component } from 'react';
+
+import './letters.css';
+import { LetterPage } from './letter-page/letterPage';
+import { LetterList } from './letters-list/letterList';
+
+export class Letters extends Component {
+ render() {
+ return this.props.isLetterOpened ? (
+
+ ) : (
+
+ );
+ }
+}
diff --git a/src/app/structure/main-content/mainContent.css b/src/app/structure/main-content/mainContent.css
new file mode 100644
index 0000000..909b74c
--- /dev/null
+++ b/src/app/structure/main-content/mainContent.css
@@ -0,0 +1,14 @@
+.main-block {
+ position: relative;
+
+ width: calc(100% - 230px);
+ min-width: 515px;
+ min-height: 300px;
+ padding: 0;
+ margin: 0 20px 14px 22px;
+
+ background-color: #ffffff;
+ border-radius: 3px;
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.34);
+ float: right;
+}
diff --git a/src/app/structure/main-content/mainContent.jsx b/src/app/structure/main-content/mainContent.jsx
new file mode 100644
index 0000000..8e68e7d
--- /dev/null
+++ b/src/app/structure/main-content/mainContent.jsx
@@ -0,0 +1,134 @@
+import React, { Component } from 'react';
+
+import './mainContent.css';
+import { Letters } from './letters/letters';
+import { AllFunctions } from './all-functions/allFunctions';
+import { generateNewLetter, randomInt } from './scripts/generator';
+import { Footer } from './footer/footer';
+
+const LETTERS_ON_PAGE = 30;
+
+export class MainContent extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ isLetterOpened: false,
+ openedLetterText: null,
+ letters: [],
+ isAllChecked: false,
+ checkedLetters: {}
+ };
+
+ this.onCheckboxChange = this.onCheckboxChange.bind(this);
+ this.selectAll = this.selectAll.bind(this);
+ this.newMail = this.newMail.bind(this);
+ this.deleteLetter = this.deleteLetter.bind(this);
+ this.getRandomLetter = this.getRandomLetter.bind(this);
+ this.openLetter = this.openLetter.bind(this);
+ this.closeLetter = this.closeLetter.bind(this);
+
+ setTimeout(this.getRandomLetter, 100);
+ }
+
+ onCheckboxChange(id) {
+ this.setState(prevState => {
+ const newCheckedLetters = prevState.checkedLetters;
+ newCheckedLetters[id] = !newCheckedLetters[id];
+ return {
+ isAllChecked: false,
+ checkedLetters: newCheckedLetters
+ };
+ });
+ }
+
+ getRandomLetter() {
+ const t = randomInt(10, 300000) + 300000;
+ this.newMail();
+ setTimeout(this.getRandomLetter, t);
+ }
+
+ selectAll() {
+ this.setState(prevState => {
+ const newCheckedLetters = prevState.checkedLetters;
+ prevState.letters.forEach(letter => {
+ if (letter.isVisible) {
+ newCheckedLetters[letter.key] = !prevState.isAllChecked;
+ }
+ });
+ return {
+ isAllChecked: !prevState.isAllChecked,
+ checkedLetters: newCheckedLetters
+ };
+ });
+ }
+
+ newMail() {
+ const newLetter = generateNewLetter();
+ this.setState(prevState => {
+ const newCheckedLetters = prevState.checkedLetters;
+ const newLetters = prevState.letters;
+ newCheckedLetters[newLetter.id] = false;
+ for (let i = newLetters.length - 1; i >= LETTERS_ON_PAGE - 1; i--) {
+ newLetters[i].isVisible = false;
+ newLetters[i].isChecked = false;
+ newCheckedLetters[newLetters[i].key] = false;
+ }
+ return {
+ letters: [newLetter, ...newLetters],
+ checkedLetters: newCheckedLetters,
+ isAllChecked: false
+ };
+ });
+ }
+
+ deleteLetter() {
+ this.setState(prevState => {
+ const newLetters = prevState.letters.filter(letter => !prevState.checkedLetters[letter.key]);
+ for (let i = 0; i < Math.min(newLetters.length, LETTERS_ON_PAGE); i++) {
+ newLetters[i].isVisible = true;
+ }
+ return {
+ letters: newLetters,
+ isAllChecked: false
+ };
+ });
+ }
+
+ openLetter(text) {
+ this.setState({
+ isLetterOpened: true,
+ openedLetterText: text
+ });
+ }
+
+ closeLetter() {
+ this.setState({
+ isLetterOpened: false,
+ openedLetterText: null
+ });
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/src/app/structure/main-content/scripts/generator.js b/src/app/structure/main-content/scripts/generator.js
new file mode 100644
index 0000000..a90f2bb
--- /dev/null
+++ b/src/app/structure/main-content/scripts/generator.js
@@ -0,0 +1,119 @@
+const companies = ['ebay', 'facebook', 'live', 'yandex', 'live', 'reddit', 'twitter', 'youtube'];
+const topics = [
+ 'Внимание!',
+ 'Добро пожаловать!',
+ 'Обновление',
+ 'Получите приз!',
+ 'Восстановление аккаунта',
+ 'Ищем сотрудников',
+ 'Спасибо за отзыв'
+];
+const hello = ['Здравствуйте!', 'Добрый день!', 'Привет!', 'Приветствую!', 'Салют!'];
+const word1 = ['Я', 'Меня зовут', 'Это'];
+const firstName = ['Виталий', 'Андрей', 'Владимир', 'Алексей', 'Артём', 'Антон'];
+const secondName = [
+ 'Соболев',
+ 'Чиркин',
+ 'Борисов',
+ 'Орехов',
+ 'Гаврилов',
+ 'Иванов',
+ 'Сергеев',
+ 'Онегин'
+];
+const phrase1 = [
+ 'Так вышло, что',
+ 'Нам стало известно, что',
+ 'Сообщаем вам, что',
+ 'Как вы могли заметить,',
+ 'С сегоднящнего дня'
+];
+const nouns1 = ['эксперт', 'редактор', 'программист', 'рабочий'];
+const verbs = [
+ 'взломал',
+ 'проверил',
+ 'удалил',
+ 'исправил',
+ 'закрыл',
+ 'заметил',
+ 'пометил',
+ 'пересмотрел',
+ 'передал'
+];
+const nouns2 = ['счет', 'аккаунт', 'пароль', 'кабинет'];
+const adjectives = [
+ 'идеальный',
+ 'прямой',
+ 'обратный',
+ 'наш',
+ 'постоянный',
+ 'великолепный',
+ 'исключительный',
+ 'личный',
+ 'ваш'
+];
+
+let counter = 0;
+
+export function randomInt(min, max) {
+ return Math.floor((max - min) * Math.random() + min);
+}
+
+function randFromList(list) {
+ return list[randomInt(0, list.length)];
+}
+
+const randomDate = () => {
+ const m = randomInt(1, 12);
+ let day = randomInt(1, 30);
+ if (m === 2) day = Math.min(28, day);
+ const month = [
+ 'янв',
+ 'фев',
+ 'мар',
+ 'апр',
+ 'май',
+ 'июн',
+ 'июл',
+ 'авг',
+ 'сен',
+ 'окт',
+ 'ноя',
+ 'дек'
+ ];
+ return `${String(day)} ${String(month[m - 1])}`;
+};
+
+const generateText = sender => {
+ const textContent = [
+ `${randFromList(hello)} ${randFromList(word1)} ${randFromList(firstName)} ${randFromList(
+ secondName
+ )}, глава компании ${sender.toUpperCase()}.`
+ ];
+ textContent.push(
+ `${randFromList(phrase1)} ${randFromList(adjectives)} ${randFromList(nouns1)} ${randFromList(
+ verbs
+ )} ${randFromList(adjectives)} ${randFromList(nouns2)}.`
+ );
+ return textContent;
+};
+
+export const generateNewLetter = () => {
+ counter++;
+ const id = counter;
+ const author = randFromList(companies);
+ const text = generateText(author);
+ const topic = randFromList(topics);
+ const date = randomDate();
+
+ return {
+ key: `id${id}`,
+ id: `id${id}`,
+ text,
+ author,
+ topic,
+ date,
+ isChecked: false,
+ isVisible: true
+ };
+};
diff --git a/src/app/structure/menu/menu.css b/src/app/structure/menu/menu.css
new file mode 100644
index 0000000..bafed00
--- /dev/null
+++ b/src/app/structure/menu/menu.css
@@ -0,0 +1,53 @@
+.menu {
+ width: 147px;
+ max-width: 170px;
+ margin-left: 22px;
+ float: left;
+}
+
+.menu__to-write {
+ width: 147px;
+ height: 32px;
+
+ border: none;
+ background-color: #6287bd;
+ border-radius: 3px;
+ color: #ffffff;
+ font-family: "'HelveticaNeue'", sans-serif;
+ font-size: 12px;
+}
+
+.menu__to-write:hover {
+ box-shadow: 2px 2px rgba(0, 0, 0, 0.6);
+}
+
+.menu__bar {
+ padding: 0;
+}
+
+.menu__action {
+ width: 147px;
+ height: 22px;
+ margin-top: 2px;
+ border-radius: 3px;
+ list-style: none;
+}
+
+.menu__text-ref {
+ display: block;
+ padding-left: 10px;
+ color: #555555;
+ font-family: "'HelveticaNeue'", sans-serif;
+ font-size: 11px;
+ font-weight: 500;
+ line-height: 22px;
+ text-decoration: none;
+}
+
+.menu__action:hover {
+ background-color: #cdd6e4;
+}
+
+.menu__text-ref:hover {
+ font-weight: 700;
+}
diff --git a/src/app/structure/menu/menu.jsx b/src/app/structure/menu/menu.jsx
new file mode 100644
index 0000000..7cc0737
--- /dev/null
+++ b/src/app/structure/menu/menu.jsx
@@ -0,0 +1,35 @@
+import React, { Component } from 'react';
+
+import './menu.css';
+
+const actions = [
+ { title: 'Входящие', fragment: 'inbox' },
+ { title: 'Отправленные', fragment: 'sent' },
+ { title: 'Удалённые', fragment: 'deleted' },
+ { title: 'Спам', fragment: 'spam' },
+ { title: 'Черновики', fragment: 'drafts' },
+ { title: 'Создать папку', fragment: 'createdir' }
+];
+
+export class Menu extends Component {
+ render() {
+ return (
+
+ );
+ }
+}