diff --git a/package-lock.json b/package-lock.json
index 937a670..a95836c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1216,6 +1216,11 @@
"loader-utils": "^1.1.0"
}
},
+ "@types/classnames": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.7.tgz",
+ "integrity": "sha512-rzOhiQ55WzAiFgXRtitP/ZUT8iVNyllEpylJ5zHzR4vArUvMB39GTk+Zon/uAM0JxEFAWnwsxC2gH8s+tZ3Myg=="
+ },
"@types/events": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
@@ -1233,6 +1238,19 @@
"@types/node": "*"
}
},
+ "@types/jest": {
+ "version": "24.0.12",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.12.tgz",
+ "integrity": "sha512-60sjqMhat7i7XntZckcSGV8iREJyXXI6yFHZkSZvCPUeOnEJ/VP1rU/WpEWQ56mvoh8NhC+sfKAuJRTyGtCOow==",
+ "requires": {
+ "@types/jest-diff": "*"
+ }
+ },
+ "@types/jest-diff": {
+ "version": "20.0.1",
+ "resolved": "https://registry.npmjs.org/@types/jest-diff/-/jest-diff-20.0.1.tgz",
+ "integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA=="
+ },
"@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -1246,10 +1264,14 @@
"dev": true
},
"@types/node": {
- "version": "11.13.5",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.5.tgz",
- "integrity": "sha512-/OMMBnjVtDuwX1tg2pkYVSqRIDSmNTnvVvmvP/2xiMAAWf4a5+JozrApCrO4WCAILmXVxfNoQ3E+0HJbNpFVGg==",
- "dev": true
+ "version": "11.13.8",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.8.tgz",
+ "integrity": "sha512-szA3x/3miL90ZJxUCzx9haNbK5/zmPieGraZEe4WI+3srN0eGLiT22NXeMHmyhNEopn+IrxqMc7wdVwvPl8meg=="
+ },
+ "@types/prop-types": {
+ "version": "15.7.1",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz",
+ "integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg=="
},
"@types/q": {
"version": "1.5.2",
@@ -1257,6 +1279,23 @@
"integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==",
"dev": true
},
+ "@types/react": {
+ "version": "16.8.15",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.15.tgz",
+ "integrity": "sha512-dMhzw1rWK+wwJWvPp5Pk12ksSrm/z/C/+lOQbMZ7YfDQYnJ02bc0wtg4EJD9qrFhuxFrf/ywNgwTboucobJqQg==",
+ "requires": {
+ "@types/prop-types": "*",
+ "csstype": "^2.2.0"
+ }
+ },
+ "@types/react-dom": {
+ "version": "16.8.4",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.8.4.tgz",
+ "integrity": "sha512-eIRpEW73DCzPIMaNBDP5pPIpK1KXyZwNgfxiVagb5iGiz6da+9A5hslSX6GAQKdO7SayVCS/Fr2kjqprgAvkfA==",
+ "requires": {
+ "@types/react": "*"
+ }
+ },
"@types/tapable": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.2.tgz",
@@ -4085,6 +4124,11 @@
}
}
},
+ "classnames": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
+ "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
+ },
"clean-css": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
@@ -4890,6 +4934,11 @@
"cssom": "0.3.x"
}
},
+ "csstype": {
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.4.tgz",
+ "integrity": "sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg=="
+ },
"currently-unhandled": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
@@ -16699,8 +16748,7 @@
"typescript": {
"version": "3.3.4000",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.4000.tgz",
- "integrity": "sha512-jjOcCZvpkl2+z7JFn0yBOoLQyLoIkNZAs/fYJkUG6VKy6zLPHJGfQJYFHzibB6GJaF/8QrcECtlQ5cpvRHSMEA==",
- "dev": true
+ "integrity": "sha512-jjOcCZvpkl2+z7JFn0yBOoLQyLoIkNZAs/fYJkUG6VKy6zLPHJGfQJYFHzibB6GJaF/8QrcECtlQ5cpvRHSMEA=="
},
"uglify-js": {
"version": "3.4.10",
diff --git a/package.json b/package.json
index 9ede333..e114765 100644
--- a/package.json
+++ b/package.json
@@ -9,8 +9,15 @@
"not op_mini all"
],
"dependencies": {
+ "@types/jest": "24.0.12",
+ "@types/node": "11.13.8",
+ "@types/react": "16.8.15",
+ "@types/react-dom": "16.8.4",
+ "@types/classnames": "2.2.7",
"react": "16.8.6",
- "react-dom": "16.8.6"
+ "react-dom": "16.8.6",
+ "typescript": "3.3.4000",
+ "classnames": "2.2.6"
},
"devDependencies": {
"@hellroot/eslint-config": "1.8.0",
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/LetterSmall/index.js b/src/app/LetterSmall/index.js
new file mode 100644
index 0000000..98d2e58
--- /dev/null
+++ b/src/app/LetterSmall/index.js
@@ -0,0 +1 @@
+export * from './letterSmall';
diff --git a/src/app/LetterSmall/letterSmall.module.css b/src/app/LetterSmall/letterSmall.module.css
new file mode 100644
index 0000000..d6ba3a5
--- /dev/null
+++ b/src/app/LetterSmall/letterSmall.module.css
@@ -0,0 +1,202 @@
+.letter {
+ width: 100%;
+ height: 37px;
+
+ border-right: solid 1px #e2e2e2;
+ border-bottom: solid 1px #e2e2e2;
+}
+
+.letter__animatedAddLetter {
+ animation-duration: 2s;
+ animation-name: add-new-letter;
+}
+
+.letter__animatedDeleteLetter {
+ animation-duration: 1s;
+ animation-name: delete-letter;
+}
+
+.letter__checkbox {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ padding: 2px;
+ margin-top: 11px;
+ margin-left: 20px;
+
+ border: solid 1px rgba(0, 0, 0, 0.15);
+ -webkit-appearance: none;
+ background-color: #ffffff;
+ border-radius: 3px;
+ outline: none;
+ vertical-align: top;
+}
+
+.letter__checkbox:checked {
+ display: inline-block;
+ background: #e2e2e2;
+ background-clip: content-box;
+}
+
+.letter__checkbox_dark {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ padding: 2px;
+ margin-top: 11px;
+ margin-left: 20px;
+
+ border: solid 1px #ffffff;
+ -webkit-appearance: none;
+ background-color: rgba(0, 0, 0, 0.15);
+ border-radius: 3px;
+ outline: none;
+ vertical-align: top;
+}
+
+.letter__checkbox_dark:checked {
+ display: inline-block;
+ background: #e2e2e2;
+ background-clip: content-box;
+}
+
+.letter__textSenderLetter_dark {
+ display: inline-block;
+ overflow: hidden;
+ width: 40%;
+ height: 15px;
+ margin-top: 12px;
+ margin-left: 10px;
+ color: #cccccc;
+ font-family: HelveticaNeue;
+ font-size: 13px;
+ text-overflow: ellipsis;
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+.letter__textLetter_dark {
+ display: inline-block;
+ overflow: hidden;
+ width: 10%;
+ height: 15px;
+ margin-top: 12px;
+ margin-left: 10px;
+ color: #cccccc;
+ font-family: HelveticaNeue;
+ font-size: 13px;
+ text-overflow: ellipsis;
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+.letter__data_dark {
+ width: 4%;
+ height: 15px;
+ margin-top: 11px;
+ margin-right: 20px;
+ color: #cccccc;
+ float: right;
+ font-family: HelveticaNeue;
+ font-size: 13px;
+ text-align: right;
+}
+
+.letter__delLine {
+ text-decoration: none;
+}
+
+.letter__yLogo {
+ display: inline-block;
+ width: 22px;
+ height: 22px;
+ margin-top: 7px;
+ margin-left: 7px;
+ background-color: red;
+ border-radius: 50%;
+ color: white;
+ text-align: center;
+}
+
+.letter__yLogoText {
+ margin-top: 4px;
+ font-family: HelveticaNeueLight;
+ font-size: 20px;
+}
+
+.letter_isBold {
+ font-weight: bold;
+}
+
+.letter__textSenderLetter {
+ display: inline-block;
+ overflow: hidden;
+ width: 40%;
+ height: 15px;
+ margin-top: 12px;
+ margin-left: 10px;
+ color: #000000;
+ font-family: HelveticaNeue;
+ font-size: 13px;
+ text-overflow: ellipsis;
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+.letter__textLetter {
+ display: inline-block;
+ overflow: hidden;
+ width: 10%;
+ height: 15px;
+ margin-top: 12px;
+ margin-left: 10px;
+ color: #000000;
+ font-family: HelveticaNeue;
+ font-size: 13px;
+ text-overflow: ellipsis;
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+.letter__markNewLetter {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ margin-top: 14px;
+ margin-left: 7px;
+ background-color: #6287bd;
+ border-radius: 50%;
+ vertical-align: top;
+}
+
+.letter__data {
+ width: 8%;
+ height: 15px;
+ margin-top: 7px;
+ margin-right: 10px;
+ color: #9b9b9b;
+ float: right;
+ font-family: HelveticaNeue;
+ font-size: 13px;
+ text-align: right;
+}
+
+@keyframes delete-letter {
+ from {
+ opacity: 100%;
+ }
+
+ to {
+ opacity: 0;
+ }
+}
+
+@keyframes add-new-letter {
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 100%;
+ }
+}
diff --git a/src/app/LetterSmall/letterSmall.tsx b/src/app/LetterSmall/letterSmall.tsx
new file mode 100644
index 0000000..6c1cd29
--- /dev/null
+++ b/src/app/LetterSmall/letterSmall.tsx
@@ -0,0 +1,66 @@
+import *as React from 'react';
+
+import styles from './letterSmall.module.css';
+import classnames from 'classnames';
+
+interface IProps {
+ isDark: boolean;
+ isSelected: boolean;
+ changeAnimation: boolean;
+ id: number;
+ deleteChosenLetter: (id :number) => void;
+ switchLetterCheckbox: (id: number) => void;
+ openLetter: (text: string[]) => void;
+ text: string[];
+ author: string;
+ subject: string;
+ date: string;
+}
+
+export class LetterSmall extends React.Component {
+ constructor(props: IProps) {
+ super(props);
+ this.props = props;
+ this.changeAnimation = this.changeAnimation.bind(this);
+ }
+
+ public readonly props: IProps;
+
+ changeAnimation() {
+ if (this.props.changeAnimation) {
+ this.props.deleteChosenLetter(this.props.id);
+ }
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/src/app/allLetters/allLetters.module.css b/src/app/allLetters/allLetters.module.css
new file mode 100644
index 0000000..b1edb05
--- /dev/null
+++ b/src/app/allLetters/allLetters.module.css
@@ -0,0 +1,4 @@
+.allLetters {
+ display: inline-block;
+ width: 100%;
+}
diff --git a/src/app/allLetters/allLetters.tsx b/src/app/allLetters/allLetters.tsx
new file mode 100644
index 0000000..b882527
--- /dev/null
+++ b/src/app/allLetters/allLetters.tsx
@@ -0,0 +1,48 @@
+import *as React from 'react';
+
+import styles from './allLetters.module.css';
+import { Letter } from '../letter';
+import {ILetter} from '../letterTypes/letterTypes';
+
+interface IProps {
+ create: boolean;
+ visibleLetters: ILetter[];
+ markedLetters: {[id: string]: boolean};
+ switchLetterCheckbox: (id: number) => void;
+ openLetter: (text: string[]) => void;
+ deleteChosenLetter: (id: number) => void;
+ isDark: boolean;
+}
+
+export class AllLetters extends React.Component {
+ constructor(props: IProps) {
+ super(props);
+ this.props = props;
+ }
+ public readonly props: IProps;
+
+ render() {
+ return (
+
+ {this.props.visibleLetters.map(letter => {
+ return (
+
+ );
+ })}
+
+ );
+ }
+}
diff --git a/src/app/allLetters/index.js b/src/app/allLetters/index.js
new file mode 100644
index 0000000..7e2dfac
--- /dev/null
+++ b/src/app/allLetters/index.js
@@ -0,0 +1 @@
+export * from './allLetters';
diff --git a/src/app/app.css b/src/app/app.css
deleted file mode 100644
index 1c4d511..0000000
--- a/src/app/app.css
+++ /dev/null
@@ -1,27 +0,0 @@
-.app {
- text-align: center;
-}
-
-.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);
-}
-
-.app-link {
- color: #61dafb;
-}
-
-@keyframes app-logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
diff --git a/src/app/app.jsx b/src/app/app.jsx
deleted file mode 100644
index f759eed..0000000
--- a/src/app/app.jsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import React, { Component } from 'react';
-
-import './app.css';
-
-export class App extends Component {
- render() {
- return (
-
- );
- }
-}
diff --git a/src/app/app.module.css b/src/app/app.module.css
new file mode 100644
index 0000000..5e68794
--- /dev/null
+++ b/src/app/app.module.css
@@ -0,0 +1,13 @@
+.app {
+ padding: 25px 3% 2%;
+}
+
+@font-face {
+ font-family: HelveticaNeue;
+ src: url(./txtStyle/HelveticaNeueCyr-Medium.otf);
+}
+
+@font-face {
+ font-family: HelveticaNeueLight;
+ src: url(./txtStyle/HelveticaNeueCyr-Light.otf);
+}
diff --git a/src/app/app.tsx b/src/app/app.tsx
new file mode 100644
index 0000000..c14e412
--- /dev/null
+++ b/src/app/app.tsx
@@ -0,0 +1,36 @@
+import *as React from 'react';
+
+import styles from './app.module.css';
+import { Header } from './header';
+import { MailInnerContent } from './mailInnerContent';
+
+interface IState {
+ isDark: boolean;
+}
+
+export class App extends React.Component {
+ public readonly state: IState;
+
+ constructor(props: {}) {
+ super(props);
+ this.state = {
+ isDark: false,
+ };
+ this.changeTheme = this.changeTheme.bind(this);
+ }
+
+ private changeTheme() {
+ this.setState((state: IState) => {
+ document.body.style.background = state.isDark ? '#e5eaf0' : 'black';
+ return { isDark: !state.isDark };
+ });
+ }
+
+ render() {
+ return (
+
+
+
+ );
+ }
+}
diff --git a/src/app/button/button.module.css b/src/app/button/button.module.css
new file mode 100644
index 0000000..59c9060
--- /dev/null
+++ b/src/app/button/button.module.css
@@ -0,0 +1,29 @@
+.button__textMenu {
+ width: 137px;
+ height: 13px;
+ padding-top: 4px;
+ padding-bottom: 4px;
+ padding-left: 10px;
+ margin-bottom: 8px;
+ margin-left: -10px;
+ color: #707070;
+ font-family: HelveticaNeue;
+ font-size: 11px;
+ line-height: 16px;
+ list-style-type: none;
+}
+
+.button__textMenu:hover {
+ background-color: #cdd6e4;
+ border-radius: 3px;
+ color: #555555;
+ font-weight: bold;
+}
+
+.button_unhighlight {
+ color: inherit;
+}
+
+.button__delLine {
+ text-decoration: none;
+}
diff --git a/src/app/button/button.tsx b/src/app/button/button.tsx
new file mode 100644
index 0000000..a4eaa17
--- /dev/null
+++ b/src/app/button/button.tsx
@@ -0,0 +1,26 @@
+import *as React from 'react';
+
+import styles from './button.module.css';
+import classnames from 'classnames';
+
+interface IProps {
+ name: string;
+}
+
+export class Button extends React.Component {
+ constructor(props: IProps) {
+ super(props);
+ this.props = props;
+ }
+ public readonly props: IProps;
+
+ render() {
+ return (
+
+
+ {this.props.name}
+
+
+ );
+ }
+}
diff --git a/src/app/button/index.js b/src/app/button/index.js
new file mode 100644
index 0000000..eaf5eea
--- /dev/null
+++ b/src/app/button/index.js
@@ -0,0 +1 @@
+export * from './button';
diff --git a/src/app/content/content.module.css b/src/app/content/content.module.css
new file mode 100644
index 0000000..091935e
--- /dev/null
+++ b/src/app/content/content.module.css
@@ -0,0 +1,22 @@
+.content {
+ display: inline-block;
+ width: 78%;
+ min-height: 600px;
+ margin-left: 3%;
+ background-color: #ffffff;
+ border-radius: 3px;
+ box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.34);
+ vertical-align: top;
+}
+
+.content_dark {
+ display: inline-block;
+ width: 78%;
+ min-height: 600px;
+ margin-left: 3%;
+ background-color: #101010;
+ border-radius: 3px;
+ box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.34);
+ color: inherit;
+ vertical-align: top;
+}
diff --git a/src/app/content/content.tsx b/src/app/content/content.tsx
new file mode 100644
index 0000000..f007e86
--- /dev/null
+++ b/src/app/content/content.tsx
@@ -0,0 +1,51 @@
+import *as React from 'react';
+
+import styles from './content.module.css';
+import { LettersMenu } from '../lettersMenu';
+import { LetterState } from '../lettersState';
+import { Footer } from '../footer';
+import { ILetter } from '../letterTypes/letterTypes';
+
+interface IProps {
+ create: boolean;
+ selectAll: boolean;
+ chooseAllLetters: () => void;
+ markLettersToDelete: () => void;
+ deleteChosenLetter: (id: number) => void;
+ visibleLetters: ILetter[];
+ markedLetters: {[id: string]: boolean};
+ switchLetterCheckbox: (id: number) => void;
+ isDark: boolean;
+ createNewLetter: () => void;
+}
+
+export class Content extends React.Component {
+ constructor(props: IProps) {
+ super(props);
+ this.props = props;
+ }
+
+ public readonly props: IProps;
+ render() {
+ return (
+
+
+
+
+
+ );
+ }
+}
diff --git a/src/app/content/index.js b/src/app/content/index.js
new file mode 100644
index 0000000..7b367d1
--- /dev/null
+++ b/src/app/content/index.js
@@ -0,0 +1 @@
+export * from './content';
diff --git a/src/app/footer/footer.module.css b/src/app/footer/footer.module.css
new file mode 100644
index 0000000..0484ee2
--- /dev/null
+++ b/src/app/footer/footer.module.css
@@ -0,0 +1,24 @@
+.footer {
+ width: 100%;
+ height: 37px;
+
+ border-top: solid 1px #e2e2e2;
+}
+
+.footerText__textEndline {
+ height: 12px;
+ margin-right: 45px;
+ color: #9b9b9b;
+ float: right;
+ font-family: HelveticaNeueLight;
+ font-size: 11px;
+ line-height: 40px;
+}
+
+.footerText_unhighlight {
+ color: inherit;
+}
+
+.footerText__delLine {
+ text-decoration: none;
+}
diff --git a/src/app/footer/footer.tsx b/src/app/footer/footer.tsx
new file mode 100644
index 0000000..535fd5a
--- /dev/null
+++ b/src/app/footer/footer.tsx
@@ -0,0 +1,16 @@
+import *as React from 'react';
+
+import styles from './footer.module.css';
+import classnames from 'classnames';
+
+export class Footer extends React.Component {
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/src/app/footer/index.js b/src/app/footer/index.js
new file mode 100644
index 0000000..a058eae
--- /dev/null
+++ b/src/app/footer/index.js
@@ -0,0 +1 @@
+export * from './footer';
diff --git a/src/app/header/header.module.css b/src/app/header/header.module.css
new file mode 100644
index 0000000..18bdefe
--- /dev/null
+++ b/src/app/header/header.module.css
@@ -0,0 +1,58 @@
+.header {
+ display: inline-block;
+ width: 100%;
+ min-width: 800px;
+ height: 5%;
+ margin-bottom: 12px;
+}
+
+.header__ypLogo {
+ display: inline-block;
+ width: 200px;
+ margin-left: 11px;
+ font-size: 170%;
+ vertical-align: text-bottom;
+}
+
+.header__burgerMenu {
+ display: inline-block;
+ margin-top: 7px;
+}
+
+.header__line {
+ width: 20px;
+ height: 3px;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ background-color: #000000;
+}
+
+.header__line_dark {
+ width: 20px;
+ height: 3px;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ background-color: #ffffff;
+}
+.header__button {
+ width: 80px;
+ height: 35px;
+ margin-bottom: 8px;
+
+ border: #6287bd;
+ background-color: #6287bd;
+ border-radius: 3px;
+ float: right;
+}
+
+.header__textWrite {
+ display: inline-block;
+ width: 56px;
+ height: 15px;
+ margin-top: 7px;
+ margin-bottom: 10px;
+ color: #ffffff;
+ font-family: HelveticaNeue;
+ font-size: 12px;
+ vertical-align: center;
+}
diff --git a/src/app/header/header.tsx b/src/app/header/header.tsx
new file mode 100644
index 0000000..f0517ec
--- /dev/null
+++ b/src/app/header/header.tsx
@@ -0,0 +1,38 @@
+import *as React from 'react';
+
+import styles from './header.module.css';
+import { Search } from '../search';
+import logo from '../images/header-logo.svg';
+import darkLogo from '../images/header-logo-dark.png';
+
+interface IProps {
+ isClearInput: boolean;
+ search: (text: string) => void;
+ changeTheme: () => void;
+ isDark: boolean;
+}
+
+export class Header extends React.Component {
+ constructor(props: IProps) {
+ super(props);
+ this.props = props;
+ }
+ public readonly props: IProps;
+
+ render() {
+ return (
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/src/app/header/index.js b/src/app/header/index.js
new file mode 100644
index 0000000..677ca79
--- /dev/null
+++ b/src/app/header/index.js
@@ -0,0 +1 @@
+export * from './header';
diff --git a/src/app/images/cross.png b/src/app/images/cross.png
new file mode 100644
index 0000000..7765268
Binary files /dev/null and b/src/app/images/cross.png differ
diff --git a/src/app/images/header-logo-dark.png b/src/app/images/header-logo-dark.png
new file mode 100644
index 0000000..d2b1bc7
Binary files /dev/null and b/src/app/images/header-logo-dark.png differ
diff --git a/src/app/images/header-logo.svg b/src/app/images/header-logo.svg
new file mode 100644
index 0000000..db23b2d
--- /dev/null
+++ b/src/app/images/header-logo.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/src/app/images/logo.jpg b/src/app/images/logo.jpg
new file mode 100644
index 0000000..8743b99
Binary files /dev/null and b/src/app/images/logo.jpg differ
diff --git a/src/app/leftMenu/index.js b/src/app/leftMenu/index.js
new file mode 100644
index 0000000..45e2691
--- /dev/null
+++ b/src/app/leftMenu/index.js
@@ -0,0 +1 @@
+export * from './leftMenu';
diff --git a/src/app/leftMenu/leftMenu.module.css b/src/app/leftMenu/leftMenu.module.css
new file mode 100644
index 0000000..d8f6caa
--- /dev/null
+++ b/src/app/leftMenu/leftMenu.module.css
@@ -0,0 +1,28 @@
+.leftMenu {
+ display: inline-block;
+ width: 147px;
+ height: 100%;
+ vertical-align: top;
+}
+
+.leftMenu__button {
+ width: 147px;
+ height: 32px;
+ margin-bottom: 8px;
+
+ border: #6287bd;
+ background-color: #6287bd;
+ border-radius: 3px;
+}
+
+.leftMenu__textWrite {
+ display: inline-block;
+ width: 56px;
+ height: 15px;
+ margin-top: 7px;
+ margin-bottom: 10px;
+ color: #ffffff;
+ font-family: HelveticaNeue;
+ font-size: 12px;
+ vertical-align: center;
+}
diff --git a/src/app/leftMenu/leftMenu.tsx b/src/app/leftMenu/leftMenu.tsx
new file mode 100644
index 0000000..f857a2e
--- /dev/null
+++ b/src/app/leftMenu/leftMenu.tsx
@@ -0,0 +1,27 @@
+import *as React from 'react';
+
+import styles from './leftMenu.module.css';
+import { MailMenu } from '../mailMenu';
+
+interface IProps {
+ newMail: () => void;
+}
+
+export class LeftMenu extends React.Component {
+ constructor(props: IProps) {
+ super(props);
+ this.props = props;
+ }
+ public readonly props: IProps;
+
+ render() {
+ return (
+
+
+
+
+ );
+ }
+}
diff --git a/src/app/letter/index.js b/src/app/letter/index.js
new file mode 100644
index 0000000..c37f80d
--- /dev/null
+++ b/src/app/letter/index.js
@@ -0,0 +1 @@
+export * from './letter';
diff --git a/src/app/letter/letter.module.css b/src/app/letter/letter.module.css
new file mode 100644
index 0000000..2979b15
--- /dev/null
+++ b/src/app/letter/letter.module.css
@@ -0,0 +1,201 @@
+.letter {
+ width: 100%;
+ height: 37px;
+
+ border-bottom: solid 1px #e2e2e2;
+}
+
+.letter__animatedAddLetter {
+ animation-duration: 2s;
+ animation-name: add-new-letter;
+}
+
+.letter__animatedDeleteLetter {
+ animation-duration: 1s;
+ animation-name: delete-letter;
+}
+
+.letter__checkbox {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ padding: 2px;
+ margin-top: 11px;
+ margin-left: 20px;
+
+ border: solid 1px rgba(0, 0, 0, 0.15);
+ -webkit-appearance: none;
+ background-color: #ffffff;
+ border-radius: 3px;
+ outline: none;
+ vertical-align: top;
+}
+
+.letter__checkbox:checked {
+ display: inline-block;
+ background: #e2e2e2;
+ background-clip: content-box;
+}
+
+.letter__checkbox_dark {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ padding: 2px;
+ margin-top: 11px;
+ margin-left: 20px;
+
+ border: solid 1px #ffffff;
+ -webkit-appearance: none;
+ background-color: rgba(0, 0, 0, 0.15);
+ border-radius: 3px;
+ outline: none;
+ vertical-align: top;
+}
+
+.letter__checkbox_dark:checked {
+ display: inline-block;
+ background: #e2e2e2;
+ background-clip: content-box;
+}
+
+.letter__textSenderLetter_dark {
+ display: inline-block;
+ overflow: hidden;
+ width: 20%;
+ height: 15px;
+ margin-top: 12px;
+ margin-left: 10px;
+ color: #cccccc;
+ font-family: HelveticaNeue;
+ font-size: 13px;
+ text-overflow: ellipsis;
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+.letter__textLetter_dark {
+ display: inline-block;
+ overflow: hidden;
+ width: 40%;
+ height: 15px;
+ margin-top: 12px;
+ margin-left: 10px;
+ color: #cccccc;
+ font-family: HelveticaNeue;
+ font-size: 13px;
+ text-overflow: ellipsis;
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+.letter__data_dark {
+ width: 8%;
+ height: 15px;
+ margin-top: 11px;
+ margin-right: 20px;
+ color: #cccccc;
+ float: right;
+ font-family: HelveticaNeue;
+ font-size: 13px;
+ text-align: right;
+}
+
+.letter__delLine {
+ text-decoration: none;
+}
+
+.letter__yLogo {
+ display: inline-block;
+ width: 22px;
+ height: 22px;
+ margin-top: 7px;
+ margin-left: 20px;
+ background-color: red;
+ border-radius: 50%;
+ color: white;
+ text-align: center;
+}
+
+.letter__yLogoText {
+ margin-top: 4px;
+ font-family: HelveticaNeueLight;
+ font-size: 20px;
+}
+
+.letter_isBold {
+ font-weight: bold;
+}
+
+.letter__textSenderLetter {
+ display: inline-block;
+ overflow: hidden;
+ width: 20%;
+ height: 15px;
+ margin-top: 12px;
+ margin-left: 10px;
+ color: #000000;
+ font-family: HelveticaNeue;
+ font-size: 13px;
+ text-overflow: ellipsis;
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+.letter__textLetter {
+ display: inline-block;
+ overflow: hidden;
+ width: 40%;
+ height: 15px;
+ margin-top: 12px;
+ margin-left: 10px;
+ color: #000000;
+ font-family: HelveticaNeue;
+ font-size: 13px;
+ text-overflow: ellipsis;
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+.letter__markNewLetter {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ margin-top: 14px;
+ margin-left: 20px;
+ background-color: #6287bd;
+ border-radius: 50%;
+ vertical-align: top;
+}
+
+.letter__data {
+ width: 8%;
+ height: 15px;
+ margin-top: 11px;
+ margin-right: 20px;
+ color: #9b9b9b;
+ float: right;
+ font-family: HelveticaNeue;
+ font-size: 13px;
+ text-align: right;
+}
+
+@keyframes delete-letter {
+ from {
+ opacity: 100%;
+ }
+
+ to {
+ opacity: 0;
+ }
+}
+
+@keyframes add-new-letter {
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 100%;
+ }
+}
diff --git a/src/app/letter/letter.tsx b/src/app/letter/letter.tsx
new file mode 100644
index 0000000..a5c053e
--- /dev/null
+++ b/src/app/letter/letter.tsx
@@ -0,0 +1,66 @@
+import *as React from 'react';
+
+import styles from './letter.module.css';
+import classnames from 'classnames';
+
+interface IProps {
+ isDark: boolean;
+ isSelected: boolean;
+ changeAnimation: boolean;
+ id: number;
+ deleteChosenLetter: (id :number) => void;
+ switchLetterCheckbox: (id: number) => void;
+ openLetter: (text: string[]) => void;
+ text: string[];
+ author: string;
+ subject: string;
+ date: string;
+}
+
+export class Letter extends React.Component {
+ constructor(props: IProps) {
+ super(props);
+ this.props = props;
+ this.changeAnimation = this.changeAnimation.bind(this);
+ }
+
+ public readonly props: IProps;
+
+ changeAnimation() {
+ if (this.props.changeAnimation) {
+ this.props.deleteChosenLetter(this.props.id);
+ }
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/src/app/letterTypes/letterTypes.ts b/src/app/letterTypes/letterTypes.ts
new file mode 100644
index 0000000..af8a243
--- /dev/null
+++ b/src/app/letterTypes/letterTypes.ts
@@ -0,0 +1,9 @@
+export interface ILetter {
+ id: number;
+ author: string;
+ subject: string;
+ text: string[];
+ date: string;
+ changeAnimation: boolean;
+ isSelected: boolean;
+}
diff --git a/src/app/lettersMenu/index.js b/src/app/lettersMenu/index.js
new file mode 100644
index 0000000..9dd0de6
--- /dev/null
+++ b/src/app/lettersMenu/index.js
@@ -0,0 +1 @@
+export * from './lettersMenu';
diff --git a/src/app/lettersMenu/lettersMenu.module.css b/src/app/lettersMenu/lettersMenu.module.css
new file mode 100644
index 0000000..0dba425
--- /dev/null
+++ b/src/app/lettersMenu/lettersMenu.module.css
@@ -0,0 +1,77 @@
+.lettersMenu {
+ width: 100%;
+ height: 37px;
+ padding: 0;
+ margin: 0;
+
+ border-bottom: solid 1px #e2e2e2;
+}
+
+.lettersMenu__checkbox {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ padding: 2px;
+ margin-top: 11px;
+ margin-left: 20px;
+
+ border: solid 1px rgba(0, 0, 0, 0.15);
+ -webkit-appearance: none;
+ background-color: #ffffff;
+ border-radius: 3px;
+ outline: none;
+ vertical-align: top;
+}
+
+.lettersMenu__checkbox:checked {
+ display: inline-block;
+ background: #e2e2e2;
+ background-clip: content-box;
+}
+
+.lettersMenu__checkbox_dark {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ padding: 2px;
+ margin-top: 11px;
+ margin-left: 20px;
+
+ border: solid 1px #ffffff;
+ -webkit-appearance: none;
+ background-color: rgba(0, 0, 0, 0.15);
+ border-radius: 3px;
+ outline: none;
+ vertical-align: top;
+}
+
+.lettersMenu__checkbox_dark:checked {
+ display: inline-block;
+ background: #e2e2e2;
+ background-clip: content-box;
+}
+
+.lettersMenu__horizontalPosition {
+ display: inline;
+ list-style-type: none;
+}
+
+.lettersMenu__button__textTitle {
+ display: inline-block;
+ height: 16px;
+ margin-top: 11px;
+ margin-left: 25px;
+
+ border: none;
+ background: none;
+ color: #cccccc;
+ font-family: HelveticaNeue;
+ font-size: 13px;
+ line-height: 20px;
+ outline: none;
+ vertical-align: top;
+}
+
+.lettersMenu__button__delLine {
+ text-decoration: none;
+}
diff --git a/src/app/lettersMenu/lettersMenu.tsx b/src/app/lettersMenu/lettersMenu.tsx
new file mode 100644
index 0000000..23323e8
--- /dev/null
+++ b/src/app/lettersMenu/lettersMenu.tsx
@@ -0,0 +1,69 @@
+import *as React from 'react';
+
+import styles from './lettersMenu.module.css';
+import classnames from 'classnames';
+
+interface IProps {
+ selectAll: boolean;
+ chooseAllLetters: () => void;
+ createNewLetter: () => void;
+ markLettersToDelete: () => void;
+ isDark: boolean;
+}
+export class LettersMenu extends React.Component {
+ constructor(props: IProps) {
+ super(props);
+ this.props = props;
+ }
+ public readonly props: IProps;
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/src/app/lettersState/index.js b/src/app/lettersState/index.js
new file mode 100644
index 0000000..32f343b
--- /dev/null
+++ b/src/app/lettersState/index.js
@@ -0,0 +1 @@
+export * from './letterState';
diff --git a/src/app/lettersState/letterState.module.css b/src/app/lettersState/letterState.module.css
new file mode 100644
index 0000000..3a0b05b
--- /dev/null
+++ b/src/app/lettersState/letterState.module.css
@@ -0,0 +1,32 @@
+.letterState {
+ width: 100%;
+ min-height: 524px;
+}
+
+.letterState_show:target {
+ display: inline-block;
+}
+
+.search__textSearch {
+ width: 90%;
+ height: 100%;
+ padding-left: 10px;
+
+ border: none;
+ -webkit-appearance: none;
+ background: none;
+ color: #000000;
+ font-size: 15px;
+ outline: none;
+}
+
+.search {
+ display: inline-block;
+ width: 40%;
+ height: 32px;
+ margin-left: 14%;
+ background-color: #ffffff;
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);
+ opacity: 0.5;
+ vertical-align: text-bottom;
+}
diff --git a/src/app/lettersState/letterState.tsx b/src/app/lettersState/letterState.tsx
new file mode 100644
index 0000000..2e84060
--- /dev/null
+++ b/src/app/lettersState/letterState.tsx
@@ -0,0 +1,88 @@
+import *as React from 'react';
+
+import classnames from 'classnames';
+import styles from './letterState.module.css';
+import { OpenLetter } from '../openLetter';
+import { AllLetters } from '../allLetters';
+import { ILetter } from '../letterTypes/letterTypes';
+import cross from '../images/cross.png';
+
+interface IProps {
+ create: boolean;
+ deleteChosenLetter: (id: number) => void;
+ visibleLetters: ILetter[];
+ markedLetters: { [id: string]: boolean };
+ switchLetterCheckbox: (id: number) => void;
+ isDark: boolean;
+}
+
+interface IState {
+ openLetter: boolean;
+ contentLetter: string[];
+}
+
+export class LetterState extends React.Component {
+ constructor(props: IProps) {
+ super(props);
+ this.props = props;
+ this.state = {
+ openLetter: false,
+ contentLetter: []
+ };
+ this.openLetter = this.openLetter.bind(this);
+ this.closeLetter = this.closeLetter.bind(this);
+ }
+
+ public readonly props: IProps;
+ public readonly state: IState;
+
+ openLetter(text: string[]) {
+ this.setState({
+ openLetter: true,
+ contentLetter: text
+ });
+ }
+
+ closeLetter() {
+ this.setState({
+ openLetter: false
+ });
+ }
+
+ render() {
+ return this.props.create ? (
+
+ ) : (this.state.openLetter ? (
+
+
+
+ ) : (
+
+ ));
+ }
+}
diff --git a/src/app/mailInnerContent/index.js b/src/app/mailInnerContent/index.js
new file mode 100644
index 0000000..1babe3c
--- /dev/null
+++ b/src/app/mailInnerContent/index.js
@@ -0,0 +1 @@
+export * from './mailInnerContent';
diff --git a/src/app/mailInnerContent/mailInnerContent.module.css b/src/app/mailInnerContent/mailInnerContent.module.css
new file mode 100644
index 0000000..156ad4a
--- /dev/null
+++ b/src/app/mailInnerContent/mailInnerContent.module.css
@@ -0,0 +1,7 @@
+.mailInnerContent {
+ display: inline-block;
+ width: 100%;
+ min-width: 800px;
+ height: 90%;
+ padding-top: 13px;
+}
diff --git a/src/app/mailInnerContent/mailInnerContent.tsx b/src/app/mailInnerContent/mailInnerContent.tsx
new file mode 100644
index 0000000..8ace356
--- /dev/null
+++ b/src/app/mailInnerContent/mailInnerContent.tsx
@@ -0,0 +1,246 @@
+import *as React from 'react';
+
+import styles from './mailInnerContent.module.css';
+import { LeftMenu } from '../leftMenu';
+import { Content } from '../content';
+import {
+ generateDate,
+ generateName,
+ generateContent,
+ generateRandomCount
+} from './scripts/letterGeneratorUtils';
+import { ILetter } from '../letterTypes/letterTypes';
+import { Header } from '../header/header';
+
+interface IState {
+ create: boolean;
+ isClearInput: boolean;
+ counter: number;
+ letters: ILetter[];
+ visibleLetters: ILetter[];
+ selectAll: boolean;
+ markedLetters: { [id: string]: boolean };
+ text: string;
+}
+
+interface IProps {
+ changeTheme: () => void;
+ isDark: boolean;
+}
+
+const MAX_COUNT = 30;
+
+export class MailInnerContent extends React.Component {
+ public readonly state: IState;
+ public readonly props: IProps;
+
+ static async generateLetter() {
+ const author = generateName();
+ const text = await generateContent();
+ const subject = text[0].substr(0, 45);
+ const date = generateDate();
+ return { author, text, subject, date };
+ }
+
+ constructor(props: IProps) {
+ super(props);
+ this.props = props;
+ this.state = {
+ create: false,
+ isClearInput: false,
+ text: '',
+ counter: 0,
+ letters: [],
+ visibleLetters: [],
+ selectAll: false,
+ markedLetters: {}
+ };
+ this.search = this.search.bind(this);
+ this.deleteChosenLetter = this.deleteChosenLetter.bind(this);
+ this.markLettersToDelete = this.markLettersToDelete.bind(this);
+ this.switchLetterCheckbox = this.switchLetterCheckbox.bind(this);
+ this.chooseAllLetters = this.chooseAllLetters.bind(this);
+ this.newMail = this.newMail.bind(this);
+ this.GenerateNewLetter();
+ this.createNewLetter = this.createNewLetter.bind(this);
+ }
+
+ createNewLetter() {
+ console.log(this.state.create);
+ this.setState((state: IState) => {
+ return {
+ create: !state.create
+ };
+ });
+ }
+
+ search(text: string) {
+ console.log(this.state.isClearInput);
+ this.setState(() => {
+ return {
+ text: text
+ }
+ });
+ const tmpLetters: ILetter[] = [];
+ const tmp = this.state.letters;
+ for (let i = 0; i < tmp.length; i++) {
+ if (i < MAX_COUNT) {
+ tmpLetters.push(tmp[i]);
+ }
+ }
+ if (text == '') {
+ this.setState(() => {
+ return { visibleLetters: tmpLetters };
+ });
+ } else {
+ let contentVisibleLetters = tmpLetters.filter(letter => letter.text[0].search(text) !== -1);
+ let authorVisibleLetters = tmpLetters.filter(letter => letter.author.search(text) !== -1);
+ if (authorVisibleLetters !== this.state.visibleLetters && authorVisibleLetters.length !== 0) {
+ this.setState(() => {
+ return { visibleLetters: authorVisibleLetters };
+ });
+ } else if (contentVisibleLetters !== this.state.visibleLetters) {
+ this.setState(() => {
+ return { visibleLetters: contentVisibleLetters };
+ });
+ }
+ }
+ }
+
+ deleteChosenLetter(id: number) {
+ let count = 0;
+ const tmpVisibleLetters: ILetter[] = [];
+ const tmpLetters = this.state.letters.filter(letter => letter.id !== id);
+ tmpLetters.forEach(letter => {
+ const tmp = letter;
+ if (MAX_COUNT > count) {
+ tmpVisibleLetters.push(tmp);
+ count++;
+ }
+ });
+ this.setState((state: IState) => {
+ return { isClearInput: false, letters: tmpLetters, visibleLetters: tmpVisibleLetters };
+ });
+ }
+
+ chooseAllLetters() {
+ const tmpVisibleLetters = this.state.visibleLetters;
+ const newMarkedLetters = this.state.markedLetters;
+ for (let i = 0; i < tmpVisibleLetters.length; i++) {
+ newMarkedLetters[tmpVisibleLetters[i].id] = !this.state.selectAll;
+ }
+ this.setState((state: IState) => {
+ return {
+ visibleLetters: tmpVisibleLetters,
+ selectAll: !state.selectAll,
+ markedLetters: newMarkedLetters
+ };
+ });
+ }
+
+ async newMail() {
+ const { author, text, subject, date } = await MailInnerContent.generateLetter();
+ const newMarkedLetters = this.state.markedLetters;
+ const id: number = this.state.counter;
+ this.setState((state: IState) => {
+ return { counter: state.counter + 1 };
+ });
+ newMarkedLetters[id] = false;
+ const tmpLetters = this.state.letters;
+ // const tmpVisibleLetters: ILetter[] = [];
+ const letter = {
+ id,
+ author,
+ subject,
+ text,
+ date,
+ changeAnimation: false,
+ isSelected: false
+ };
+ // tmpVisibleLetters.push(letter);
+ // for (let i = 0; i < tmpLetters.length; i++) {
+ // if (i < MAX_COUNT - 1) {
+ // tmpVisibleLetters.push(tmpLetters[i]);
+ // }
+ // }
+ this.setState((state: IState) => {
+ return {
+ //visibleLetters: tmpVisibleLetters,
+ letters: [letter].concat(state.letters),
+ markedLetters: newMarkedLetters
+ };
+ });
+ this.search(this.state.text);
+ }
+
+ sleep(ms: number) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+ }
+
+ async GenerateNewLetter() {
+ const fiveMinute = 300000;
+ const minTime = 10;
+ const maxTime = 600000;
+ let previous = 300000;
+ await this.newMail();
+ previous = Math.max(fiveMinute - previous, generateRandomCount(minTime, maxTime));
+ await this.sleep(previous);
+ this.GenerateNewLetter();
+ }
+
+ markLettersToDelete() {
+ const tmpLetters = this.state.letters;
+ const tmpVisibleLetters = this.state.visibleLetters;
+ //console.log(tmpVisibleLetters);
+ //console.log(tmpLetters);
+ let f = false;
+ for (let i = 0; i < tmpVisibleLetters.length; i++) {
+ if (this.state.markedLetters[tmpVisibleLetters[i].id]) {
+ for (let j = 0; j < tmpLetters.length; j++) {
+ if (tmpLetters[j] == tmpVisibleLetters[i]){
+ f = true;
+ tmpVisibleLetters[i].changeAnimation = true;
+ tmpLetters[j].changeAnimation = true;
+ }
+ }
+ }
+ }
+ this.setState(() => {
+ return {
+ isClearInput: f,
+ visibleLetters: tmpVisibleLetters,
+ letters: tmpLetters,
+ selectAll: false
+ };
+ });
+ }
+
+ switchLetterCheckbox(id: number) {
+ const newMarkedLetters = this.state.markedLetters;
+ newMarkedLetters[id] = !newMarkedLetters[id];
+ this.setState(() => {
+ return { markedLetters: newMarkedLetters };
+ });
+ }
+
+ render() {
+ return (
+
+
+ );
+ }
+}
diff --git a/src/app/mailInnerContent/scripts/letterGeneratorUtils.js b/src/app/mailInnerContent/scripts/letterGeneratorUtils.js
new file mode 100644
index 0000000..2d2f0ae
--- /dev/null
+++ b/src/app/mailInnerContent/scripts/letterGeneratorUtils.js
@@ -0,0 +1,95 @@
+const months = ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'];
+
+const names = [
+ 'Фотин',
+ 'Евтихий',
+ 'Азарий',
+ 'Фетис',
+ 'Полиевкт',
+ 'Борислав',
+ 'Кассиан',
+ 'Юст',
+ 'Мартьян',
+ 'Капитон',
+ 'Никандр',
+ 'Эрнест',
+ 'Петроний',
+ 'Иезекииль',
+ 'Харитон',
+ 'Севастиан',
+ 'Орест',
+ 'Вит',
+ 'Василий',
+ 'Гордей',
+ 'Максим',
+ 'Павлин',
+ 'Захар',
+ 'Владилен',
+ 'Наум',
+ 'Алипий',
+ 'Меркурий',
+ 'Феоктист',
+ 'Овдоким',
+ 'Феофил'
+];
+
+const surnames = [
+ 'Чашников',
+ 'Березников',
+ 'Руликовский',
+ 'Ляпишев',
+ 'Оффенберг',
+ 'Шипов',
+ 'Арнаутов',
+ 'Машковцев',
+ 'Столыпин',
+ 'Шереметьев',
+ 'Яворский',
+ 'Рындин',
+ 'Лонгинов',
+ 'Ададуров',
+ 'Нечаев',
+ 'Габаев',
+ 'Маткевич',
+ 'Маковский',
+ 'Юрасовский',
+ 'Ващенко',
+ 'Кобылин',
+ 'Карандеев',
+ 'Золотарёв',
+ 'Голицын',
+ 'Игнатьев',
+ 'Байчуров',
+ 'Бурдуков',
+ 'Болтенков',
+ 'Михеев',
+ 'Храпов'
+];
+
+export const generateRandomCount = (from, to) => {
+ return Math.floor(Math.random() * (to - from) + from);
+};
+
+const getRandomObj = (array) => {
+ return array[generateRandomCount(0, array.length)];
+};
+
+export const generateName = () => {
+ const name = getRandomObj(names);
+ const surname = getRandomObj(surnames);
+ return `${name} ${surname}`;
+};
+
+export const generateContent = async () => {
+ const paragraphsCount = generateRandomCount(1, 2);
+
+ const text = await fetch(
+ `https://baconipsum.com/api/?type=meat&formaat=json¶s=${paragraphsCount}`
+ );
+ return text.json();
+};
+
+export const generateDate = () => {
+ const date = new Date();
+ return `${date.getDate()} ${months[date.getMonth()]}`;
+};
diff --git a/src/app/mailMenu/index.js b/src/app/mailMenu/index.js
new file mode 100644
index 0000000..7451256
--- /dev/null
+++ b/src/app/mailMenu/index.js
@@ -0,0 +1 @@
+export * from './mailMenu';
diff --git a/src/app/mailMenu/mailMenu.module.css b/src/app/mailMenu/mailMenu.module.css
new file mode 100644
index 0000000..0a08017
--- /dev/null
+++ b/src/app/mailMenu/mailMenu.module.css
@@ -0,0 +1,5 @@
+.mailMenu__actionsBlock {
+ width: 100%;
+ margin-top: 0;
+ margin-left: -30px;
+}
diff --git a/src/app/mailMenu/mailMenu.tsx b/src/app/mailMenu/mailMenu.tsx
new file mode 100644
index 0000000..a808eb2
--- /dev/null
+++ b/src/app/mailMenu/mailMenu.tsx
@@ -0,0 +1,19 @@
+import *as React from 'react';
+
+import styles from './mailMenu.module.css';
+import {Button} from '../button';
+
+export class MailMenu extends React.Component {
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/src/app/openLetter/index.js b/src/app/openLetter/index.js
new file mode 100644
index 0000000..3406e12
--- /dev/null
+++ b/src/app/openLetter/index.js
@@ -0,0 +1 @@
+export * from './openLetter';
diff --git a/src/app/openLetter/openLetter.module.css b/src/app/openLetter/openLetter.module.css
new file mode 100644
index 0000000..75c4932
--- /dev/null
+++ b/src/app/openLetter/openLetter.module.css
@@ -0,0 +1,48 @@
+.openLetter__close {
+ margin-top: 10px;
+ margin-right: 10px;
+ float: right;
+}
+
+.allLetters {
+ display: inline-block;
+ width: 40%;
+}
+
+.width {
+ width: 60%;
+ float: right;
+}
+
+.openLetter__delLine {
+ text-decoration: none;
+}
+
+.openLetter__cross {
+ width: 15px;
+ height: 15px;
+ margin-top: 20px;
+ margin-right: 10px;
+ float: right;
+ opacity: 0.15;
+}
+
+.openLetter__textLetter {
+ margin: 30px;
+}
+
+.openLetter__cross_dark {
+ width: 20px;
+ height: 20px;
+ margin-top: -8px;
+ margin-right: 10px;
+ background-color: #cccccc;
+ border-radius: 50%;
+ float: right;
+ opacity: 0.15;
+}
+
+.openLetter__textLetter_dark {
+ margin: 30px;
+ color: #cccccc;
+}
diff --git a/src/app/openLetter/openLetter.tsx b/src/app/openLetter/openLetter.tsx
new file mode 100644
index 0000000..f85385e
--- /dev/null
+++ b/src/app/openLetter/openLetter.tsx
@@ -0,0 +1,64 @@
+import *as React from 'react';
+
+import styles from './openLetter.module.css';
+import cross from '../images/cross.png';
+import classnames from 'classnames';
+import { ILetter } from '../letterTypes/letterTypes';
+import { LetterSmall } from '../LetterSmall/letterSmall';
+
+interface IProps {
+ markedLetters: { [id: string]: boolean };
+ switchLetterCheckbox: (id: number) => void;
+ openLetter: (text: string[]) => void;
+ deleteChosenLetter: (id: number) => void;
+ visibleLetters: ILetter[];
+ contentLetter: string[];
+ closeLetter: () => void;
+ isDark: boolean;
+}
+
+export class OpenLetter extends React.Component {
+ constructor(props: IProps) {
+ super(props);
+ this.props = props;
+ }
+
+ public readonly props: IProps;
+
+ render() {
+ return (
+
+
+ {this.props.visibleLetters.map(letter => {
+ return (
+
+ );
+ })}
+
+
+
+
+
+
{this.props.contentLetter.map((paragraph) => {
+ return
{paragraph}
;
+ })}
+
+
+ );
+ }
+}
diff --git a/src/app/search/index.js b/src/app/search/index.js
new file mode 100644
index 0000000..5a2bdeb
--- /dev/null
+++ b/src/app/search/index.js
@@ -0,0 +1 @@
+export * from './search';
diff --git a/src/app/search/search.module.css b/src/app/search/search.module.css
new file mode 100644
index 0000000..7d55b6a
--- /dev/null
+++ b/src/app/search/search.module.css
@@ -0,0 +1,32 @@
+.search {
+ display: inline-block;
+ width: 40%;
+ height: 32px;
+ margin-left: 14%;
+ background-color: #ffffff;
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);
+ opacity: 0.5;
+ vertical-align: text-bottom;
+}
+
+.search__textSearch {
+ width: 90%;
+ height: 100%;
+ padding-left: 10px;
+
+ border: none;
+ -webkit-appearance: none;
+ background: none;
+ color: #000000;
+ font-size: 15px;
+ outline: none;
+}
+
+.search__cross {
+ width: 9px;
+ height: 9px;
+ margin-top: 12px;
+ margin-right: 10px;
+ float: right;
+ opacity: 0.15;
+}
diff --git a/src/app/search/search.tsx b/src/app/search/search.tsx
new file mode 100644
index 0000000..5d59da2
--- /dev/null
+++ b/src/app/search/search.tsx
@@ -0,0 +1,35 @@
+import *as React from 'react';
+
+import styles from './search.module.css';
+import cross from '../images/cross.png';
+
+interface IProps {
+ isClearInput: boolean;
+ search: (text: string) => void;
+}
+
+export class Search extends React.Component {
+ public constructor(props: IProps) {
+ super(props);
+ this.props = props;
+ }
+
+ public readonly props: IProps;
+
+ render() {
+ return this.props.isClearInput ? (
+
+
this.props.search('')}/>
+

+
+ ) : (
+
+
this.props.search(text.target.value)}/>
+

+
+ );
+ }
+}
diff --git a/src/app/txtStyle/HelveticaNeueCyr-Light.otf b/src/app/txtStyle/HelveticaNeueCyr-Light.otf
new file mode 100644
index 0000000..7ced49a
Binary files /dev/null and b/src/app/txtStyle/HelveticaNeueCyr-Light.otf differ
diff --git a/src/app/txtStyle/HelveticaNeueCyr-Medium.otf b/src/app/txtStyle/HelveticaNeueCyr-Medium.otf
new file mode 100644
index 0000000..a2cde16
Binary files /dev/null and b/src/app/txtStyle/HelveticaNeueCyr-Medium.otf differ
diff --git a/src/app/txtStyle/YandexSansDisplay-Thin.ttf b/src/app/txtStyle/YandexSansDisplay-Thin.ttf
new file mode 100644
index 0000000..3b8e196
Binary files /dev/null and b/src/app/txtStyle/YandexSansDisplay-Thin.ttf differ
diff --git a/src/index.css b/src/index.css
index 2b6e525..74897da 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1,10 +1,5 @@
body {
- padding: 0;
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
- 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
+ background-color: #e5eaf0;
}
code {
diff --git a/src/index.jsx b/src/index.tsx
similarity index 62%
rename from src/index.jsx
rename to src/index.tsx
index ffc72ee..4b7c423 100644
--- a/src/index.jsx
+++ b/src/index.tsx
@@ -1,5 +1,5 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
+import *as React from 'react';
+import *as ReactDOM from 'react-dom';
import { App } from './app';
diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts
new file mode 100644
index 0000000..6431bc5
--- /dev/null
+++ b/src/react-app-env.d.ts
@@ -0,0 +1 @@
+///