26 Commits 764932c53a ... 42225dafc0

Autor SHA1 Nachricht Datum
  sveta 42225dafc0 end vor 5 Jahren
  sveta 028624f45b Merge Sveta vor 5 Jahren
  sveta 51acd675b4 bred vor 5 Jahren
  sveta 38435bf311 Merge Maxim vor 5 Jahren
  sveta 7925d5eb61 test vor 5 Jahren
  sveta 0f33146481 test vor 5 Jahren
  sveta 31d7915f23 change test vor 5 Jahren
  sveta cbf6b70436 create,change, test vor 5 Jahren
  Maxim 15844d82bd auth changes => logOut is done vor 5 Jahren
  sveta 37604e9378 create test vor 5 Jahren
  Maxim 293bffe5b2 somewhat vor 5 Jahren
  Svetlana e99b4855da category admin vor 5 Jahren
  Maxim 063a04fffd router logic rewrote: static -> using token vor 5 Jahren
  Svetlana 44569b3daa marge -> sineIn, sineUp and profile vor 5 Jahren
  Svetlana b46a81722c profile vor 5 Jahren
  Maxim 1fa808c423 sign up is finally done vor 5 Jahren
  Maxim 3dd80863d5 signUp -> validation and form added, reducer is done vor 5 Jahren
  sveta c9fa754a79 profile->login vor 5 Jahren
  Maxim f952c35f77 user storaging via redux is done -> router works correctly vor 5 Jahren
  Svetlana 939956eb6e marge vor 5 Jahren
  Svetlana e26c783cb0 Merge remote-tracking branch 'origin/new_Sveta' into new_dev vor 5 Jahren
  Svetlana dc79b4e3e8 header vor 5 Jahren
  Maxim ba885f86b9 added reworked sign in vor 5 Jahren
  Svetlana 013d5cb557 profile; vor 5 Jahren
  Maxim 12c3e855af Rework final structure added bootstrap and custom classes + popper.js and jquery vor 5 Jahren
  Maxim 2e840c1379 rework initial structure vor 5 Jahren
100 geänderte Dateien mit 11853 neuen und 4045 gelöschten Zeilen
  1. 8090 3897
      package-lock.json
  2. 22 2
      package.json
  3. BIN
      public/favicon.ico
  4. 14 35
      public/index.html
  5. 0 15
      public/manifest.json
  6. 0 32
      src/App.css
  7. 0 28
      src/App.js
  8. 0 9
      src/App.test.js
  9. 14 0
      src/actions/admin/category/changeCategory.js
  10. 14 0
      src/actions/admin/category/createCategory.js
  11. 14 0
      src/actions/admin/category/deleteCategory.js
  12. 14 0
      src/actions/admin/category/getCategory.js
  13. 24 0
      src/actions/admin/changeTest/changeTest.js
  14. 17 0
      src/actions/admin/changeTest/deleteAnswer.js
  15. 17 0
      src/actions/admin/changeTest/deleteQuestion.js
  16. 17 0
      src/actions/admin/changeTest/deleteTopic.js
  17. 17 0
      src/actions/admin/changeTest/getAnswers.js
  18. 17 0
      src/actions/admin/changeTest/getQuestions.js
  19. 16 0
      src/actions/admin/changeTest/getTopic.js
  20. 13 0
      src/actions/admin/meUser.js
  21. 21 0
      src/actions/admin/test/createTest.js
  22. 25 0
      src/actions/admin/test/createTopics.js
  23. 19 0
      src/actions/admin/user/changeUser.js
  24. 0 0
      src/actions/admin/user/changeUserRole.js
  25. 19 0
      src/actions/admin/user/deleteUser.js
  26. 17 0
      src/actions/admin/user/getUser.js
  27. 17 0
      src/actions/auth/logOut.js
  28. 19 0
      src/actions/auth/signIn.js
  29. 16 0
      src/actions/auth/signUp.js
  30. 10 0
      src/actions/auth/tokenCheckout.js
  31. 16 0
      src/actions/user/changeEmail.js
  32. 16 0
      src/actions/user/changePassword.js
  33. 16 0
      src/actions/user/changelogin.js
  34. 17 0
      src/actions/user/test/checkTest.js
  35. 17 0
      src/actions/user/test/getTopics.js
  36. 17 0
      src/actions/user/test/nextTest.js
  37. 17 0
      src/actions/user/test/testStart.js
  38. 35 0
      src/components/admin/CardsCreator/index.js
  39. 161 0
      src/components/admin/CreateTest/CreateTopic.js
  40. 69 0
      src/components/admin/CreateTest/index.js
  41. 49 0
      src/components/admin/addDeleteCategory/ChangeCategory.js
  42. 33 0
      src/components/admin/addDeleteCategory/CreateCategoryForm/index.js
  43. 48 0
      src/components/admin/addDeleteCategory/DeleteCategory.js
  44. 140 0
      src/components/admin/addDeleteCategory/GetCategory.js
  45. 56 0
      src/components/admin/addDeleteCategory/index.js
  46. 71 0
      src/components/admin/deleteUser/GetUsers.js
  47. 62 0
      src/components/admin/deleteUser/changeUsers.js
  48. 74 0
      src/components/admin/deleteUser/index.js
  49. 106 0
      src/components/admin/getChangeDeleteTest/GetQuestions.js
  50. 39 0
      src/components/admin/getChangeDeleteTest/GetTest.js
  51. 76 0
      src/components/admin/getChangeDeleteTest/GetTopic.js
  52. 162 0
      src/components/admin/getChangeDeleteTest/OpenModal.js
  53. 112 0
      src/components/admin/getChangeDeleteTest/changeQuestions.js
  54. 125 0
      src/components/admin/getChangeDeleteTest/index.js
  55. 9 0
      src/components/common/formInput.js
  56. 50 0
      src/components/common/protectedRoute.js
  57. 9 0
      src/components/common/spinner.js
  58. 120 0
      src/components/public/Header.js
  59. 32 0
      src/components/public/landing.js
  60. 58 0
      src/components/public/signIn/Form/index.js
  61. 14 0
      src/components/public/signIn/Form/validate.js
  62. 51 0
      src/components/public/signIn/index.js
  63. 63 0
      src/components/public/signUp/Form/index.js
  64. 47 0
      src/components/public/signUp/Form/validate.js
  65. 31 0
      src/components/public/signUp/index.js
  66. 63 0
      src/components/user/Categoty.js
  67. 44 0
      src/components/user/ProfilePage/ChangeEmailForm/index.js
  68. 43 0
      src/components/user/ProfilePage/ChangeLoginForm/index.js
  69. 0 0
      src/components/user/ProfilePage/ChangeLoginForm/validate/index.js
  70. 47 0
      src/components/user/ProfilePage/changePassword/index.js
  71. 131 0
      src/components/user/ProfilePage/index.js
  72. 25 0
      src/components/user/Test/ModalSommary.js
  73. 60 0
      src/components/user/Test/getTest.js
  74. 95 0
      src/components/user/Test/index.js
  75. 12 0
      src/configs/requestsConfigs/index.js
  76. 90 0
      src/configs/routerConfig.js
  77. 47 0
      src/configs/validate.js
  78. 83 0
      src/constants/admin.js
  79. 18 0
      src/constants/auth.js
  80. 15 0
      src/constants/routes.js
  81. 31 0
      src/constants/user.js
  82. 0 14
      src/index.css
  83. 16 6
      src/index.js
  84. 0 7
      src/logo.svg
  85. 43 0
      src/reducers/admin/changeCategory.js
  86. 42 0
      src/reducers/admin/createCategory.js
  87. 35 0
      src/reducers/admin/getCategory.js
  88. 33 0
      src/reducers/admin/getUsers.js
  89. 32 0
      src/reducers/admin/initialValues.js
  90. 35 0
      src/reducers/admin/test/changeUser.js
  91. 34 0
      src/reducers/admin/test/createTopics.js
  92. 34 0
      src/reducers/admin/test/deleteQuestion.js
  93. 34 0
      src/reducers/admin/test/deleteTopic.js
  94. 36 0
      src/reducers/admin/test/deleteUsers.js
  95. 36 0
      src/reducers/admin/test/getAnswers.js
  96. 36 0
      src/reducers/admin/test/getQuestions.js
  97. 37 0
      src/reducers/admin/test/getTopic.js
  98. 34 0
      src/reducers/admin/test/newTopic.js
  99. 31 0
      src/reducers/auth/logOut.js
  100. 0 0
      src/reducers/auth/signIn.js

Datei-Diff unterdrückt, da er zu groß ist
+ 8090 - 3897
package-lock.json


+ 22 - 2
package.json

@@ -3,9 +3,26 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
+    "antd": "^3.13.2",
+    "axios": "^0.18.0",
+    "bootstrap": "^4.3.0",
+    "jquery": "^3.3.1",
+    "jwt-decode": "^2.2.0",
+    "node-sass": "^4.11.0",
+    "popper.js": "^1.14.6",
     "react": "^16.6.3",
+    "react-bootstrap": "^1.0.0-beta.5",
     "react-dom": "^16.6.3",
-    "react-scripts": "2.1.1"
+    "react-redux": "^6.0.0",
+    "react-router": "^4.3.1",
+    "react-router-dom": "^4.3.1",
+    "react-scripts": "^2.1.3",
+    "react-spinners": "^0.5.1",
+    "react-transition-group": "^2.5.3",
+    "redux": "^4.0.1",
+    "redux-form": "^8.1.0",
+    "redux-saga": "^1.0.0",
+    "stylefire": "^2.4.0"
   },
   "scripts": {
     "start": "react-scripts start",
@@ -21,5 +38,8 @@
     "not dead",
     "not ie <= 11",
     "not op_mini all"
-  ]
+  ],
+  "devDependencies": {
+    "redux-logger": "^3.0.6"
+  }
 }

BIN
public/favicon.ico


+ 14 - 35
public/index.html

@@ -1,40 +1,19 @@
 <!DOCTYPE html>
 <html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
-    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
-    <meta name="theme-color" content="#000000">
-    <!--
-      manifest.json provides metadata used when your web app is added to the
-      homescreen on Android. See https://developers.google.com/web/fundamentals/web-app-manifest/
-    -->
-    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
-    <!--
-      Notice the use of %PUBLIC_URL% in the tags above.
-      It will be replaced with the URL of the `public` folder during the build.
-      Only files inside the `public` folder can be referenced from the HTML.
 
-      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
-      work correctly both with client-side routing and a non-root public URL.
-      Learn how to configure a non-root public URL by running `npm run build`.
-    -->
-    <title>React App</title>
-  </head>
-  <body>
-    <noscript>
-      You need to enable JavaScript to run this app.
-    </noscript>
-    <div id="root"></div>
-    <!--
-      This HTML file is a template.
-      If you open it directly in the browser, you will see an empty page.
+<head>
+  <meta charset="utf-8">
+  <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
+  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+  <meta name="theme-color" content="#000000">
+  <title>React App</title>
+</head>
 
-      You can add webfonts, meta tags, or analytics to this file.
-      The build step will place the bundled scripts into the <body> tag.
+<body>
+  <noscript>
+    You need to enable JavaScript to run this app.
+  </noscript>
+  <div id="root"></div>
+</body>
 
-      To begin the development, run `npm start` or `yarn start`.
-      To create a production bundle, use `npm run build` or `yarn build`.
-    -->
-  </body>
-</html>
+</html>

+ 0 - 15
public/manifest.json

@@ -1,15 +0,0 @@
-{
-  "short_name": "React App",
-  "name": "Create React App Sample",
-  "icons": [
-    {
-      "src": "favicon.ico",
-      "sizes": "64x64 32x32 24x24 16x16",
-      "type": "image/x-icon"
-    }
-  ],
-  "start_url": ".",
-  "display": "standalone",
-  "theme_color": "#000000",
-  "background_color": "#ffffff"
-}

+ 0 - 32
src/App.css

@@ -1,32 +0,0 @@
-.App {
-  text-align: center;
-}
-
-.App-logo {
-  animation: App-logo-spin infinite 20s linear;
-  height: 40vmin;
-}
-
-.App-header {
-  background-color: #282c34;
-  min-height: 100vh;
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  font-size: calc(10px + 2vmin);
-  color: white;
-}
-
-.App-link {
-  color: #61dafb;
-}
-
-@keyframes App-logo-spin {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
-}

+ 0 - 28
src/App.js

@@ -1,28 +0,0 @@
-import React, { Component } from 'react';
-import logo from './logo.svg';
-import './App.css';
-
-class App extends Component {
-  render() {
-    return (
-      <div className="App">
-        <header className="App-header">
-          <img src={logo} className="App-logo" alt="logo" />
-          <p>
-            Edit <code>src/App.js</code> and save to reload.
-          </p>
-          <a
-            className="App-link"
-            href="https://reactjs.org"
-            target="_blank"
-            rel="noopener noreferrer"
-          >
-            Learn React
-          </a>
-        </header>
-      </div>
-    );
-  }
-}
-
-export default App;

+ 0 - 9
src/App.test.js

@@ -1,9 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import App from './App';
-
-it('renders without crashing', () => {
-  const div = document.createElement('div');
-  ReactDOM.render(<App />, div);
-  ReactDOM.unmountComponentAtNode(div);
-});

+ 14 - 0
src/actions/admin/category/changeCategory.js

@@ -0,0 +1,14 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const changeCategoryRequest = payload => ({
+    type: actionTypes.CHANGE_CATEGORY_REQUEST,
+    payload
+});
+export const changeCategorySuccess = payload => ({
+    type: actionTypes.CHANGE_CATEGORY_REQUEST_SUCCESS,
+    payload
+});
+export const changeCategoryFailure = error => ({
+    type: actionTypes.CHANGE_CATEGORY_REQUEST_FAILURE,
+    error
+});

+ 14 - 0
src/actions/admin/category/createCategory.js

@@ -0,0 +1,14 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const createCategoryRequest = payload => {
+  return{  type: actionTypes.CREATE_CATEGORY_REQUEST,
+    payload
+}};
+export const createCategorySuccess = payload => ({
+    type: actionTypes.CREATE_CATEGORY_REQUEST_SUCCESS,
+    payload
+});
+export const createCategoryFailure = error => ({
+    type: actionTypes.CREATE_CATEGORY_REQUEST_FAILURE,
+    error
+});

+ 14 - 0
src/actions/admin/category/deleteCategory.js

@@ -0,0 +1,14 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const deleteCategoryRequest = payload => ({
+    type: actionTypes.DELETE_CATEGORY_REQUEST,
+    payload
+});
+export const deleteCategorySuccess = payload => ({
+    type: actionTypes.DELETE_CATEGORY_REQUEST_SUCCESS,
+    payload
+});
+export const deleteCategoryFailure = error => ({
+    type: actionTypes.DELETE_CATEGORY_REQUEST_FAILURE,
+    error
+});

+ 14 - 0
src/actions/admin/category/getCategory.js

@@ -0,0 +1,14 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const getCategoryRequest = payload => ({
+    type: actionTypes.GET_CATEGORY_REQUEST,
+    payload
+});
+export const getCategorySuccess = payload => ({
+    type: actionTypes.GET_CATEGORY_REQUEST_SUCCESS,
+    payload
+});
+export const getCategoryFailure = error => ({
+    type: actionTypes.GET_CATEGORY_REQUEST_FAILURE,
+    error
+});

+ 24 - 0
src/actions/admin/changeTest/changeTest.js

@@ -0,0 +1,24 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const changeTestRequest = payload => {
+    return{
+    type: actionTypes.CHANGE_TEST_REQUEST,
+    payload
+};
+}
+export const changeTopicSuccess = payload => ({
+    type: actionTypes.CHANGE_TOPIC_REQUEST_SUCCESS,
+    payload
+});
+export const changeQuestionSuccess = payload => ({
+    type: actionTypes.CHANGE_QUESTIONS_REQUEST_SUCCESS,
+    payload
+});
+export const changeAnswersSuccess = payload => ({
+    type: actionTypes.CHANGE_ANSVERS_REQUEST_SUCCESS,
+    payload
+});
+export const createTopicsFailure = error => ({
+    type: actionTypes.CHANGE_TEST_REQUEST_FAILURE,
+    error
+});

+ 17 - 0
src/actions/admin/changeTest/deleteAnswer.js

@@ -0,0 +1,17 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const deleteAnswerRequest = payload => {
+    return{
+    type: actionTypes.DELETE_ANSWER_REQUEST,
+    payload
+};
+}
+export const deleteAnswerSuccess = payload => ({
+    type: actionTypes.DELETE_ANSWER_REQUEST_SUCCESS,
+    payload
+});
+
+export const deleteAnswerFailure = error => ({
+    type: actionTypes.DELETE_ANSWER_REQUEST_FAILURE,
+    error
+});

+ 17 - 0
src/actions/admin/changeTest/deleteQuestion.js

@@ -0,0 +1,17 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const deleteQuestionRequest = payload => {
+    return{
+    type: actionTypes.DELETE_QUESTION_REQUEST,
+    payload
+};
+}
+export const deleteQuestionSuccess = payload => ({
+    type: actionTypes.DELETE_QUESTION_REQUEST_SUCCESS,
+    payload
+});
+
+export const deleteQuestionFailure = error => ({
+    type: actionTypes.DELETE_QUESTION_REQUEST_FAILURE,
+    error
+});

+ 17 - 0
src/actions/admin/changeTest/deleteTopic.js

@@ -0,0 +1,17 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const deleteTopicRequest = payload => {
+    return{
+    type: actionTypes.DELETE_TOPIC_REQUEST,
+    payload
+};
+}
+export const deleteTopicSuccess = payload => ({
+    type: actionTypes.DELETE_TOPIC_REQUEST_SUCCESS,
+    payload
+});
+
+export const deleteTopicFailure = error => ({
+    type: actionTypes.DELETE_TOPIC_REQUEST_FAILURE,
+    error
+});

+ 17 - 0
src/actions/admin/changeTest/getAnswers.js

@@ -0,0 +1,17 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const getAnswersRequest = payload => {
+    return{
+    type: actionTypes.GET_ANSWERS_REQUEST,
+    payload
+};
+}
+export const getAnswersSuccess = payload => ({
+    type: actionTypes.GET_ANSWERS_REQUEST_SUCCESS,
+    payload
+});
+
+export const getAnswersFailure = error => ({
+    type: actionTypes.GET_ANSWERS_REQUEST_FAILURE,
+    error
+});

+ 17 - 0
src/actions/admin/changeTest/getQuestions.js

@@ -0,0 +1,17 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const getQuestionsRequest = payload => {
+    return{
+    type: actionTypes.GET_QUESTIONS_REQUEST,
+    payload
+};
+}
+export const getQuestionsSuccess = payload => ({
+    type: actionTypes.GET_QUESTIONS_REQUEST_SUCCESS,
+    payload
+});
+
+export const getQuestionsFailure = error => ({
+    type: actionTypes.GET_QUESTIONS_REQUEST_FAILURE,
+    error
+});

+ 16 - 0
src/actions/admin/changeTest/getTopic.js

@@ -0,0 +1,16 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const getTopicRequest = payload => {
+    return{
+    type: actionTypes.GET_TOPIC_REQUEST,
+    payload
+};
+}
+export const getTopicSuccess = payload => ({
+    type: actionTypes.GET_TOPIC_REQUEST_SUCCESS,
+    payload
+});
+export const getTopicFailure = error => ({
+    type: actionTypes.GET_TOPIC_REQUEST_FAILURE,
+    error
+});

+ 13 - 0
src/actions/admin/meUser.js

@@ -0,0 +1,13 @@
+import * as actionTypes from '../../constants/admin';
+
+export const myUserRequest = payload => ({
+    type: actionTypes.MY_USER_REQUEST,
+});
+export const myUserSuccess = payload => ({
+    type: actionTypes.MY_USER_REQUEST_SUCCESS,
+    payload
+});
+export const myUserFailure = error => ({
+    type: actionTypes.MY_USER_REQUEST_FAILURE,
+    error
+});

+ 21 - 0
src/actions/admin/test/createTest.js

@@ -0,0 +1,21 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const createTestRequest = payload => {
+    console.log(payload)
+    return{
+    type: actionTypes.CREATE_TEST_REQUEST,
+    payload
+};
+}
+export const createQuestionSuccess = payload => ({
+    type: actionTypes.CREATE_QUESTIONS_REQUEST_SUCCESS,
+    payload
+});
+export const createAnswersSuccess = payload => ({
+    type: actionTypes.CREATE_ANSVERS_REQUEST_SUCCESS,
+    payload
+});
+export const createTestFailure = error => ({
+    type: actionTypes.CREATE_TEST_REQUEST_FAILURE,
+    error
+});

+ 25 - 0
src/actions/admin/test/createTopics.js

@@ -0,0 +1,25 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const createTopicsRequest = payload => {
+    console.log(payload)
+    return{
+    type: actionTypes.CREATE_TOPICS_REQUEST,
+    payload
+};
+}
+export const createTopicsSuccess = payload => ({
+    type: actionTypes.CREATE_TOPICS_REQUEST_SUCCESS,
+    payload
+});
+export const createQuestionSuccess = payload => ({
+    type: actionTypes.CREATE_QUESTIONS_REQUEST_SUCCESS,
+    payload
+});
+export const createAnswersSuccess = payload => ({
+    type: actionTypes.CREATE_ANSVERS_REQUEST_SUCCESS,
+    payload
+});
+export const createTopicsFailure = error => ({
+    type: actionTypes.CREATE_TOPICS_REQUEST_FAILURE,
+    error
+});

+ 19 - 0
src/actions/admin/user/changeUser.js

@@ -0,0 +1,19 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const changeUserRequest = payload => {
+    console.log(payload)
+    return{
+
+        type: actionTypes.CHANGE_USERS_REQUEST,
+        payload
+    }
+    
+}
+export const changeUserSuccess = payload => ({
+    type: actionTypes.CHANGE_USERS_REQUEST_SUCCESS,
+    payload
+});
+export const changeUserFailure = error => ({
+    type: actionTypes.CHANGE_USERS_REQUEST_FAILURE,
+    error
+});

+ 0 - 0
src/actions/admin/user/changeUserRole.js


+ 19 - 0
src/actions/admin/user/deleteUser.js

@@ -0,0 +1,19 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const deleteUsersRequest = payload => {
+    console.log(payload)
+    return{
+
+        type: actionTypes.DELETE_USERS_REQUEST,
+        payload
+    }
+    
+}
+export const deleteUsersSuccess = payload => ({
+    type: actionTypes.DELETE_USERS_REQUEST_SUCCESS,
+    payload
+});
+export const deleteUsersFailure = error => ({
+    type: actionTypes.DELETE_USERS_REQUEST_FAILURE,
+    error
+});

+ 17 - 0
src/actions/admin/user/getUser.js

@@ -0,0 +1,17 @@
+import * as actionTypes from '../../../constants/admin';
+
+export const getUserRequest = payload => {
+    console.log('Inside the getUser action', payload);
+    return {
+        type: actionTypes.GET_USERS_REQUEST,
+        payload
+    };
+}
+export const getUserSuccess = payload => ({
+    type: actionTypes.GET_USERS_REQUEST_SUCCESS,
+    payload
+});
+export const getUserFailure = error => ({
+    type: actionTypes.GET_USERS_REQUEST_FAILURE,
+    error
+});

+ 17 - 0
src/actions/auth/logOut.js

@@ -0,0 +1,17 @@
+import * as actionTypes from './../../constants/auth';
+
+const logOut = () => ({
+    type: actionTypes.LOG_OUT_REQUEST
+})
+
+export const logOutSuccess = payload => ({
+    type: actionTypes.LOG_OUT_REQUEST_SUCCESS,
+    payload
+})
+
+export const logOutFailure = ({ message: error }) => ({
+    type: actionTypes.LOG_OUT_REQUEST_FAILURE,
+    error
+})
+
+export default logOut;

+ 19 - 0
src/actions/auth/signIn.js

@@ -0,0 +1,19 @@
+import * as actionTypes from './../../constants/auth';
+
+const signIn = payload => ({
+    type: actionTypes.SIGN_IN_REQUEST,
+    payload
+});
+export const signInSuccess = payload => ({
+    type: actionTypes.SIGN_IN_REQUEST_SUCCESS,
+    payload
+});
+export const signInFailure = error => ({
+    type: actionTypes.SIGN_IN_REQUEST_FAILURE,
+    error
+});
+export const signInStateZeroing = () => ({
+    type: actionTypes.SIGN_IN_STATE_ZEROING
+})
+
+export default signIn;

+ 16 - 0
src/actions/auth/signUp.js

@@ -0,0 +1,16 @@
+import * as actionTypes from './../../constants/auth';
+
+const signUp = payload => ({
+    type: actionTypes.SIGN_UP_REQUEST,
+    payload
+});
+export const signUpSuccess = payload => ({
+    type: actionTypes.SIGN_UP_REQUEST_SUCCESS,
+    payload
+});
+export const signUpFailure = error => ({
+    type: actionTypes.SIGN_UP_REQUEST_FAILURE,
+    error
+});
+
+export default signUp;

+ 10 - 0
src/actions/auth/tokenCheckout.js

@@ -0,0 +1,10 @@
+import * as types from './../../constants/auth';
+
+export const activeToken = payload => ({
+    type: types.ACTIVE_TOKEN,
+    payload
+})
+
+export const inactiveToken = () => ({
+    type: types.INACTIVE_TOKEN
+})

+ 16 - 0
src/actions/user/changeEmail.js

@@ -0,0 +1,16 @@
+import * as actionTypes from './../../constants/user';
+
+export const changeEmailRequest = payload => {
+    return {
+        type: actionTypes.CHANGE_EMAIL_REQUEST,
+        payload
+    };
+}
+export const changeEmailSuccess = payload => ({
+    type: actionTypes.CHANGE_EMAIL_REQUEST_SUCCESS,
+    payload
+});
+export const changeEmailFailure = error => ({
+    type: actionTypes.CHANGE_EMAIL_REQUEST_FAILURE,
+    error
+});

+ 16 - 0
src/actions/user/changePassword.js

@@ -0,0 +1,16 @@
+import * as actionTypes from './../../constants/user';
+
+export const changePasswordRequest = payload => {
+    return {
+        type: actionTypes.CHANGE_PASSWORD_REQUEST,
+        payload
+    };
+}
+export const changePasswordSuccess = payload => ({
+    type: actionTypes.CHANGE_PASSWORD_REQUEST_SUCCESS,
+    payload
+});
+export const changePasswordFailure = error => ({
+    type: actionTypes.CHANGE_PASSWORD_REQUEST_FAILURE,
+    error
+});

+ 16 - 0
src/actions/user/changelogin.js

@@ -0,0 +1,16 @@
+import * as actionTypes from './../../constants/user';
+
+export const changeLoginRequest = payload => {
+    return {
+        type: actionTypes.CHANGE_LOGIN_REQUEST,
+        payload
+    };
+}
+export const changeLoginSuccess = payload => ({
+    type: actionTypes.CHANGE_LOGIN_REQUEST_SUCCESS,
+    payload
+});
+export const changeLoginFailure = error => ({
+    type: actionTypes.CHANGE_LOGIN_REQUEST_FAILURE,
+    error
+});

+ 17 - 0
src/actions/user/test/checkTest.js

@@ -0,0 +1,17 @@
+import * as actionTypes from '../../../constants/user';
+
+
+export const checkTestRequest = payload => {
+    return{
+    type: actionTypes.CHECK_TEST_REQUEST,
+    payload
+};
+}
+export const checkTestSuccess = payload => ({
+    type: actionTypes.CHECK_TEST_REQUEST_SUCCESS,
+    payload
+});
+export const checkTestFailure = error => ({
+    type: actionTypes.CHECK_TEST_REQUEST_FAILURE,
+    error
+});

+ 17 - 0
src/actions/user/test/getTopics.js

@@ -0,0 +1,17 @@
+import * as actionTypes from '../../../constants/user';
+
+
+export const getTopicTestRequest = payload => {
+    return{
+    type: actionTypes.GET_TOPIC_TEST_REQUEST,
+    payload
+};
+}
+export const getTopicTestSuccess = payload => ({
+    type: actionTypes.GET_TOPIC_TEST_REQUEST_SUCCESS,
+    payload
+});
+export const getTopicTestFailure = error => ({
+    type: actionTypes.GET_TOPIC_TEST_REQUEST_FAILURE,
+    error
+});

+ 17 - 0
src/actions/user/test/nextTest.js

@@ -0,0 +1,17 @@
+import * as actionTypes from '../../../constants/user';
+
+
+export const nextTestRequest = payload => {
+    return{
+    type: actionTypes.NEXT_TEST_REQUEST,
+    payload
+};
+}
+export const nextTestSuccess = payload => ({
+    type: actionTypes.NEXT_TEST_REQUEST_SUCCESS,
+    payload
+});
+export const nextTestFailure = error => ({
+    type: actionTypes.NEXT_TEST_REQUEST_FAILURE,
+    error
+});

+ 17 - 0
src/actions/user/test/testStart.js

@@ -0,0 +1,17 @@
+import * as actionTypes from '../../../constants/user';
+
+
+export const startTestRequest = payload => {
+    return{
+    type: actionTypes.START_TEST_REQUEST,
+    payload
+};
+}
+export const startTestSuccess = payload => ({
+    type: actionTypes.START_TEST_REQUEST_SUCCESS,
+    payload
+});
+export const startTestFailure = error => ({
+    type: actionTypes.START_TEST_REQUEST_FAILURE,
+    error
+});

+ 35 - 0
src/components/admin/CardsCreator/index.js

@@ -0,0 +1,35 @@
+import React from 'react';
+import { Field, reduxForm } from 'redux-form';
+import { connect } from 'react-redux';
+
+class CardCreator extends React.Component {
+    state = {
+        type: null
+    }
+
+    render() {
+        const { formProps } = this.props;
+        console.log('------------ PROPS --------------');
+        console.log(formProps);
+
+        return (
+            <div>
+                <h1>Create Test</h1>
+                <Field name='some' component='select'>
+                    <option value="some value 1">Optional</option>
+                    <option value="some value 2">Multioptional</option>
+                    <option value="some value 3">Open Answer</option>
+                    <option value="some value 4">Conformity</option>
+                </Field>
+            </div>
+        )
+    }
+}
+
+const mapStateToProps = state => ({
+    formProps: state.form
+})
+
+export default connect(mapStateToProps, null)(reduxForm({
+    form: "CardCreator"
+})(CardCreator))

+ 161 - 0
src/components/admin/CreateTest/CreateTopic.js

@@ -0,0 +1,161 @@
+import React from 'react';
+import { Field, reduxForm, formValueSelector } from 'redux-form';
+import formInput from '../../common/formInput';
+import { connect } from 'react-redux';
+import validate from '../../../configs/validate'
+
+class CreateTopic extends React.Component {
+
+    state = {
+        click: false,
+        arrayAnswers: [],
+        array: [],
+        simple: false,
+        click_2: false,
+        click_3: false
+
+    }
+
+    submit = () => {
+        const { actions: { createTopicsRequest }, categoryId, formValues: { name, description } } = this.props;
+        console.log(name, description)
+        createTopicsRequest({
+            name,
+            description,
+            categoryId,
+
+        })
+    }
+    qestionAnswerSubmit = () => {
+        const { simple, array } = this.state
+        const {  topic: { _id }  , actions: { createTestRequest }, formValues: { questions } } = this.props;
+        console.log(questions)
+        createTestRequest({
+            questions,
+            simple,
+            _id,
+            array
+        })
+        this.setState({ arrayAnswers:[] })
+        this.setState({ array:[] })
+
+
+
+
+    }
+
+    handelChange = () => { this.setState((prevState) => ({ simple: !prevState.simple })) }
+
+    handelClick = () => { this.setState((prevState) => ({ click: !prevState.click })) }
+
+    handleClick_3 = () => {
+        this.setState((prevState) => ({ click_2: !prevState.click_2 }))
+        this.setState({ click_3:true })
+        this.setState((prevState) => ({ arrayAnswers: prevState.arrayAnswers.concat(prevState.arrayAnswers.length + 1) }))
+
+    }
+    handelClick_2 =()=>{
+        this.setState((prevState) => ({ click_3: !prevState.click_3 }))
+
+    }
+    formSubmitinput = (event) => {
+        const currentId = this.state.arrayAnswers.length;
+
+        const values = {
+            answer: event[`answers${currentId}`],
+            price: Number(event[`price${currentId}`]),
+            correct: event[`correct${currentId}`] || false
+        }
+        console.log(values)
+        this.setState((prevState) => ({ array: prevState.array.push(values) }, console.log(prevState.array)))
+        this.setState((prevState) => ({ click_2: !prevState.click_2 }))
+
+    }
+
+
+    render() {
+        const { handleSubmit} = this.props;
+        const { simple, price, correct, click, array, arrayAnswers, click_2, click_3 } = this.state;
+        const { handelChange, submit, handelClick, formSubmitinput, qestionAnswerSubmit, handelClick_2, handleClick_3 } = this;
+console.log(this.state)
+        return (
+            <div>
+                <form onSubmit={handleSubmit(qestionAnswerSubmit)}>
+                    <h4 className="text-white font-ci"> Enter topic </h4>
+                    <Field className="bg-mist bg-mist-op text-white mt-3 mb-3 border rounded w-100 " name="name" type="name" placeholder="Create Name Topic" component={formInput} />
+                    <h4 className="text-white font-ci"> Enter description </h4>
+                    <Field className="bg-mist bg-mist-op text-white mt-3 mb-3 border rounded w-100 " name="description" type="textarea" placeholder="Create Descriptions" component={formInput} />
+                    {
+                        !click
+                            ?
+                            <button className= "btn  btn-outline-light bg-stone"
+                                onClick={() => {
+                                    handelClick()
+                                    submit()
+                                }}>
+                                Create questions
+                            </button>
+                            :
+                            <div>
+                                <h4 className="text-white font-ci"> Enter question and set the difficulty level</h4>
+                                <div className="d-flex w-100 ">
+                                    <Field className="bg-stone bg-mist-op text-white mt-3 mb-3 border rounded w-100 " name="questions" type="questions" placeholder="Create Qestions" component={formInput} />
+                                    <Field className="bg-mist bg-mist-op text-white mt-4 pb-1  border rounded w-25 flex-row align-items-end check" name="simple" type="checkbox" checked={simple} onChange={handelChange} component={formInput} />
+                                </div>
+                                {
+                                    click_3
+                                        ?
+
+                                        arrayAnswers.map(el =>
+                                            <div key={el} id={el}>
+                                                <Field className="bg-mist bg-mist-op text-white mt-3 mb-3 border rounded" name={`answers${el}`} type="name" placeholder="Add anwer" ref='ansversInput' component={formInput} />
+                                                <Field className="bg-mist bg-mist-op text-white mt-3 mb-3 border rounded" name={`price${el}`} type="number" value={price} component={formInput} />
+                                                <Field className="bg-mist bg-mist-op text-white mt-3 mb-3 border rounded" name={`correct${el}`} type="checkbox" checked={correct} component={formInput} />
+                                            </div>
+                                        )
+                                        :
+                                null
+
+                                }
+
+                                <React.Fragment>
+                                    {
+                                        click_2
+                                            ?
+                                            <button className= "btn  btn-outline-light bg-stone m-3" type="button" onClick={handleSubmit(formSubmitinput)}>Add answer</button>
+                                            :
+                                            <React.Fragment>
+                                                <button className= "btn  btn-outline-light bg-stone m-3" type="button " onClick={handleClick_3}>Create answers</button>
+                                                <button className= "btn  btn-outline-light bg-stone m-3" onClick ={handelClick_2} >Create Questions</button>
+                                            </React.Fragment>
+                                    }
+
+
+
+                                </React.Fragment>
+
+
+                        
+
+                            </div>
+                    }
+
+                </form>
+            </div>
+        )
+
+    }
+
+}
+
+const selector = formValueSelector('createTopicForm');
+
+const mapStateToProps = state => ({
+
+    formValues: selector(state, 'name', 'description', 'questions', 'simple', 'answer', 'price', 'correct')
+})
+
+export default connect(mapStateToProps, null)(reduxForm({
+    form: "createTopicForm",
+    validate
+})(CreateTopic));

+ 69 - 0
src/components/admin/CreateTest/index.js

@@ -0,0 +1,69 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux';
+import { getCategoryRequest } from '../../../actions/admin/category/getCategory';
+import CreateTopic from './CreateTopic';
+import { createTopicsRequest } from '../../../actions/admin/test/createTopics';
+import { createTestRequest } from '../../../actions/admin/test/createTest';
+import { myUserRequest } from '../../../actions/admin/meUser'
+
+
+
+
+class CreateTest extends React.Component {
+    state = {
+        categoryId: null
+    }
+
+    componentDidMount() {
+        const { getCategoryRequest, myUserRequest } = this.props;
+        getCategoryRequest()
+    }
+
+    onClick = (event) => {
+        this.setState({ categoryId: event.target.value })
+    }
+
+
+
+
+    render() {
+        const { category: { data }, createTopicsRequest, createTestRequest, topicId: { topic } } = this.props;
+        const { categoryId } = this.state
+        const { onClick } = this;
+
+
+        console.log(topic)
+
+        return (
+            <div className=" padding profile-page  d-flex flex-row font-ci">
+                <div className=" slideDown w-100 m-5 bg-gradient border rounded">
+                    <div className=" m-5 text-center  text-white font-ci font-ci-bold ">
+                        <h4 className="text-white font-ci">Select category for creating tests</h4>
+                        <select class="custom-select bg-mist bg-mist-op text-white mt-3 mb-3" onChange={onClick} value={categoryId}>
+                            <option selected>Open this Category menu</option>
+                            {
+                                data && data.map(mass => <option key={mass._id} value={mass._id}>{mass.name}</option>)
+
+                            }
+                        </select>
+                        <CreateTopic categoryId={categoryId} topic={topic} actions={{ createTopicsRequest, createTestRequest }} ></CreateTopic>
+                    </div>
+                </div>
+            </div>
+
+        )
+    }
+
+}
+
+const
+    mapStateToProps = state => ({
+        myUser: state.myUser,
+        category: state.category,
+        topicId: state.topicId
+    });
+
+const mapDispatchToProps = dispatch => bindActionCreators({ getCategoryRequest, createTopicsRequest, createTestRequest, myUserRequest }, dispatch);
+
+export default connect(mapStateToProps, mapDispatchToProps)(CreateTest);

+ 49 - 0
src/components/admin/addDeleteCategory/ChangeCategory.js

@@ -0,0 +1,49 @@
+import React from 'react';
+import { Field, reduxForm } from 'redux-form';
+import formInput from '../../common/formInput'
+import DeleteCategory from './DeleteCategory';
+
+
+
+class ChangeCategory extends React.Component {
+
+    submit = ({ name }) => {
+        const { actions: { changeCategoryRequest }, categorys: { id } } = this.props;
+        changeCategoryRequest({
+            name,
+            id
+        })
+    }
+
+    render() {
+        const { handleSubmit, handlers:{changeCategoryClick, deleteClick},categorys} = this.props;
+        const { submit } = this;
+
+        return (
+
+            <form className="m-2" onSubmin={handleSubmit(submit)}>
+                <Field className="form-control mb-3" name="name" type="name" placeholder="Change Category" component={formInput} />
+                <div className="d-flex">
+                <button className="btn  btn-outline-light bg-stone m-3" type="button" onClick={
+                    function () {
+                        
+                        handleSubmit(submit)();
+                    }
+                }
+                >
+                Сhange
+                </button>
+                <DeleteCategory handlers={{deleteClick}} categorys={categorys}></DeleteCategory>
+                </div>
+            </form >
+
+        )
+    }
+
+}
+
+
+
+export default reduxForm({
+    form: "changeCategoryForm",
+})(ChangeCategory);

+ 33 - 0
src/components/admin/addDeleteCategory/CreateCategoryForm/index.js

@@ -0,0 +1,33 @@
+import React from 'react';
+import { Field, reduxForm } from 'redux-form';
+
+import formInput from '../../..//common/formInput';
+
+class CreateCategoryForm extends React.Component {
+    submit = async ({ name }) => {
+        const { actions: { createCategoryRequest } } = this.props;
+        console.log('---- EXPRECTED PROMISE------', await createCategoryRequest({
+            name
+        }))
+    }
+    render() {
+        const { handleSubmit, handlers: { handelClick } } = this.props;
+        const { submit } = this;
+        return (
+            <form onSubmin={handleSubmit(submit)}>
+                <Field required name="name" type="name" placeholder="Add new Category" component={formInput} />
+                <button className="btn  btn-outline-light bg-stone m-3"
+                    type="button"  onClick={() => {
+                        handleSubmit(submit)();
+                    }
+                    }>
+                    Add
+                </button>
+            </form >
+        )
+    }
+}
+
+export default reduxForm({
+    form: "createCategoryForm"
+})(CreateCategoryForm);

+ 48 - 0
src/components/admin/addDeleteCategory/DeleteCategory.js

@@ -0,0 +1,48 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux'
+import { deleteCategoryRequest } from '../../../actions/admin/category/deleteCategory';
+
+
+
+class DeleteCategory extends React.Component {
+    state ={
+        click:true
+    }
+
+    onClick = () => {
+        const { deleteCategoryRequest, categorys: { id },click } = this.props;
+        console.log(
+        deleteCategoryRequest({
+            id
+        }))
+        this.setState(prevState=>console.log(prevState))
+    }
+
+
+
+    render() {
+        const { onClick } = this;
+        const {handlers:{deleteClick} } = this.props;
+        console.log(deleteClick)
+
+        return (
+            <div>
+                <button className="btn  btn-outline-light bg-stone m-3 right" type="button" onClick={()=>{
+                    deleteClick()
+                    onClick()
+                }
+                }
+                >Delete</button>
+            </div>
+
+        )
+    }
+
+}
+
+
+
+const mapDispatchToProps = dispatch => bindActionCreators({ deleteCategoryRequest }, dispatch);
+
+export default connect(null, mapDispatchToProps)(DeleteCategory);

+ 140 - 0
src/components/admin/addDeleteCategory/GetCategory.js

@@ -0,0 +1,140 @@
+import React from 'react';
+import { CSSTransition, TransitionGroup } from 'react-transition-group';
+import PropagateLoader from 'react-spinners/PropagateLoader';
+
+import CreateCategoryForm from "./CreateCategoryForm";
+import ChangeCategory from "./ChangeCategory";
+import DeleteCategory from './DeleteCategory';
+
+import store from './../../../state';
+
+
+class GetCategory extends React.Component {
+
+    state = {
+        click: false,
+        clicked: false,
+        categorys: { // categorIEs
+            id: null,
+            names: null
+        },
+        chpic: false,
+        massCategory: null,
+    }
+    componentDidMount() {
+        const { category } = this.props;
+        this.setState({ massCategory: category.data })
+    }
+
+    cclics = () => { //cliCKS
+        this.setState((prevState) => ({ click: !prevState.click }));
+
+    }
+    deleteClick = () => {
+        const { massCategory, categorys: { id } } = this.state;
+        for (let key in massCategory) {
+            if (massCategory[key]._id == id) {
+                delete massCategory[key]
+            }
+            else {
+            }
+        }
+        this.setState((prevState) => ({ clicked: !prevState.clicked }))
+    }
+
+    componentWillReceiveProps(nextProps) {
+        const { data, isFlag, actions: { changeCategoryRequest }, changeCategory } = nextProps;
+        const { massCategory } = this.state;
+
+        if (data) {
+            this.setState(prevState => {
+                this.setState({ massCategory: this.state.massCategory.concat(data) });
+                store.dispatch({
+                    type: 'wtfCreate'
+                })
+            })
+        }
+        if (changeCategory.data) {
+            for (const key in massCategory) {
+                if (massCategory[key]._id === changeCategory.data._id) {
+                    this.setState(prevState => {
+                        const categoriesArray = prevState.massCategory.slice();
+                        categoriesArray.splice(key, 1, changeCategory.data);
+
+                        return {
+                            massCategory: categoriesArray
+                        }
+                    })
+                    break;
+                }
+            }
+            store.dispatch({
+                type: 'wtfUpdate'
+            })
+        }
+
+        return true
+    }
+
+    onClicked = ({ mass: { _id, name } }) => {
+        this.setState({ categorys: { id: _id, name: name } })
+        this.setState((prevState) => ({ clicked: !prevState.clicked }))
+    }
+
+    render() {
+        const { actions: { createCategoryRequest, changeCategoryRequest }, data } = this.props;
+        const { category } = this.props;
+        const { handelClick, onClicked, deleteClick, changeCategoryClick } = this;
+        const { click, categorys, newCategory, massCategory, clicked } = this.state;
+        console.log(this.state)
+
+        return (
+            <div>
+            <div className="overflow-hidden padding profile-page  d-flex flex-row font-ci">
+                <div className="slideDown w-100 p-5 bg-gradient border rounded">
+                    <div className=" text-center  text-white font-ci font-ci-bold ">
+                    {
+                        massCategory !== null
+                            ?
+                            massCategory.map(mass =>
+                                <div className="btn " key={mass.id}>
+                                    <button class="btn btn-secondary font-ci font-ci-bold text-light bg-mist " onClick={onClicked.bind(null, { mass })} type="button" id={mass.id} key={mass.id} >
+                                        {mass.name}
+                                    </button>
+                                </div>
+
+                            )
+                            :
+                            null
+                    }
+                    <div>
+                        {
+                            click
+                                ?
+                                <CreateCategoryForm newCategory={newCategory} actions={{ createCategoryRequest }} handlers={{ handelClick }}></CreateCategoryForm>
+                                :
+                                <button className="btn  btn-outline-light bg-stone m-3" type='button' onClick={this.cclics}>Create Category</button>
+                        }
+                    </div>
+
+                </div>
+                {
+                    clicked
+                        ?
+                        <div>
+                            <ChangeCategory actions={{ changeCategoryRequest }} categorys={categorys} handlers={{ changeCategoryClick,deleteClick }}></ChangeCategory>
+                            {/* <DeleteCategory categorys={categorys} handlers={{  }} ></DeleteCategory> */}
+                        </div>
+                        :
+                        null
+                }
+                </div>
+                </div>
+            </div>
+        )
+    }
+
+}
+
+
+export default GetCategory;

+ 56 - 0
src/components/admin/addDeleteCategory/index.js

@@ -0,0 +1,56 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux'
+import { createCategoryRequest } from '../../../actions/admin/category/createCategory';
+import { changeCategoryRequest } from '../../../actions/admin/category/changeCategory';
+import { getCategoryRequest } from '../../../actions/admin/category/getCategory';
+import PropagateLoader from 'react-spinners/PropagateLoader';
+import GetCategory from './GetCategory'
+
+
+
+class AddDeleteCategory extends React.Component {
+    state = {
+        ckick: false
+    }
+    componentDidMount() {
+        const { getCategoryRequest } = this.props
+        getCategoryRequest()
+    }
+    onClick = () => {
+        this.setState((prevState) => ({ click: !prevState.click }));
+    }
+
+
+
+    render() {
+        const { category, createCategoryRequest, getCategoryRequest, changeCategoryRequest, newCategory: { data, isFlag }, changeCategory } = this.props
+        const { onClick } = this;
+
+        return (
+            <div>
+                {
+                    !category.isFlag
+                        ?
+                        <PropagateLoader />
+                        :
+                        <GetCategory actions={{ getCategoryRequest, createCategoryRequest, changeCategoryRequest }} category={category} data={data} isFlag={isFlag} changeCategory={changeCategory}></GetCategory>
+                }
+            </div>
+
+        )
+    }
+
+}
+
+const
+    mapStateToProps = state => ({
+        signIn: state.signIn,
+        category: state.category,
+        newCategory: state.newCategory,
+        changeCategory: state.changeCategory
+    });
+
+const mapDispatchToProps = dispatch => bindActionCreators({ createCategoryRequest, getCategoryRequest, changeCategoryRequest }, dispatch);
+
+export default connect(mapStateToProps, mapDispatchToProps)(AddDeleteCategory);

+ 71 - 0
src/components/admin/deleteUser/GetUsers.js

@@ -0,0 +1,71 @@
+import React from 'react';
+
+
+
+
+class GetUser extends React.Component {
+    state = {
+        arrayUsers: []
+    }
+    componentDidMount() {
+        const { user } = this.props;
+        this.setState({ arrayUsers: user })
+
+    }
+    componentWillReceiveProps(nextProps) {
+        const { isFetching, data, deleteUsers, initialValues} = nextProps;
+        const { arrayUsers } = this.state;
+        if (isFetching){
+            for (let key in arrayUsers) {
+                if (arrayUsers[key]._id == data._id) {
+                    this.setState(prevState => {
+                        const newArray = prevState.arrayUsers.slice();
+                        newArray.splice(key, 1, data)
+                        return {
+                            arrayUsers: newArray
+                        }
+                    })
+                    break;
+
+                }
+            }
+        }
+        if(deleteUsers.isFetching){
+            for (let key in arrayUsers) {
+                if (arrayUsers[key]._id ==initialValues._id) {
+                    this.setState(prevState => {
+                        const newArray = prevState.arrayUsers.slice();
+                        newArray.splice(key, 1)
+                        return {
+                            arrayUsers: newArray
+                        }
+                    })
+                    break;
+                }
+
+        }
+        }
+    }
+
+
+        render() {
+            const { handlers: { handelClick } } = this.props;
+            const { arrayUsers } = this.state;
+
+
+            return (
+                <div class="list-group">
+
+                    {arrayUsers && arrayUsers.map(el =>
+                        <button type="button" class="text-center overflow-hidden rounded-pill btn-outline-light btn mb-4 borber bg-rgba border-0  font-ci font-ci-bold " id={el._id} onClick={handelClick.bind(null, { el })}>{el.name}</button>
+                    )}
+                </div>
+
+            )
+        }
+    }
+
+
+
+
+    export default GetUser

+ 62 - 0
src/components/admin/deleteUser/changeUsers.js

@@ -0,0 +1,62 @@
+import React from 'react';
+
+import formInput from '../../common/formInput';
+import { Field, reduxForm } from 'redux-form';
+import validate from '../../../configs/validate'
+
+
+class ChangeUsers extends React.Component {
+
+
+    submit = ({ name, email, newPassword, confirmPassword }) => {
+        const { action: { changeUserRequest }, initialValues: { _id } } = this.props
+        changeUserRequest({
+            name,
+            email,
+            newPassword,
+            confirmPassword,
+            _id
+        })
+    }
+
+    deleteUser=()=>{
+        const {action:{deleteUsersRequest},initialValues: { _id }}=this.props
+        deleteUsersRequest({_id})
+        
+    }
+
+
+
+    render() {
+        const { initialValues, handleSubmit } = this.props;
+        const { submit, deleteUser } = this
+
+        return (
+            <div>
+
+                <form onSubmit={handleSubmit(submit)} className="ml-3 mr-3 mt-3">
+                    <h5 className="font-ci font-ci-bold text-white mb-3">User Name</h5>
+                    <Field name="name" type="name" component={formInput} className="form-control mb-3" />
+                    <h5 className="font-ci font-ci-bold text-white mb-3">Email</h5>
+                    <Field name="email" type="email" component={formInput} className="form-control mb-3"/>
+                    <h5 className="font-ci font-ci-bold text-white mb-3">Password</h5>
+                    <Field name="newPassword" type="password" placeholder="Enter login" component={formInput} className="form-control mb-3"/>
+                    <h5 className="font-ci font-ci-bold text-white mb-3">Confirm Password</h5>
+                    <Field name="confirmPassword" type="password" placeholder="Enter login" component={formInput} className="form-control mb-3"/>
+                    <button className= "btn  btn-outline-light bg-stone">Change</button>
+                    <button type="button" className= "btn  btn-outline-light bg-stone" onClick ={handleSubmit(deleteUser)} >Delete</button>
+                </form >
+            </div>
+
+        )
+    }
+
+}
+
+
+
+export default reduxForm({
+    form: "ChangeUserForm",
+    enableReinitialize: true,
+    validate
+})(ChangeUsers)

+ 74 - 0
src/components/admin/deleteUser/index.js

@@ -0,0 +1,74 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux'
+import { getUserRequest } from '../../../actions/admin/user/getUser';
+import { changeUserRequest } from '../../../actions/admin/user/changeUser';
+import { deleteUsersRequest } from '../../../actions/admin/user/deleteUser'
+import ChangeUser from './changeUsers';
+import GetUser from './GetUsers';
+import PropagateLoader from 'react-spinners/PropagateLoader';
+
+
+
+
+class DeleteUser extends React.Component {
+    state = {
+        initialValues: null,
+        flag: false
+    }
+    componentDidMount() {
+        const { getUserRequest } = this.props;
+        getUserRequest()
+
+    }
+    handelClick = ({ el }) => {
+        this.setState({ initialValues: el });
+        this.setState((prevState) => ({ flag: !prevState.flag }))
+    }
+
+    render() {
+        const { handelClick } = this
+        const { users: { user }, changeUserRequest, changeUser: { data, isFetching }, deleteUsers, deleteUsersRequest } = this.props;
+        const { initialValues, flag } = this.state;
+
+
+        return (
+            <div className="overflow-hidden profile-page d-flex flex-row font-ci padding ">
+                <div className='slideRight w-25 p-3 bg-gradient border rounded'  >
+                    <h4 class=" text-center  text-white font-ci font-ci-bold">USERS</h4>
+                    <div class="list-group">
+                        {
+                            user !== null
+                                ?
+                                <GetUser data={data} deleteUsers={deleteUsers} initialValues={initialValues} user={user} isFetching={isFetching} handlers={{ handelClick }}></GetUser>
+                                :
+                                <PropagateLoader />
+                        }
+                    </div>
+                </div>
+                <div className='w-75 p-3 bg-gradient ml-3 border rounded slideLeft'  >
+
+                    {
+                        flag
+                            ?
+                            <ChangeUser initialValues={initialValues} action={{ changeUserRequest, deleteUsersRequest }} ></ChangeUser>
+                            :
+                            null
+                    }
+                </div>
+            </div>
+        )
+    }
+
+}
+
+const
+    mapStateToProps = state => ({
+        users: state.users,
+        changeUser: state.changeUser,
+        deleteUsers: state.deleteUsers
+    });
+
+const mapDispatchToProps = dispatch => bindActionCreators({ getUserRequest, changeUserRequest, deleteUsersRequest }, dispatch);
+
+export default connect(mapStateToProps, mapDispatchToProps)(DeleteUser);

+ 106 - 0
src/components/admin/getChangeDeleteTest/GetQuestions.js

@@ -0,0 +1,106 @@
+import React from 'react';
+import { Field, reduxForm } from 'redux-form';
+// import {ChangeQuestion} from './changeQuestions'
+import formInput from '../../common/formInput'
+
+
+
+
+class GetQuestions extends React.Component {
+    state = {
+        id: null,
+        arrayQuestion: [],
+        questionS:{question:null}
+    }
+
+    componentWillMount = () => {
+        const { questions } = this.props;
+        console.log(questions)
+        this.setState({ arrayQuestion: questions })
+    }
+    changeQuestion = (event) => {
+        this.setState({questionS:{question:event.target.value}})
+    }
+  
+    submit =(payload)=>{
+console.log(payload)
+    }
+
+    deleteClick = ({ el: { _id } }) => {
+        this.setState({ id: _id })
+        const { actions: { deleteQuestionRequest } } = this.props;
+        deleteQuestionRequest({ _id })
+    }
+
+    componentWillUpdate(nextState, nextProps) {
+        const { deleteQuestion: { isFetching } } = nextState;
+        const { arrayQuestion, id } = nextProps;
+        if (!isFetching) {
+            for (let key in arrayQuestion) {
+                if (arrayQuestion[key]._id == id) {
+                    this.setState(prevState => {
+                        const array = prevState.arrayQuestion.slice()
+                        array.splice(key, 1)
+                        return {
+                            arrayQuestion: array
+                        }
+                    })
+                    break;
+                }
+            }
+
+        }
+    }
+
+    render() {
+        const { handleClick, deleteClick, changeQuestion } = this;
+        const{handleSubmit} =this.props
+        const { questionS:{question}, arrayQuestion } = this.state;
+        console.log(this.state)
+
+        return (
+            <div className=" profile-page p-4 d-flex flex-row font-ci">
+                <div className="container w-100 h-auto  bg-stone  bg-mist-border">
+                    <form onSubmit ={handleSubmit(this.submit)}>
+                        <Field name="name" type="name" component={formInput} />
+
+                        <select class="custom-select bg-mist bg-mist-op text-white mt-3 mb-3" onChange={changeQuestion} value={question} >
+                            <option selected>Open this Category menu</option>
+                            {
+                                arrayQuestion && arrayQuestion.map(el =>
+                                    <React.Fragment>
+                                        <option key={el._id} value={el.question}>{el.question}</option>
+                                        <button class="btn btn-secondary font-ci font-ci-bold text-light bg-mist " type="button"  >
+                                            P
+                                    </button>
+                                        <button class="btn btn-secondary font-ci font-ci-bold text-light bg-mist " onClick={deleteClick.bind(null, { el })} type="button"  >
+                                            X
+                                    </button>
+                                    </React.Fragment>
+                                )
+                            }
+                        </select>
+                        {
+                            question == null
+                                ?
+                                null
+                                :
+
+                        <Field name="question" type="question" component={formInput} />
+
+                        }
+
+                        <button>ssss</button>
+                    </form>
+                </div>
+            </div >
+        )
+    }
+
+}
+
+
+export default reduxForm({
+    form: "changeTestForm",
+    enableReinitialize: true
+})(GetQuestions)

+ 39 - 0
src/components/admin/getChangeDeleteTest/GetTest.js

@@ -0,0 +1,39 @@
+import React from 'react';
+
+
+
+class GetTest extends React.Component {
+    state = {
+        arrayTopic: [],
+        arrayCategory: []
+    }
+    componentWillMount() {
+        const { data } = this.props;
+        this.setState({ arrayCategory: data })
+    }
+
+    render() {
+
+        const { handlers:{getQuestionClick} } = this.props;
+        const { arrayTopic, topicElement, arrayCategory } = this.state
+
+        return (
+                <div className=' slideRight w-45 p-3 bg-gradient border rounded'  >
+                    {
+                        arrayCategory.map(el =>
+
+                            <div className="btn ">
+                                <button class="btn btn-secondary font-ci font-ci-bold text-light bg-mist " onClick={getQuestionClick.bind(null, { el })} type="button" id={el._id} key={el._id} >
+                                    {el.name}
+                                </button>
+                            </div>
+                        )
+                    }
+                </div>
+        )
+    }
+
+}
+
+
+export default GetTest;

+ 76 - 0
src/components/admin/getChangeDeleteTest/GetTopic.js

@@ -0,0 +1,76 @@
+import React from 'react';
+
+
+
+class GetTest extends React.Component {
+    state = {
+        arrayTopic: {
+            categotyId: null,
+            topic: null
+        }
+    }
+    componentWillMount() {
+        const { topic: { payload, topics } } = this.props;
+        this.setState({ arrayTopic: { categogyId: payload, topic: topics } })
+    }
+
+
+    componentWillUpdate(nextState, nextProps) {
+        const { newTopic, deleteTopic, topicId } = nextState;
+        const { arrayTopic: { topic } } = nextProps;
+        if (newTopic.data !== null) {
+            for (let key in topic) {
+                if (topic[key]._id == newTopic.data._id) {
+                    this.setState(prevState => {
+                        const array = prevState.arrayTopic.topic.slice()
+                        array.splice(key, 1, newTopic.data)
+                        return {
+                            arrayTopic: array
+                        }
+                    })
+                    break;
+                }
+            }
+
+        }
+        if (!deleteTopic.isFetching) {
+            for (let key in topic) {
+                if (topic[key]._id == topicId) {
+                    this.setState(prevState => {
+                        const array = prevState.arrayTopic.topic.slice()
+                        array.splice(key, 1)
+                        return {
+                            arrayTopic: array
+                        }
+                    })
+                    break;
+                }
+            }
+        }
+    }
+
+
+    render() {
+        const { handlers: { openEditModal } } = this.props;
+        const { arrayTopic: { topic } } = this.state
+
+        return (
+
+            <div className='slideLeft w-45 p-3 bg-gradient border rounded'  >
+                {
+                    topic && topic.map(el =>
+                        <div className="btn ">
+                            <button class="btn btn-secondary font-ci font-ci-bold text-light bg-mist " onClick={openEditModal.bind(null, { el })} type="button" id={el._id} key={el._id} >
+                                {el.name}
+                            </button>
+                        </div>)
+                }
+            </div>
+
+        )
+    }
+
+}
+
+
+export default GetTest;

+ 162 - 0
src/components/admin/getChangeDeleteTest/OpenModal.js

@@ -0,0 +1,162 @@
+import React, { Component } from "react";
+import { Modal } from "react-bootstrap";
+
+import { Field, reduxForm } from 'redux-form';
+import formInput from '../../common/formInput'
+
+class EditModal extends React.Component {
+    state = {
+        clicked: false,
+        answers_id: null,
+        answers: [],
+        clicks: false,
+        questionId: null
+    }
+
+    submit = (payload) => {
+        const { name, categoryId, description, question, simple, topicId } = payload
+        const { answers, questionId } = this.state
+        const { actions: { changeTestRequest } } = this.props;
+        changeTestRequest({ questionId, name, categoryId, description, question, simple, topicId, answers })
+
+    }
+
+    changeQuestion = (event) => {
+        const { value } = event.target
+        const { actions: { getAnswersRequest } } = this.props;
+        getAnswersRequest({ value })
+        this.setState((prevState) => ({ clicked: !prevState.clicked, }))
+        this.setState({ questionId: value })
+
+    }
+
+    answersChange = (event) => {
+        const { value } = event.target
+        this.setState({ clicks: true, answers_id: value })
+    }
+
+    changeAnswers = (payload) => {
+        const { answers_id } = this.state
+        const { answer, price, correct } = payload
+        const value = {
+            _id: answers_id,
+            answer: answer,
+            price: +price,
+            correct: correct
+        }
+        this.setState((prevState) => ({ answers: prevState.answers.concat(value) }))
+        this.setState({ clicks: false })
+
+    }
+
+    deleteAnswer = () => {
+        const { answers_id } = this.state
+        const { actions: { deleteAnswerRequest } } = this.props;
+        deleteAnswerRequest({ answers_id })
+
+    }
+
+    deleteQuestions = () => {
+        const { questionId } = this.state
+        const { actions: { deleteQuestionRequest } } = this.props;
+        deleteQuestionRequest({ questionId })
+    }
+
+    deleteTopic = (payload) => {
+        const { topicId } = payload
+        const { actions: { deleteTopicRequest } } = this.props;
+        deleteTopicRequest({ topicId })
+
+    }
+
+    render() {
+        const { visible, handleClose: { closeModal }, inputData, editLoads, initialValues, arrayQuestions: { questions, _id }, answers, handlers: { handelClick }, click, handleSubmit } = this.props;
+        const { submit, answersChange, changeAnswers, deleteAnswer, deleteQuestions, deleteTopic } = this
+        const { clicked, clicks } = this.state
+        return (
+            <Modal show={visible} onHide={closeModal} aria-labelledby="contained-modal-title-vcenter" >
+                < Modal.Header closeButton >
+                    < Modal.Title className="text-center  text-white font-ci font-ci-bold" >Changes Test  </ Modal.Title >
+                </ Modal.Header >
+                < Modal.Body >
+                    <h4 class="text-center  text-white font-ci font-ci-bold">Topic</h4>
+                    <form onSubmit={handleSubmit(submit)}>
+                        <Field name="name" type="name" component={formInput} className="form-control mb-3" />
+                        <h4 class="text-center  text-white font-ci font-ci-bold">Description</h4>
+                        <Field name="description" type="description" component={formInput} className="form-control mb-3" />
+
+                        <h4 class="text-center  text-white font-ci font-ci-bold">Questions</h4>
+                        <select class="custom-select bg-mist bg-mist-op text-white mt-3 mb-3" onChange={this.changeQuestion} >
+                            <option selected>Question</option>
+                            {questions !== null
+                                ?
+                                questions.map(el =>
+                                    <option key={el._id} name={el._id} value={el._id}>{el.question}</option>
+
+
+                                )
+                                : null
+                            }
+                        </select>
+                        {
+                            clicked
+                                ?
+                                <React.Fragment>
+                                    <h4 class="text-center  text-white font-ci font-ci-bold">Questions and Simple</h4>
+                                    <Field name="question" type="question" component={formInput} />
+                                    <Field name="simple" type="checkbox" component={formInput} />
+                                    <button className="btn  btn-outline-light bg-stone m-3" onClick={handleSubmit(deleteQuestions)} >Delete Question</button >
+                                </React.Fragment>
+                                : null
+                        }
+                        <ul class="list-group list-group-flush">
+                            {
+                                clicked
+                                    ?
+                                    <select class="custom-select bg-mist bg-mist-op text-white mt-3 mb-3" onChange={answersChange} >
+                                        <option selected>Aswers</option>
+                                        {answers !== null
+                                            ?
+                                            answers.map(el =>
+                                                <option key={el._id} name={el._id} value={el._id}>{el.answer}</option>
+
+
+                                            )
+                                            : null
+                                        }
+                                    </select>
+                                    : null
+                            }
+                            {
+                                clicks
+                                    ?
+                                    <React.Fragment>
+                                        <Field name="answer" type="answer" component={formInput} className="form-control mb-3" />
+                                        <Field name="correct" type="checkbox" component={formInput} />
+                                        <Field name="price" type="number" component={formInput} />
+                                        <div>
+                                            <button className="btn  btn-outline-light bg-stone m-3" onClick={handleSubmit(deleteAnswer)}>Delete Answer</button>
+                                            <button className="btn  btn-outline-light bg-stone m-3" onClick={handleSubmit(changeAnswers)} >Change Answers</button >
+                                        </div>
+                                    </React.Fragment>
+                                    : null
+                            }
+
+                        </ul>
+                    </form>
+                </ Modal.Body >
+                < Modal.Footer>
+                    <React.Fragment>
+                        <button className="btn  btn-outline-light bg-stone m-3" onClick={handleSubmit(deleteTopic)}>Delete Answer</button>
+                        <button type="submit" className="btn  btn-outline-light bg-stone m-3" onClick={handleSubmit(submit)} >Change</button>
+                    </React.Fragment>
+                </ Modal.Footer >
+            </Modal>
+        );
+    }
+}
+
+export default reduxForm({
+    form: "editModal",
+    enableReinitialize: true
+})(EditModal)

+ 112 - 0
src/components/admin/getChangeDeleteTest/changeQuestions.js

@@ -0,0 +1,112 @@
+import React from 'react';
+import { Field, reduxForm } from 'redux-form';
+import formInput from '../../common/formInput';
+
+
+
+
+class GetQuestions extends React.Component {
+    state = {
+        id: null,
+        arrayQuestion: [],
+        question:{
+        names: null
+        }
+    }
+
+    componentWillMount = () => {
+        const { questions } = this.props;
+        console.log(questions)
+        this.setState({ arrayQuestion: questions })
+    }
+
+    changeQuestion = (event) => {
+        this.setState({ question:{names: event.target.value} })
+    }
+
+    // handleClick =({el:{_id}})=>{
+    //     const {actions:{getQestionsRequest}} =this.props
+    //     console.log(_id)
+    //     getQestionsRequest({_id})
+
+    // }
+
+    deleteClick = ({ el: { _id } }) => {
+        this.setState({ id: _id })
+        const { actions: { deleteQuestionRequest } } = this.props;
+        deleteQuestionRequest({ _id })
+    }
+
+    componentWillUpdate(nextState, nextProps) {
+        const { deleteQuestion: { isFetching } } = nextState;
+        const { arrayQuestion, id } = nextProps;
+        console.log(isFetching, "nextState---------", nextState, "nextProps_________", nextProps)
+        if (!isFetching) {
+            for (let key in arrayQuestion) {
+                if (arrayQuestion[key]._id == id) {
+                    this.setState(prevState => {
+                        console.log("-------TRUE--------")
+                        const array = prevState.arrayQuestion.slice()
+                        array.splice(key, 1)
+                        return {
+                            arrayQuestion: array
+                        }
+                    })
+                    break;
+                }
+            }
+
+        }
+    }
+
+    render() {
+        const { handleClick, deleteClick, changeQuestion } = this;
+        const{question}=this.state
+        const { arrayQuestion } = this.state;
+        console.log(this.state)
+
+        return (
+            <div className=" profile-page p-4 d-flex flex-row font-ci">
+                <div className="container w-100 h-auto  bg-stone  bg-mist-border">
+                    <form >
+                        <Field name="name" type="name" component={formInput} />
+                        {
+                            question.names==null
+                        ?
+                        <select class="custom-select bg-mist bg-mist-op text-white mt-3 mb-3" onChange={changeQuestion} value={question} >
+                            <option selected>Open this Category menu</option>
+                            {
+                                arrayQuestion && arrayQuestion.map(el =>
+                                    <React.Fragment>
+                                        <option key={el._id} value={el.question}>{el.question}</option>
+                                        <button class="btn btn-secondary font-ci font-ci-bold text-light bg-mist " type="button"  >
+                                            P
+                                    </button>
+                                        <button class="btn btn-secondary font-ci font-ci-bold text-light bg-mist " onClick={deleteClick.bind(null, { el })} type="button"  >
+                                            X
+                                    </button>
+                                    </React.Fragment>
+                                )
+                            }
+                        </select>
+                        :
+                        <Field name="name" type="name" initialize ={this.state.question.names}component={formInput} />
+                        
+                        
+                        }
+                    </form>
+                </div>
+            </div >
+        )
+    }
+
+}
+
+
+export default reduxForm({
+    form: "changeTestForm",
+    enableReinitialize: true
+})(GetQuestions)
+
+
+

+ 125 - 0
src/components/admin/getChangeDeleteTest/index.js

@@ -0,0 +1,125 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux';
+import { getTopicRequest } from '../../../actions/admin/changeTest/getTopic';
+import { getQuestionsRequest } from '../../../actions/admin/changeTest/getQuestions';
+import { deleteTopicRequest } from '../../../actions/admin/changeTest/deleteTopic';
+import { deleteQuestionRequest } from '../../../actions/admin/changeTest/deleteQuestion';
+import { getCategoryRequest } from '../../../actions/admin/category/getCategory';
+import { getAnswersRequest } from '../../../actions/admin/changeTest/getAnswers';
+import { changeTestRequest } from '../../../actions/admin/changeTest/changeTest';
+import { deleteAnswerRequest } from '../../../actions/admin/changeTest/deleteAnswer';
+
+
+
+
+import GetTest from './GetTest';
+import GetTopic from './GetTopic';
+import EditModal from './OpenModal';
+
+
+
+
+class ChangeTest extends React.Component {
+    state = {
+
+        categoryId: null,
+        name: null,
+        topicId: null,
+        description: null,
+        answers: [],
+        answer: null,
+        correct: null,
+        price: null,
+        simple: null,
+        openModal: false,
+        toggleModal: false,
+        click: false
+
+    }
+
+    openEditModal = ({ el: { _id, description, name } }) => {
+        const { getQuestionsRequest } = this.props
+        getQuestionsRequest({ _id })
+        this.setState(({ openModal: true, toggleModal: false, topicId: _id, description: description, name: name }))
+    }
+
+    closeModal = () => { this.setState((prevState) => ({ openModal: !prevState.openModal })) }
+
+    getQuestionClick = ({ el: { _id } }) => {
+        const { getTopicRequest } = this.props
+        getTopicRequest({ _id })
+        this.setState({ categoryId: _id })
+    }
+
+    handelClick = ({ el: { answer, correct, price, _id } }) => {
+        this.setState({ answer: answer, corrent: correct, price: price });
+        this.setState((prevState) => ({ click: !prevState.click }))
+    }
+
+    componentWillMount = () => {
+        const { getCategoryRequest } = this.props
+        getCategoryRequest()
+    }
+    componentWillReceiveProps(nextProps) {
+        const { arrayAnswers: { answers } } = nextProps;
+        if (answers !== null) {
+            this.setState({ answers: answers })
+        }
+    }
+
+
+    render() {
+        const { getQuestionClick, openEditModal, closeModal, handelClick, state } = this;
+        const { openModal, questionId, name, topicId, description, answers, click } = this.state
+        const initialValues = {
+            ...state
+        }
+        const { category: { data, isFlag }, deleteTopic, topic, arrayQuestions, getAnswersRequest, deleteTopicRequest, arrayAnswers, changeTestRequest, newTopic, deleteAnswerRequest, deleteQuestionRequest } = this.props
+
+        return (
+            <div className=" profile-page  font-ci padding ">
+
+                {
+                    !isFlag
+                        ?
+                        null
+                        :
+                        <React.Fragment>
+                            <GetTest data={data} handlers={{ getQuestionClick }}></GetTest>
+                            {
+                                topic.isFlag
+                                    ?
+                                    <React.Fragment>
+                                        <GetTopic handlers={{ openEditModal }} topicId={topicId} deleteTopic={deleteTopic} newTopic={newTopic} topic={topic}></GetTopic>
+                                        <EditModal className="bg-mist" visible={openModal} handlers={{ handelClick }} click={click} answers={answers} actions={{ getAnswersRequest, deleteTopicRequest, deleteAnswerRequest, deleteQuestionRequest, changeTestRequest }} arrayQuestions={arrayQuestions} initialValues={initialValues}
+                                            handleClose={{ closeModal }}></EditModal>
+                                    </React.Fragment>
+                                    :
+                                    null
+
+                            }
+
+                        </React.Fragment>
+                }
+            </div>
+        )
+    }
+
+}
+
+const
+    mapStateToProps = state => ({
+        topic: state.topic,
+        arrayQuestions: state.arrayQuestions,
+        deleteTopic: state.deleteTopic,
+        deleteQuestion: state.deleteQuestion,
+        category: state.category,
+        arrayAnswers: state.arrayAnswers,
+        newTopic: state.newTopic
+
+    });
+
+const mapDispatchToProps = dispatch => bindActionCreators({ getCategoryRequest, deleteAnswerRequest, getTopicRequest, changeTestRequest, getQuestionsRequest, deleteTopicRequest, deleteQuestionRequest, getAnswersRequest }, dispatch);
+
+export default connect(mapStateToProps, mapDispatchToProps)(ChangeTest);

+ 9 - 0
src/components/common/formInput.js

@@ -0,0 +1,9 @@
+import React, { Fragment } from 'react';
+
+export default ({ input, className, placeholder, required, type, meta: { touched, error } }) => (
+    <Fragment>
+        <input className={className} placeholder={placeholder} type={type} {...input}/>
+        {touched && (error && <p className="text-af pt-2 text-uppercase">⚠ {error}</p>)}
+        {required ? <p className="text-af pt-2 text-uppercase">⚠ Reqired</p> : null}
+    </Fragment>
+)

+ 50 - 0
src/components/common/protectedRoute.js

@@ -0,0 +1,50 @@
+import React from 'react';
+import { Route, Redirect } from 'react-router-dom';
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux';
+import { inactiveToken, activeToken } from './../../actions/auth/tokenCheckout'
+import decode from 'jwt-decode';
+
+import * as routes from './../../constants/routes';
+import storageKey from './../../utils/storageKey';
+
+const protectedRoute = ({ component: Component, activeToken, inactiveToken, access, ...rest }) => (
+    <Route
+        {...rest}
+        render={props => {
+            try {
+                const user = decode(localStorage.getItem(storageKey));
+                activeToken(user.role);
+                {/* if (user.exp < Date.now()*1000) {
+                    throw new Error('Date expired');
+                } */}
+
+                if (access === 'admin-only' && !user.role) {
+                    throw new Error('Permission Denied')
+                }
+
+                return <Component {...props} />
+            }
+            catch ({ message }) {
+                if (message === 'Permission Denied') {
+                    return <div>Permission denied</div>
+                }
+
+                inactiveToken();
+
+                if (access === 'public') {
+                    return <Component {...props} />
+                }
+
+                return <Redirect to={routes.SIGN_IN} />
+            }
+        }}
+    />
+)
+
+const mapDispatchToProps = dispatch => bindActionCreators({
+    activeToken,
+    inactiveToken
+}, dispatch);
+
+export default connect(null, mapDispatchToProps)(protectedRoute);

+ 9 - 0
src/components/common/spinner.js

@@ -0,0 +1,9 @@
+import React from 'react';
+
+export default () => (
+    <div className="container d-flex align-items-center justify-content-center">
+        <div class="spinner-border" role="status">
+            <span class="sr-only">Loading...</span>
+        </div>
+    </div>
+)

+ 120 - 0
src/components/public/Header.js

@@ -0,0 +1,120 @@
+import React, { PureComponent } from 'react';
+import { Link, withRouter, Redirect } from "react-router-dom";
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux';
+import axios from 'axios';
+
+import storageKey from './../../utils/storageKey';
+import { signInStateZeroing } from './../../actions/auth/signIn';
+import { LOG_OUT_URL } from './../../constants/auth';
+
+import * as routes from '../../constants/routes';
+
+//pure component + make storage check an action -> connect router
+class Header extends PureComponent {
+    handleLogOut = () => {
+        console.log(this.props)
+        const { history, zeroState } = this.props;
+
+        axios.get(LOG_OUT_URL, {})
+            .then(() => {
+                console.log('request was succesfull')
+                localStorage.removeItem(storageKey);
+                zeroState();
+                history.push('/sign-in');
+            })
+            .catch(e => alert('Sorry, something bad happened, try log out later \n' + e.message));
+    }
+
+    render() {
+        const { role } = this.props;
+
+        return (
+
+            <nav class="navbar navbar-expand-lg navbar-expand-lg bg-gradient1 p-4 position-absolute w-100 ">
+                <Link to={routes.LANDING} class="navbar-brand font-label text-af" href="#">Test.io</Link>
+                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
+                    <span class="navbar-toggler-icon" />
+                </button>
+
+                <div class="collapse navbar-collapse" id="navbarSupportedContent">
+                    <ul class="navbar-nav mr-auto">
+                        <li class="nav-item active">
+                            <Link onClick={this.handleClick} class="nav-link text-shadow font-ci font-ci-bold" to={routes.HOME}>Home <span class="sr-only">(current)</span></Link>
+                        </li>
+                        <li class="nav-item">
+                            <Link onClick={this.handleClick} class="nav-link text-shadow font-ci font-ci-bold" to={routes.PROFILE}>Profile</Link>
+                        </li>
+                        <li class="nav-item">
+                            <Link onClick={this.handleClick} class="nav-link text-shadow font-ci font-ci-bold " to={routes.TESTS}>Tests</Link>
+                        </li>
+                        <li class="nav-item">
+                            <Link onClick={this.handleClick} class="nav-link text-shadow font-ci font-ci-bold " to={routes.CATEGORIES}>Catigories</Link>
+
+                        </li>
+                        {role
+                                ?
+                        <li class="nav-item dropdown">
+
+                            <a class="nav-link text-shadow font-ci font-ci-bold" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                Menu Admin
+                                </a>
+                            <div class="dropdown-menu" aria-labelledby="navbarDropdown">
+                            <Link to={routes.DELETE_USER} className="nav-link text-secondary text-shadow font-ci">Delete User</Link>
+                                <Link to={routes.CREATE_TEST} className="nav-link text-secondary text-shadow font-ci">Create Test</Link>
+                                <Link to={routes.CHANGE_TEST} className="nav-link text-secondary text-shadow font-ci">Change Test</Link>
+                                
+                                <Link to={routes.CREATE_CATEGORY} className="nav-link text-secondary text-shadow font-ci">Create Category</Link>
+
+                                
+                            </div>
+                        </li>
+                                
+                                :
+                                null
+                        }
+                    </ul>
+                    
+                    <div className="controls">
+                        {
+                            role !== null
+                                ?
+                                <button onClick={this.handleLogOut} className="btn  btn-outline-light ml-2 bg-stone">Log Out</button>
+                                :
+                                <React.Fragment>
+                                    <Link to={routes.SIGN_IN}>
+                                        <button className="btn  btn-outline-light ml-2 bg-stone">Sign In</button>
+                                    </Link>
+                                    <Link to={routes.SIGN_UP}>
+                                        <button className="btn  btn-outline-light ml-2 bg-stone">Sign Up</button>
+                                    </Link>
+                                </React.Fragment>
+                        }
+{/* =======
+
+                    <div className="">
+                        <Link to={routes.SIGN_IN}>
+                            <button className="btn  btn-outline-light bg-stone">Sign In</button>
+                        </Link>
+                        <Link to={routes.SIGN_UP}>
+                            <button className="btn  btn-outline-light ml-2 bg-stone">Sign Up</button>
+
+                        </Link>
+                        <button onClick={this.handleLogOut} className="btn btn-outline-primary">Log Out</button>
+>>>>>>> new_Sveta */}
+                    </div>
+                </div>
+            
+            </nav>
+        )
+    }
+}
+
+const mapStateToProps = state => ({
+    role: state.tokenCheckout.role,
+});
+const mapDispatchToProps = dispatch => bindActionCreators({
+    zeroState: signInStateZeroing
+}, dispatch)
+
+export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Header));

+ 32 - 0
src/components/public/landing.js

@@ -0,0 +1,32 @@
+import React from 'react';
+
+const landing = () => (
+    <div id="carouselExampleIndicators" className="carousel slide" data-ride="carousel">
+        <ol className="carousel-indicators">
+            <li data-target="#carouselExampleIndicators" data-slide-to="0" className="active"></li>
+            <li data-target="#carouselExampleIndicators" data-slide-to="1"></li>
+            <li data-target="#carouselExampleIndicators" data-slide-to="2"></li>
+        </ol>
+        <div className="carousel-inner">
+            <div className="carousel-item active">
+                <img src="https://images.theconversation.com/files/17962/original/jt558trs-1353642967.jpg?ixlib=rb-1.1.0&rect=23%2C5%2C3831%2C2573&q=45&auto=format&w=926&fit=clip" className="d-block w-100 slider-image" alt="..." />
+            </div>
+            <div className="carousel-item">
+                <img src="http://dyslexiahelp.umich.edu/sites/default/files/upload/testing%20instuments%20dreamstimesmall_5908127.jpg" className="d-block w-100 slider-image" alt="..." />
+            </div>
+            <div className="carousel-item">
+                <img src="https://amp.businessinsider.com/images/55a7e74f2acae716008b7469-750-562.jpg" className="d-block w-100 slider-image" alt="..." />
+            </div>
+        </div>
+        <a className="carousel-control-prev" href="#carouselExampleIndicators" role="button" data-slide="prev">
+            <span className="carousel-control-prev-icon" aria-hidden="true"></span>
+            <span className="sr-only">Previous</span>
+        </a>
+        <a className="carousel-control-next" href="#carouselExampleIndicators" role="button" data-slide="next">
+            <span className="carousel-control-next-icon" aria-hidden="true"></span>
+            <span className="sr-only">Next</span>
+        </a>
+    </div>
+)
+
+export default landing;

+ 58 - 0
src/components/public/signIn/Form/index.js

@@ -0,0 +1,58 @@
+import React from 'react';
+import { reduxForm, Field } from 'redux-form';
+import validate from './validate';
+import formInput from './../../../common/formInput';
+
+class Form extends React.Component {
+
+    submit = ({ email, password }) => {
+        const { signIn } = this.props;
+        signIn({
+            email,
+            password
+        })
+    }
+
+    render() {
+        const { handleSubmit, requestError, invalid } = this.props;
+
+
+        return (
+            <div className="container p-5">
+                <div className="row">
+                    <div className="col-md-8 col-4 col-lg-5 m-auto p-4  border rounded">
+                        <h1 className = "position-absolute pl-5 pr-5 sinein bg-white text-stone">SignIn</h1>
+
+                        <form className="text-center" onSubmit={handleSubmit(this.submit)}>
+                            {
+                                requestError
+                                    ?
+                                    <p className="text-af text-uppercase">{requestError}</p>
+                                    :
+                                    null
+                            }
+
+                            <div className="form-group">
+                                <label className="text-uppercase font-ci">Email address</label>
+                                <Field type="email" name='email' className="form-control" placeholder="name@example.com" component={formInput} />
+                            </div>
+
+                            <div className="form-group">
+                                <label className="text-uppercase font-ci">Password</label>
+                                <Field type="password" name='password' className="form-control" component={formInput} />
+                            </div>
+
+                            <button type="submit" className="btn btn-primary" disabled={invalid}>Sign In!</button>
+                        </form>
+                    </div>
+                </div>
+                
+            </div>
+        )
+    }
+}
+
+export default reduxForm({
+    form: "SignIn",
+    validate
+})(Form)

+ 14 - 0
src/components/public/signIn/Form/validate.js

@@ -0,0 +1,14 @@
+export default function validate(values) {
+    const { email, password } = values;
+    const errors = {};
+
+    if (!email) {
+        errors.email = "Required";
+    }
+
+    if (!password) {
+        errors.password = "Required"
+    }
+
+    return errors;
+}

+ 51 - 0
src/components/public/signIn/index.js

@@ -0,0 +1,51 @@
+import React from 'react';
+import Form from './Form';
+import { bindActionCreators } from 'redux';
+import { connect } from 'react-redux';
+import { Redirect } from 'react-router-dom'
+
+import PropagateLoader from 'react-spinners/PropagateLoader';
+
+import Spinner from './../../common/spinner';
+import signIn from './../../../actions/auth/signIn';
+
+
+
+const SignIn = ({ signIn, user }) => {
+// <<<<<<< HEAD
+    return (
+        user.isFetching
+// =======
+//     const someShit = user.isFetching
+//         ?
+//          <PropagateLoader/>
+//         : user.data
+// >>>>>>> new_Sveta
+            ?
+            <Spinner />
+            : user.data
+                ?
+                <Redirect to='/' />
+                : user.error
+                    ?
+                    (
+                        <React.Fragment>
+                            <Form signIn={signIn} requestError={user.error} />
+                        </React.Fragment>
+                    )
+                    :
+                    <Form signIn={signIn} />
+    )
+}
+
+
+
+const mapStateToProps = state => ({
+    user: state.signIn,
+});
+const mapDispatchToProps = dispatch => bindActionCreators({
+    signIn
+}, dispatch);
+
+
+export default connect(mapStateToProps, mapDispatchToProps)(SignIn);

+ 63 - 0
src/components/public/signUp/Form/index.js

@@ -0,0 +1,63 @@
+import React from 'react';
+import { reduxForm, Field } from 'redux-form';
+
+import validate from './validate';
+import formInput from './../../../common/formInput';
+
+class Form extends React.Component {
+
+    submit = ({ name, email, password }) => {
+        const { signUp } = this.props;
+        signUp({
+            name,
+            email,
+            password
+        })
+    }
+
+    render() {
+        const { handleSubmit, requestError, invalid } = this.props;
+
+        return (
+            <div className="container">
+                <div className="row">
+                    <div className="col-md-8 col-10 col-lg-6 m-auto p-4 border rounded">
+
+                        <form className="text-center" onSubmit={handleSubmit(this.submit)}>
+                            {
+                                requestError
+                                    ?
+                                    <p className="text-af text-uppercase">{requestError}</p>
+                                    :
+                                    null
+                            }
+
+                            <div className="form-group border p-4">
+                                <label className="text-uppercase">Name</label>
+                                <Field type="text" name='name' className="form-control" placeholder="example" component={formInput} />
+
+                                <label className="text-uppercase pt-3">Email address</label>
+                                <Field type="email" name='email' className="form-control" placeholder="name@example.com" component={formInput} />
+                            </div>
+
+                            <div className="form-group border p-4">
+                                <label className="text-uppercase">Password</label>
+                                <Field type="password" name='password' className="form-control" component={formInput} />
+
+                                <label className="text-uppercase pt-3">Password Confirmation</label>
+                                <Field type="password" name='passwordConfirmation' className="form-control" component={formInput} />
+                            </div>
+
+                            <button type="submit" className="btn btn-primary" disabled={invalid}>Sign In!</button>
+                        </form>
+                    </div>
+                </div>
+            </div>
+        )
+    }
+}
+
+export default reduxForm({
+    form: "SignUp",
+    validate
+})(Form)

+ 47 - 0
src/components/public/signUp/Form/validate.js

@@ -0,0 +1,47 @@
+export default function validate(values) {
+    const { name, email, password, passwordConfirmation } = values;
+    const errors = {};
+
+    if (!email) {
+        errors.email = "Required";
+    }
+    else if (email.length < 8 || email.length > 20) {
+        errors.email = "Invalid email length: email should be from 8 to 20 symbols";
+    }
+    else if (
+        !/^(([^<>()\]\\.,;:\s@"]+(\.[^<>()\]\\.,;:\s@"]+)*)|(".+"))@(([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(email)) {
+        errors.email = "Invalid email, try another one";
+    }
+
+    if (!name) {
+        errors.name = "Required";
+    }
+    else if (name.length < 6 || name.length > 10) {
+        errors.name = "Invalid name length: name should be from 6 to 10 symbols";
+    }
+    else if (!/^[_A-z0-9]*((-|\s)*[_A-z0-9])*$/.test(name)) {
+        errors.name = "Invalid name, try another one"
+    }
+    
+    if (!password) {
+        errors.password = "Required"
+    }
+    else if (/[,]/.test(password)) {
+        errors.password = "Invalid symbol: \",\" is not allowed!";
+    }
+    else if (password.length < 8 || password.length > 20) {
+        errors.password = "Invalid password length: password should be from 8 to 20 symbols";
+    }
+    else if (!/^[a-z0-9_-]{8,20}$/i.test(password)) {
+        errors.password = "Invalid password, try another one";
+    }
+
+    if (!passwordConfirmation) {
+        errors.passwordConfirmation = "Required";
+    }
+    else if (password !== passwordConfirmation) {
+        errors.passwordConfirmation = "Passwords don't match each other!";
+    }
+
+    return errors;
+}

+ 31 - 0
src/components/public/signUp/index.js

@@ -0,0 +1,31 @@
+import React from 'react';
+import Form from './Form';
+import { bindActionCreators } from 'redux';
+import { connect } from 'react-redux';
+import { Redirect } from 'react-router-dom';
+
+import Spinner from './../../common/spinner';
+import signUp from './../../../actions/auth/signUp';
+
+const SignUp = ({ status, signUp }) => (
+    status.isFetching
+        ?
+        <Spinner />
+        : status.isSuccessful
+            ?
+            <Redirect to='/sign-in' />
+            : status.error
+                ?
+                <Form signUp={signUp} requestError={status.error} />
+                :
+                <Form signUp={signUp} />
+)
+
+const mapStateToProps = state => ({
+    status: state.signUp
+});
+const mapDispatchToProps = dispatch => bindActionCreators({
+    signUp
+}, dispatch);
+
+export default connect(mapStateToProps, mapDispatchToProps)(SignUp);

+ 63 - 0
src/components/user/Categoty.js

@@ -0,0 +1,63 @@
+import React from 'react';
+import { Link } from "react-router-dom";
+
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux'
+import { getCategoryRequest } from '../../actions/admin/category/getCategory';
+import * as routes from '../../constants/routes';
+
+
+
+
+class AddDeleteCategory extends React.Component {
+    state = {
+        ckick: false
+    }
+    componentDidMount() {
+        const { getCategoryRequest } = this.props
+        getCategoryRequest()
+    }
+
+
+
+
+    render() {
+        const { category:{data}  } = this.props
+        // console.log(category)
+
+        return (
+                  <div className="slideDown padding profile-page  d-flex flex-row font-ci">
+                <div className="w-100 m-5 bg-gradient border rounded">
+                    <div className=" m-5 text-center  text-white font-ci font-ci-bold ">
+                        {
+                            data !== null
+                                ?
+                                data.map(mass =>
+                                    <div className="btn " key={mass.id}>
+                                        <button class="btn btn-secondary font-ci font-ci-bold text-light bg-mist " type="button" id={mass.id} key={mass.id} >
+                                        <Link  class="font-ci font-ci-bold text-light" to={routes.TESTS}>{mass.name}</Link>
+                                        </button>
+                                    </div>
+
+                                )
+                                :
+                                null
+                        }
+
+                    </div>
+                </div>
+            </div>
+
+        )
+    }
+
+}
+
+const
+    mapStateToProps = state => ({
+        category: state.category,
+    });
+
+const mapDispatchToProps = dispatch => bindActionCreators({getCategoryRequest}, dispatch);
+
+export default connect(mapStateToProps, mapDispatchToProps)(AddDeleteCategory);

+ 44 - 0
src/components/user/ProfilePage/ChangeEmailForm/index.js

@@ -0,0 +1,44 @@
+import React from 'react';
+import { Field, reduxForm } from 'redux-form';
+
+import formInput from '../../../common/formInput';
+
+class ChangeEmailForm extends React.Component {
+
+    submit = ({email}) => {
+        const {actions:{changeEmailRequest},data:{_id},token } = this.props
+
+        changeEmailRequest({
+            token,
+           _id,
+            email
+        })
+        
+    }
+
+    render() {
+        const { children, handleSubmit, actions:{changeEmailRequest}, handlers: {  handleClick, handleClicks }, data, token } = this.props;
+        const { submit}=this
+        return (
+            <form onSubmit={handleSubmit(submit)} >
+                <Field name="email" type="email" placeholder="Enter new login" component={formInput} className="bg-rgba1 border" />
+                <button
+                    type="button" className="link link--btn right flex-fill bg-shadow btn text-white font-ci font-ci-bold col-3"  onClick={
+                        function() {
+                        handleClicks();
+                            handleSubmit(submit)();
+                        }    
+                    
+                    }>
+                    Change
+                </button>
+            </form >
+        )
+    }
+}
+
+export default reduxForm({
+    form: "changeEmailForm",
+    enableReinitialize: true
+
+})(ChangeEmailForm);

+ 43 - 0
src/components/user/ProfilePage/ChangeLoginForm/index.js

@@ -0,0 +1,43 @@
+import React from 'react';
+import { Field, reduxForm } from 'redux-form';
+
+import formInput from '../../../common/formInput';
+
+class ChangeLoginForm extends React.Component {
+
+    submit = ({ name}) => {
+        const {actions:{changeLoginRequest},data:{_id},token } = this.props
+
+        changeLoginRequest({
+            token,
+           _id,
+            name
+        })
+        
+    }
+
+    render() {
+        const { children, handleSubmit, actions:{changeLoginRequest}, handlers: {  handleClick }, data, token } = this.props;
+        const { submit}=this
+
+        return (
+            <form onSubmit={handleSubmit(submit)} >
+                <Field name="name" type="email" placeholder="Enter new login" component={formInput} className="bg-rgba1 border" />
+                <button
+                    type="button" className="link link--btn right flex-fill bg-shadow btn text-white font-ci font-ci-bold col-3"  onClick={
+                        function() {
+                        handleClick();
+                            handleSubmit(submit)();
+                        }    
+                    
+                    }>
+                    Change
+                </button>
+            </form >
+        )
+    }
+}
+
+export default reduxForm({
+    form: "changeLoginForm",
+})(ChangeLoginForm);

+ 0 - 0
src/components/user/ProfilePage/ChangeLoginForm/validate/index.js


+ 47 - 0
src/components/user/ProfilePage/changePassword/index.js

@@ -0,0 +1,47 @@
+import React from 'react';
+import { Field, reduxForm } from 'redux-form';
+import validate from '../../../../configs/validate'
+
+import formInput from '../../../common/formInput';
+
+class ChangePasswordForm extends React.Component {
+
+    submit = ({password, confirmPassword }) => {
+        const {actions:{changePasswordRequest},data:{_id},token } = this.props
+
+        changePasswordRequest({
+            token,
+           _id,
+            password,
+            confirmPassword
+        })
+        
+    }
+
+    render() {
+        const { children, handleSubmit, actions:{ changePasswordRequest }, handlers: {  handleClicked }, data, token } = this.props;
+        const { submit}=this
+        return (
+            <form onSubmit={handleSubmit(submit)} >
+                <Field name="password" type="password" placeholder="Password" className ='' component={formInput} className="bg-rgba1 border" />
+                <Field name="confirmPassword" type="password" placeholder="new Password" component={formInput} className="bg-rgba1 border"/>
+
+                <button
+                    type="button" className="link link--btn flex-fill bg-shadow btn text-white font-ci font-ci-bold col-3 "  onClick={
+                        function() {
+                        handleClicked();
+                            handleSubmit(submit)();
+                        }    
+                    
+                    }>
+                    Change
+                </button>
+            </form >
+        )
+    }
+}
+
+export default reduxForm({
+    form: "changePasswordForm",
+    validate
+})(ChangePasswordForm);

+ 131 - 0
src/components/user/ProfilePage/index.js

@@ -0,0 +1,131 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux'
+import ChangeLoginForm from './ChangeLoginForm/index';
+import ChangeEmailForm from './ChangeEmailForm/index';
+import ChangePasswordForm from './changePassword/index'
+import {changeLoginRequest} from '../../../actions/user/changelogin';
+import {changeEmailRequest} from '../../../actions/user/changeEmail';
+import {changePasswordRequest } from '../../../actions/user/changePassword';
+import {myUserRequest} from '../../../actions/admin/meUser'
+
+class ProfilePage extends React.Component {
+    
+    state={
+        clicked:false,
+        klick: false,
+        click: false
+    }
+    componentDidMount(){
+        const {myUserRequest} =this.props
+        myUserRequest()
+    }
+
+    handleClick = () => {
+        this.setState((prevState) => ({ clicked: !prevState.clicked }));
+    }
+    handleClicks = () => {
+        this.setState((prevState) => ({ klick: !prevState.klick }));
+    }
+    handleClicked = () => {
+        this.setState((prevState) => ({ click: !prevState.click }));
+    }
+
+    render() {
+
+        const { myUser:{data, token}, changeLoginRequest, chageLoginReducer, changeEmailRequest, changeEmailReducer, changePasswordRequest} = this.props;
+        const {clicked, klick, click} =this.state;
+        const {handleClick, handleClicks, handleClicked} = this;
+
+
+        return (
+            <div className="slideDown page page--bottom-only profile-page bg-img d-block w-100 slider-image padding" >
+                <div className="border bg-rgba rounded d-flex  ">
+                    <div>
+                    <div>
+
+                        <img className="m-4 " src=" https://ru.opensuse.org/images/0/0b/Icon-user.png" ></img>
+                    </div>
+                    </div>
+                    <div className="border-left bg-autumn-foliage m-5 rounded w-75 text-white font-ci font-ci-bold">
+                            {!clicked
+                            ?
+                        <div  className ="d-flex mb-3" >
+                            <h3 className = " p-2 flex-fill bd-highlight ">Name</h3>
+                            <h5 className="p-2 font-po-bold flex-fill bd-highlight align-self-end">{
+                                chageLoginReducer.data == null
+                                ?
+                                data&&data.name 
+                                :
+                                chageLoginReducer.data
+
+                    
+                                }</h5> 
+                             <button type="button" onClick ={handleClick}  className=" flex-fill bg-shadow btn text-white font-ci font-ci-bold col-3">Change</button>
+                        </div>
+                        :
+                        <div className ="d-flex mb-3">
+                        <h3 className = " p-2 flex-fill bd-highlight">Name</h3>
+                        <ChangeLoginForm  data ={data} initialValues={data} token={token} actions ={{changeLoginRequest}} handlers={{ handleClick}}> </ChangeLoginForm>
+                        </div>
+                            }
+                            {!klick
+                            ?
+                        <div  className ="d-flex mb-3" >
+                            <h3 className = "p-2 flex-fill bd-highlight">Email</h3>
+                            <h5 className="p-2 flex-fill font-po-bold bd-highlight align-self-end">
+                                {
+                                    changeEmailReducer.data ===null
+                                    ?
+                                    data&&data.email
+                                    :
+                                    changeEmailReducer.data
+                                } 
+                             </h5>
+                            <button type="button" name ="name"  onClick ={handleClicks} className=" flex-fill bg-shadow btn text-white font-ci font-ci-bold col-3">Change</button>
+                        </div>
+                        :
+                        <div  className ="d-flex mb-3" >
+
+                            <h3 className = "p-2 flex-fill bd-highlight">Email</h3>
+                            <ChangeEmailForm  data ={data} token={token} initialValues={data} actions ={{changeEmailRequest}} handlers={{ handleClicks}}></ChangeEmailForm>
+                        </div>
+                            }
+                            {
+                                !click
+                                ?
+                        <div  className ="d-flex mb-3" >
+
+                            <h3 className = "p-2 flex-fill bd-highlight">Password</h3>
+                            <button type="button" onClick ={handleClicked} className=" flex-fill bg-shadow btn text-white font-ci font-ci-bold col-3">Change</button>
+                        </div> 
+                         :
+                        <div  className ="d-flex mb-3" >
+                            <h3 className = "p-2 flex-fill bd-highlight">Password</h3>
+                           <ChangePasswordForm data ={data} token={token} actions ={{changePasswordRequest}} handlers={{ handleClicked}}></ChangePasswordForm>
+
+                        </div>
+                            }
+                 
+                    </div>
+                </div>
+                </div>
+                
+                
+                
+            
+        )
+    }
+
+}
+
+const
+    mapStateToProps = state => ({
+        myUser:state.myUser,
+        chageLoginReducer: state.chageLoginReducer,
+        changeEmailReducer:state.changeEmailReducer
+    });
+
+const mapDispatchToProps = dispatch => bindActionCreators({changeLoginRequest, changeEmailRequest, changePasswordRequest, myUserRequest}, dispatch);
+
+export default connect(mapStateToProps, mapDispatchToProps)(ProfilePage);

+ 25 - 0
src/components/user/Test/ModalSommary.js

@@ -0,0 +1,25 @@
+import React, { Component } from "react";
+import { Modal } from "react-bootstrap";
+
+
+class ModalSummary extends React.Component {
+
+
+    render() {
+        const{clickModal, summary, handlers:{closeModal}}= this.props
+        return (
+            <Modal show={clickModal} onHide={closeModal} aria-labelledby="contained-modal-title-vcenter" >
+                < Modal.Header closeButton >
+                    < Modal.Title className="text-center  text-white font-ci font-ci-bold" >Summary </ Modal.Title >
+                </ Modal.Header >
+                < Modal.Body >
+                    <h4>{summary}</h4>
+                </ Modal.Body >
+                < Modal.Footer>
+                </ Modal.Footer >
+            </Modal>
+        );
+    }
+}
+
+export default ModalSummary

+ 60 - 0
src/components/user/Test/getTest.js

@@ -0,0 +1,60 @@
+import React, { Component } from "react";
+import { Field, reduxForm } from 'redux-form';
+import formInput from '../../common/formInput';
+import ModalSummary from './ModalSommary'
+import {reset} from 'redux-form';
+class Test extends React.Component {
+    state={
+        answers:[],
+        question:null,
+    }
+
+    submit=()=>{
+        const{sessionId,_id, actions:{checkTestRequest, nextTestRequest, startTestRequest} } =this.props;
+        const {answers, question} = this.state;
+        checkTestRequest({_id})
+        nextTestRequest({_id, sessionId,question, answers})
+        reset("gfhfh")
+        // startTestRequest({_id})
+
+    }
+    handelChange=({el:{_id, question}})=>{
+this.setState((prevState)=>({answers:prevState.answers.concat(_id)}))
+this.setState({question:question})
+    }
+
+    render() {
+        const { data, handleSubmit, summary, clickModal, handlers:{closeModal} } = this.props;
+        const{submit}=this
+        return (
+            <form onSubmit={handleSubmit(submit)}>
+
+                <h4 className="text-white font-ci">{
+                    data.question !==undefined
+                    ?
+                    data.question.question
+                    :null
+                    }</h4>
+                <div className=' d-flex flex-column'>
+                    {
+                        data.question !==undefined
+                        ?
+                        data.question.answersArr.map(el =>
+                            <div key={el._id}>
+                                <Field name={`answer${el.answer}`}  value={el.answer} type="checkbox" onChange={this.handelChange.bind(null,{el})} component={formInput} />
+                                <span className="text-white font-ci">{el.answer}</span>
+                                </div>
+                        )
+                        :
+                        <ModalSummary handlers={{closeModal}} summary={summary} clickModal ={clickModal}></ModalSummary>
+                    }
+                </div>
+                <button  className="btn  btn-outline-light bg-stone m-3 right">Next</button>
+            </form>
+        )
+    }
+}
+
+export default reduxForm({
+    form: "Test",
+})(Test)

+ 95 - 0
src/components/user/Test/index.js

@@ -0,0 +1,95 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux';
+import {getTopicTestRequest} from '../../../actions/user/test/getTopics'
+import {startTestRequest} from '../../../actions/user/test/testStart';
+import {checkTestRequest} from '../../../actions/user/test/checkTest';
+import {nextTestRequest} from '../../../actions/user/test/nextTest'
+import Test from './getTest';
+
+	
+
+
+class PassingTests extends React.Component {
+    state={
+        _id:null,
+        sessionId:null,
+        summary:null,
+        clickModal:false
+    }
+
+componentWillMount(){
+    const{getTopicTestRequest} =this.props
+    getTopicTestRequest()
+}
+
+closeModal = () => { this.setState((prevState) => ({ clickModal: !prevState.clickModal })) }
+handelClick=({el:{_id}})=>{
+    const{startTestRequest, checkTestRequest}=this.props
+    checkTestRequest({_id})
+    startTestRequest({_id})
+    this.setState({_id:_id})
+}
+componentWillReceiveProps(nextProps) {
+    const{startTest:{data}}=nextProps
+    if(data!==null){
+        this.setState({sessionId:data.sessionId})
+          if(data.finish){
+        this.setState({summary:data.summory,clickModal:true})
+    }
+    }
+
+  
+}
+
+
+    render() {
+        const{ handelClick,closeModal}=this
+        const {sessionId,_id, summary, clickModal} =this.state
+        const{topicTest:{topic},startTest:{data}, checkTestRequest, nextTestRequest, startTestRequest}=this.props;
+
+
+        return (
+            <div className=" profile-page d-flex flex-row font-ci padding  ">
+          
+                <div className='w-25 p-3  border rounded bg-gradient slideRight'  >
+                    {
+                        topic!==null
+                        ?
+                        topic.map(el=>
+                            <button type="button" class="text-center overflow-hidden rounded-pill btn-outline-light btn mb-4 borber bg-rgba border-0  font-ci font-ci-bold "key={el._id} id={el._id} onClick={handelClick.bind(null, { el })}>{el.name}</button>
+                        )
+                        :null
+                    }
+                </div>
+                <div className='w-75 p-3  ml-3 border rounded d-flex flex-row bg-gradient slideLeft'  >
+                    {
+                        data !==null
+                        ?
+                        <Test actions={{checkTestRequest, nextTestRequest, startTestRequest}} handlers={{closeModal}} summary={summary} clickModal={clickModal} sessionId={sessionId} _id={_id} data={data}></Test>
+                           
+                        :
+                        null
+                    } 
+                   
+                   
+                </div>
+            </div>
+
+
+
+        )
+    }
+
+}
+
+const
+    mapStateToProps = state => ({
+topicTest:state.topicTest,
+startTest:state.startTest
+
+    });
+
+const mapDispatchToProps = dispatch => bindActionCreators({getTopicTestRequest,startTestRequest, checkTestRequest, nextTestRequest }, dispatch);
+
+export default connect(mapStateToProps, mapDispatchToProps)(PassingTests);

+ 12 - 0
src/configs/requestsConfigs/index.js

@@ -0,0 +1,12 @@
+export const defaultConfig = {
+    headers: {
+        "Content-Type": "application/json"
+    }
+}
+
+export const makeConfigWithJWT = jwt => ({
+    headers: {
+        "Content-Type": "application/json",
+        "Authorization": `Bearer ${jwt}`
+    }
+})

+ 90 - 0
src/configs/routerConfig.js

@@ -0,0 +1,90 @@
+import React, { lazy } from 'react';
+
+import Landing from './../components/public/landing';
+import * as routes from './../constants/routes';
+
+const ProfilePage = lazy(() => import('../components/user/ProfilePage'));
+const DeleteUser = lazy(()=>import('../components/admin/deleteUser/index'));
+const AddDeleteCategory = lazy(()=> import('../components/admin/addDeleteCategory'));
+const CreateTest = lazy(()=> import('../components/admin/CreateTest'));
+const ChangeTest = lazy(()=>import('../components/admin/getChangeDeleteTest/index'))
+const PassingTests =lazy(()=>import('../components/user/Test/index'))
+const Category =lazy(()=>import('../components/user/Categoty'))
+
+const SignIn = lazy(() => import('../components/public/signIn/index'));
+const SignUp = lazy(() => import('../components/public/signUp/index'));
+
+
+const CardsCreator = lazy(() => import('./../components/admin/CardsCreator'))
+
+export default [
+    {
+        path: routes.LANDING,
+        access: 'public',
+        component: Landing
+    },
+    {
+        path: routes.SIGN_IN,
+        access: 'public',
+        component: SignIn
+    },
+    {
+        path: routes.SIGN_UP,
+        access: 'public',
+        component: SignUp
+    },
+    {
+        path: routes.HOME,
+        access: 'user-only',
+        component: () => <div>home</div>
+    },
+    {
+        path: routes.CATEGORIES,
+        access: 'user-only',
+        component: Category
+    },
+    {
+        path: routes.PROFILE,
+        access: 'user-only',
+        component: ProfilePage
+    },
+    {
+        path: routes.TESTS,
+        access: 'user-only',
+        component: PassingTests
+    },
+    {
+        path: '/admin',
+        access: 'admin-only',
+        component: () => <div>Some admin-only component</div>
+    },
+    {
+        path: routes.DELETE_USER,
+        access: 'admin-only',
+        component: DeleteUser
+    },
+    {
+        path: routes.CREATE_CATEGORY,
+        access: 'admin-only',
+        component: AddDeleteCategory
+    },
+    {
+        path: routes.CREATE_TEST,
+        access: 'admin-only',
+        component: CreateTest
+    },
+    {
+        path: routes.CREATE_TEST,
+        access: 'public',
+        component: CardsCreator
+    },
+    {
+        path: routes.CHANGE_TEST,
+        access: 'public',
+        component: ChangeTest
+    },
+    {
+        access: 'public',
+        component: () => <div>404</div>
+    },
+]

+ 47 - 0
src/configs/validate.js

@@ -0,0 +1,47 @@
+export default function validate(values) {
+    const { name, email, password, passwordConfirmation } = values;
+        const errors = {};
+    
+        if (!email) {
+            errors.email = "Required";
+        }
+        else if (email.length < 8 || email.length > 20) {
+            errors.email = "Invalid email length: email should be from 8 to 20 symbols";
+        }
+        else if (
+            !/^(([^<>()\]\\.,;:\s@"](\.[^<>()\]\\.,;:\s@"])*)|("."))@(([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]\.)[a-zA-Z]{2,}))$/.test(email)) {
+            errors.email = "Invalid email, try another one";
+        }
+    
+        if (!name) {
+            errors.name = "Required";
+        }
+        else if (name.length < 6 || name.length > 10) {
+            errors.name = "Invalid name length: name should be from 6 to 10 symbols";
+        }
+        else if (!/^[_A-z0-9]*((-|\s)*[_A-z0-9])*$/.test(name)) {
+            errors.name = "Invalid name, try another one"
+        }
+        
+        if (!password) {
+            errors.password = "Required"
+        }
+        else if (/[,]/.test(password)) {
+            errors.password = "Invalid symbol: \",\" is not allowed!";
+        }
+        else if (password.length < 8 || password.length > 20) {
+            errors.password = "Invalid password length: password should be from 8 to 20 symbols";
+        }
+        else if (!/^[a-z0-9_-]{8,20}$/i.test(password)) {
+            errors.password = "Invalid password, try another one";
+        }
+    
+        if (!passwordConfirmation) {
+            errors.passwordConfirmation = "Required";
+        }
+        else if (password !== passwordConfirmation) {
+            errors.passwordConfirmation = "Passwords don't match each other!";
+        }
+    
+      return errors;
+    }

+ 83 - 0
src/constants/admin.js

@@ -0,0 +1,83 @@
+export const CREATE_CATEGORY = "https://test-app-a-level.herokuapp.com/category" 
+export const CREATE_CATEGORY_REQUEST = 'CREATE_CATEGORY_REQUEST';
+export const CREATE_CATEGORY_REQUEST_SUCCESS = 'CREATE_CATEGORY_REQUEST_SUCCESS';
+export const CREATE_CATEGORY_REQUEST_FAILURE = 'CREATE_CATEGORY_REQUEST_FAILURE';
+
+export const GET_CATEGORY_REQUEST = 'GET_CATEGORY_REQUEST';
+export const GET_CATEGORY_REQUEST_SUCCESS = 'GET_CATEGORY_REQUEST_SUCCESS';
+export const GET_CATEGORY_REQUEST_FAILURE = 'GET_CATEGORY_REQUEST_FAILURE';
+
+
+export const CHANGE_CATEGORY_REQUEST = 'CHANGE_CATEGORY_REQUEST';
+export const CHANGE_CATEGORY_REQUEST_SUCCESS = 'CHANGE_CATEGORY_REQUEST_SUCCESS';
+export const CHANGE_CATEGORY_REQUEST_FAILURE = 'CHANGE_CATEGORY_REQUEST_FAILURE';
+
+export const DELETE_CATEGORY_REQUEST = 'DELETE_CATEGORY_REQUEST';
+export const DELETE_CATEGORY_REQUEST_SUCCESS = 'DELETE_CATEGORY_REQUEST_SUCCESS';
+export const DELETE_CATEGORY_REQUEST_FAILURE = 'DELETE_CATEGORY_REQUEST_FAILURE';
+
+export const CREATE_TOPICS = "https://test-app-a-level.herokuapp.com/topics";
+export const CREATE_TOPICS_REQUEST = 'CREATE_TOPICS_REQUEST';
+export const CREATE_TOPICS_REQUEST_SUCCESS = 'CREATE_TOPICS_REQUEST_SUCCESS';
+export const CREATE_TOPICS_REQUEST_FAILURE = 'CREATE_TOPICS_REQUEST_FAILURE';
+
+export const CREATE_QUESTIONS = "https://test-app-a-level.herokuapp.com/questions"; 
+export const CREATE_ANSVERS = "https://test-app-a-level.herokuapp.com/answers";
+export const CREATE_TEST_REQUEST = 'CREATE_TEST_REQUEST';
+export const CREATE_QUESTIONS_REQUEST_SUCCESS = 'CREATE_QUESTIONS_REQUEST_SUCCESS';
+export const CREATE_ANSVERS_REQUEST_SUCCESS = 'CREATE_ANSVERS_REQUEST_SUCCESS';
+export const CREATE_TEST_REQUEST_FAILURE = 'CREATE_TEST_REQUEST_FAILURE';
+
+export const MY_USER = "https://test-app-a-level.herokuapp.com/me";
+export const MY_USER_REQUEST = 'MY_USER_REQUEST';
+export const MY_USER_REQUEST_SUCCESS = 'MY_USER_REQUEST_SUCCESS';
+export const MY_USER_REQUEST_FAILURE = 'MY_USER_REQUEST_FAILURE';
+
+export const GET_USERS = "https://test-app-a-level.herokuapp.com/users/list";
+export const GET_USERS_REQUEST = 'GET_USERS_REQUEST';
+export const GET_USERS_REQUEST_SUCCESS = 'GET_USERS_REQUEST_SUCCESS';
+export const GET_USERS_REQUEST_FAILURE = 'GET_USERS_REQUEST_FAILURE';
+
+
+export const CHANGE_USER = "https://test-app-a-level.herokuapp.com/users/";
+export const CHANGE_USER_ROLE = "https://test-app-a-level.herokuapp.com/users/changeRole/";
+
+export const CHANGE_USERS_REQUEST = 'CHANGE_USERS_REQUEST';
+export const CHANGE_USERS_REQUEST_SUCCESS = 'CHANGE_USERS_REQUEST_SUCCESS';
+export const CHANGE_USERS_REQUEST_FAILURE = 'CHANGE_USERS_REQUEST_FAILURE';
+
+export const DELETE_USERS_REQUEST = 'DELETE_USERS_REQUEST';
+export const DELETE_USERS_REQUEST_SUCCESS = 'DELETE_USERS_REQUEST_SUCCESS';
+export const DELETE_USERS_REQUEST_FAILURE = 'DELETE_USERS_REQUEST_FAILURE';
+
+
+export const GET_TOPIC_REQUEST = 'GET_TOPIC_REQUEST';
+export const GET_TOPIC_REQUEST_SUCCESS = 'GET_TOPIC_REQUEST_SUCCESS';
+export const GET_TOPIC_REQUEST_FAILURE = 'GET_TOPIC_REQUEST_FAILURE';
+
+
+export const GET_QUESTIONS_REQUEST = 'GET_QUESTIONS_REQUEST';
+export const GET_QUESTIONS_REQUEST_SUCCESS = 'GET_QUESTIONS_REQUEST_SUCCESS';
+export const GET_QUESTIONS_REQUEST_FAILURE = 'GET_QUESTIONS_REQUEST_FAILURE';
+
+export const DELETE_TOPIC_REQUEST = 'DELETE_TOPIC_REQUEST';
+export const DELETE_TOPIC_REQUEST_SUCCESS = 'DELETE_TOPIC_REQUEST_SUCCESS';
+export const DELETE_TOPIC_REQUEST_FAILURE = 'DELETE_TOPIC_REQUEST_FAILURE';
+
+export const DELETE_QUESTION_REQUEST = 'DELETE_QUESTION_REQUEST';
+export const DELETE_QUESTION_REQUEST_SUCCESS = 'DELETE_QUESTION_REQUEST_SUCCESS';
+export const DELETE_QUESTION_REQUEST_FAILURE = 'DELETE_QUESTION_REQUEST_FAILURE';
+
+export const DELETE_ANSWER_REQUEST = 'DELETE_ANSWER_REQUEST';
+export const DELETE_ANSWER_REQUEST_SUCCESS = 'DELETE_ANSWER_REQUEST_SUCCESS';
+export const DELETE_ANSWER_REQUEST_FAILURE = 'DELETE_ANSWER_REQUEST_FAILURE';
+
+export const GET_ANSWERS_REQUEST = 'GET_ANSWERS_REQUEST';
+export const GET_ANSWERS_REQUEST_SUCCESS = 'GET_ANSWERS_REQUEST_SUCCESS';
+export const GET_ANSWERS_REQUEST_FAILURE = 'GET_ANSWERS_REQUEST_FAILURE';
+
+export const CHANGE_TEST_REQUEST = 'CHANGE_TEST_REQUEST';
+export const CHANGE_TOPIC_REQUEST_SUCCESS = 'CHANGE_TOPIC_REQUEST_SUCCESS';
+export const CHANGE_QUESTIONS_REQUEST_SUCCESS = 'CHANGE_QUESTIONS_REQUEST_SUCCESS';
+export const CHANGE_ANSVERS_REQUEST_SUCCESS = 'CHANGE_ANSVERS_REQUEST_SUCCESS';
+export const CHANGE_TEST_REQUEST_FAILURE = 'CHANGE_TEST_REQUEST_FAILURE';

+ 18 - 0
src/constants/auth.js

@@ -0,0 +1,18 @@
+export const SIGN_IN_URL = 'https://test-app-a-level.herokuapp.com/auth/login'; 
+export const SIGN_IN_REQUEST = 'SIGN_IN_REQUEST';
+export const SIGN_IN_REQUEST_SUCCESS = 'SIGN_IN_REQUEST_SUCCESS';
+export const SIGN_IN_REQUEST_FAILURE = 'SIGN_IN_REQUEST_FAILURE';
+export const SIGN_IN_STATE_ZEROING = 'SIGN_IN_STATE_ZEROING';
+
+export const SIGN_UP_URL = 'https://test-app-a-level.herokuapp.com/auth/register';
+export const SIGN_UP_REQUEST = 'SIGN_UP_REQUEST';
+export const SIGN_UP_REQUEST_SUCCESS = 'SIGN_UP_REQUEST_SUCCESS';
+export const SIGN_UP_REQUEST_FAILURE = 'SIGN_UP_REQUEST_FAILURE';
+
+export const LOG_OUT_URL = 'https://test-app-a-level.herokuapp.com/auth/logout';
+export const LOG_OUT_REQUEST = 'LOG_OUT_REQUEST';
+export const LOG_OUT_REQUEST_SUCCESS = 'LOG_OUT_REQUEST_SUCCESS';
+export const LOG_OUT_REQUEST_FAILURE = 'LOG_OUT_REQUEST_FAILURE';
+
+export const ACTIVE_TOKEN = 'ACTIVE_TOKEN';
+export const INACTIVE_TOKEN = 'INACTIVE_TOKEN'; 

+ 15 - 0
src/constants/routes.js

@@ -0,0 +1,15 @@
+// Be careful ! Check all dependencies in config/config.js,
+// otherwise it may cause mistakes in router.js! 
+
+export const LANDING = '/';
+export const SIGN_UP = '/sign-up';
+export const SIGN_IN = '/sign-in';
+export const HOME = '/home';
+export const CREATE_CATEGORY = '/create-category';
+export const CATEGORIES = '/categories';
+export const PROFILE = '/profile';
+export const CREATE_TEST = '/create-test';
+export const CHANGE_TEST = '/change-test';
+export const DELETE_USER = '/delete-user'
+export const TESTS = '/test';
+export const PASSWORD_FORGET = '/pw-forget';

+ 31 - 0
src/constants/user.js

@@ -0,0 +1,31 @@
+export const USER_URL = 'https://test-app-a-level.herokuapp.com/users/'; 
+export const CHANGE_LOGIN_REQUEST = 'CHANGE_LOGIN_REQUEST';
+export const CHANGE_LOGIN_REQUEST_SUCCESS = 'CHANGE_LOGIN_REQUEST_SUCCESS';
+export const CHANGE_LOGIN_REQUEST_FAILURE = 'CHANGE_LOGIN_REQUEST_FAILURE';
+
+export const CHANGE_EMAIL_REQUEST = 'CHANGE_EMAIL_REQUEST';
+export const CHANGE_EMAIL_REQUEST_SUCCESS = 'CHANGE_EMAIL_REQUEST_SUCCESS';
+export const CHANGE_EMAIL_REQUEST_FAILURE = 'CHANGE_EMAIL_REQUEST_FAILURE';
+
+export const CHANGE_PASSWORD_REQUEST = 'CHANGE_PASSWORD_REQUEST';
+export const CHANGE_PASSWORD_REQUEST_SUCCESS = 'CHANGE_PASSWORD_REQUEST_SUCCESS';
+export const CHANGE_PASSWORD_REQUEST_FAILURE = 'CHANGE_PASSWORD_REQUEST_FAILURE';
+
+export const GET_TOPIC_TEST_REQUEST = 'GET_TOPIC_TEST_REQUEST';
+export const GET_TOPIC_TEST_REQUEST_SUCCESS = 'GET_TOPIC_TEST_REQUEST_SUCCESS';
+export const GET_TOPIC_TEST_REQUEST_FAILURE = 'GET_TOPIC_TEST_REQUEST_FAILURE';
+
+export const START_TEST='https://test-app-a-level.herokuapp.com/statistics/start'
+export const START_TEST_REQUEST = 'START_TEST_REQUEST';
+export const START_TEST_REQUEST_SUCCESS = 'START_TEST_REQUEST_SUCCESS';
+export const START_TEST_REQUEST_FAILURE = 'START_TEST_REQUEST_FAILURE';
+
+export const CHECK_TEST='https://test-app-a-level.herokuapp.com/statistics/check'
+export const CHECK_TEST_REQUEST = 'CHECK_TEST_REQUEST';
+export const CHECK_TEST_REQUEST_SUCCESS = 'CHECK_TEST_REQUEST_SUCCESS';
+export const CHECK_TEST_REQUEST_FAILURE = 'CHECK_TEST_REQUEST_FAILURE';
+
+export const NEXT_TEST='https://test-app-a-level.herokuapp.com/statistics/next'
+export const NEXT_TEST_REQUEST = 'NEXT_TEST_REQUEST';
+export const NEXT_TEST_REQUEST_SUCCESS = 'NEXT_TEST_REQUEST_SUCCESS';
+export const NEXT_TEST_REQUEST_FAILURE = 'NEXT_TEST_REQUEST_FAILURE';

+ 0 - 14
src/index.css

@@ -1,14 +0,0 @@
-body {
-  margin: 0;
-  padding: 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;
-}
-
-code {
-  font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
-    monospace;
-}

+ 16 - 6
src/index.js

@@ -1,12 +1,22 @@
 import React from 'react';
 import ReactDOM from 'react-dom';
-import './index.css';
-import App from './App';
 import * as serviceWorker from './serviceWorker';
+import { Provider } from "react-redux";
+import { BrowserRouter } from "react-router-dom"
+import Router from './router'
+import reduxStore from './state'
 
-ReactDOM.render(<App />, document.getElementById('root'));
+import 'bootstrap/dist/css/bootstrap.min.css';
+import 'bootstrap/dist/js/bootstrap.bundle.min';
+
+import './styles/_index.scss';
+
+ReactDOM.render(
+    <BrowserRouter>
+        <Provider store={reduxStore}>
+            <Router />
+        </Provider>
+    </BrowserRouter>,
+    document.getElementById('root'));
 
-// If you want your app to work offline and load faster, you can change
-// unregister() to register() below. Note this comes with some pitfalls.
-// Learn more about service workers: http://bit.ly/CRA-PWA
 serviceWorker.unregister();

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 7
src/logo.svg


+ 43 - 0
src/reducers/admin/changeCategory.js

@@ -0,0 +1,43 @@
+import * as actionTypes from '../../constants/admin';
+import initialState from '../initialState';
+
+export default function changeCategory(state = initialState.changeCategory, {payload, type, error}) {
+
+    switch (type) { // payload.type -> type
+        case 'wtfUpdate': {
+            return initialState.changeCategory
+        }
+        case actionTypes.CHANGE_CATEGORY_REQUEST: {
+            return {
+                ...state,
+                isFetching: true,
+                isFlag:false,
+                data:null,
+                error: null
+            }
+        }
+        case actionTypes.CHANGE_CATEGORY_REQUEST_SUCCESS: {
+            const { data } = payload;
+
+            return {
+                ...state,
+                isFetching: false,
+                isFlag:true,
+                data: data,
+                error: null,
+            }
+        }
+        case actionTypes.CHANGE_CATEGORY_REQUEST_FAILURE: {
+
+            return {
+                ...state,
+                isFetching: false,
+                data: null,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 42 - 0
src/reducers/admin/createCategory.js

@@ -0,0 +1,42 @@
+import * as actionTypes from '../../constants/admin';
+import initialState from '../initialState';
+
+export default function newCategory(state = initialState.newCategory, {payload, type, error}) {
+
+    switch (type) { // payload.type -> type
+        case 'wtfCreate': { // CREATE_CATEGORY_NULIFY
+            return initialState.newCategory
+        }
+
+        case actionTypes.CREATE_CATEGORY_REQUEST: {
+            
+            return {
+                ...state,
+                isFetching: false,
+                isFlag:false,
+                data:null
+            }
+        }
+        case actionTypes.CREATE_CATEGORY_REQUEST_SUCCESS: {
+            const { data } = payload;
+
+            return {
+                ...state,
+                isFetching: false,
+                isFlag:true,
+                data: data,
+            }
+        }
+        case actionTypes.GET_CATEGORY_REQUEST_FAILURE: {
+
+            return {
+                ...state,
+                isFetching: false,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 35 - 0
src/reducers/admin/getCategory.js

@@ -0,0 +1,35 @@
+import * as actionTypes from '../../constants/admin';
+import initialState from './../initialState';
+
+export default function getCategory(state = initialState.category, { payload, type, error }) {
+
+    switch (type) { // payload.type -> type
+        case actionTypes.GET_CATEGORY_REQUEST: {
+            return {
+                ...state,
+                isFetching: true
+            }
+        }
+        case actionTypes.GET_CATEGORY_REQUEST_SUCCESS: {
+            const { data: { category } } = payload;
+
+            return {
+                ...state,
+                isFetching: false,
+                isFlag: true,
+                data: category,
+            }
+        }
+        case actionTypes.GET_CATEGORY_REQUEST_FAILURE: {
+
+            return {
+                ...state,
+                isFetching: false,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 33 - 0
src/reducers/admin/getUsers.js

@@ -0,0 +1,33 @@
+import * as actionTypes from '../../constants/admin';
+import initialState from './../initialState';
+
+export default function getUsers(state = initialState.users, { payload, type, error }) {
+
+    switch (type) { // payload.type -> type
+        case actionTypes.GET_USERS_REQUEST: {
+            return {
+                ...state,
+                isFetching: true
+            }
+        }
+        case actionTypes.GET_USERS_REQUEST_SUCCESS: {
+            const {data:{users}}=payload
+            return {
+                ...state,
+                isFetching: false,
+                user:users
+            }
+        }
+        case actionTypes.GET_USERS_REQUEST_FAILURE: {
+
+            return {
+                ...state,
+                isFetching: false,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 32 - 0
src/reducers/admin/initialValues.js

@@ -0,0 +1,32 @@
+import * as actionTypes from '../../constants/admin';
+import initialState from './../initialState';
+
+export default function getCategory(state = initialState.initialValues, {payload, type, error}) {
+
+    switch (type) { // payload.type -> type
+        case actionTypes.GET_CATEGORY_REQUEST_SUCCESS: {
+            
+            return {
+                ...state,
+                categoryId:payload
+            }
+        }
+        case actionTypes.GET_TOPIC_REQUEST_SUCCESS: {
+
+            return {
+                ...state,
+                name:payload,
+            }
+        }
+        case actionTypes.GET_QUESTIONS_REQUEST_SUCCESS: {
+
+            return {
+                ...state,
+                question:payload
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 35 - 0
src/reducers/admin/test/changeUser.js

@@ -0,0 +1,35 @@
+import * as actionTypes from '../../../constants/admin';
+import initialState from '../../initialState';
+
+export default function changeUserReducer(state = initialState.changeUser, {  type, payload }) {
+    switch (type) {
+        case actionTypes.CHANGE_USERS_REQUEST: {
+            return {
+                ...state,
+                isFetching: false,
+                payload
+            }
+        }
+        case actionTypes.CHANGE_USERS_REQUEST_SUCCESS: {
+            const { data:{user} } = payload;
+
+            return {
+                ...state,
+                isFetching: true,
+                data:user
+            }
+        }
+        case actionTypes.CHANGE_USERS_REQUEST_FAILURE: {
+            const { error } = payload;
+
+            return {
+                ...state,
+                isFetching: false,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 34 - 0
src/reducers/admin/test/createTopics.js

@@ -0,0 +1,34 @@
+import * as actionTypes from '../../../constants/admin';
+import initialState from '../../initialState';
+
+export default function topic(state = initialState.topicId, {payload, type, error}) {
+
+    switch (type) { // payload.type -> type
+        case actionTypes.CREATE_TOPICS_REQUEST: {
+            return {
+                ...state,
+                isFetching: true,
+                // payload
+            }
+        }
+        case actionTypes.CREATE_TOPICS_REQUEST_SUCCESS: {
+const {data:{topic}}=payload
+            return {
+                ...state,
+                isFetching: false,
+                topic
+            }
+        }
+        case actionTypes.CREATE_TOPICS_REQUEST_FAILURE: {
+
+            return {
+                ...state,
+                isFetching: false,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 34 - 0
src/reducers/admin/test/deleteQuestion.js

@@ -0,0 +1,34 @@
+import * as actionTypes from '../../../constants/admin';
+import initialState from '../../initialState';
+
+export default function deleteQuestion(state = initialState.deleteQuestion, {payload, type, error}) {
+
+    switch (type) { 
+        case actionTypes.DELETE_QUESTION_REQUEST: {
+            return {
+                ...state,
+                isFetching: false,
+                payload
+            }
+        }
+        case actionTypes.DELETE_QUESTION_REQUEST_SUCCESS: {
+
+            return {
+                ...state,
+                isFetching: true,
+                payload
+            }
+        }
+        case actionTypes.DELETE_QUESTION_REQUEST_FAILURE: {
+
+            return {
+                ...state,
+                isFetching: false,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 34 - 0
src/reducers/admin/test/deleteTopic.js

@@ -0,0 +1,34 @@
+import * as actionTypes from '../../../constants/admin';
+import initialState from '../../initialState';
+
+export default function deleteTopic(state = initialState.deleteTopic, {payload, type, error}) {
+
+    switch (type) { 
+        case actionTypes.DELETE_TOPIC_REQUEST: {
+            return {
+                ...state,
+                isFetching: true,
+                payload
+            }
+        }
+        case actionTypes.DELETE_TOPIC_REQUEST_SUCCESS: {
+
+            return {
+                ...state,
+                isFetching: false,
+                payload
+            }
+        }
+        case actionTypes.DELETE_TOPIC_REQUEST_FAILURE: {
+
+            return {
+                ...state,
+                isFetching: true,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 36 - 0
src/reducers/admin/test/deleteUsers.js

@@ -0,0 +1,36 @@
+import * as actionTypes from '../../../constants/admin';
+import initialState from '../../initialState';
+
+export default function changeEmailReducer(state = initialState.deleteUsers, {  type, payload }) {
+    switch (type) {
+        case actionTypes.DELETE_USERS_REQUEST: {
+            return {
+                ...state,
+                isFetching: false,
+                payload
+            }
+        }
+        case actionTypes.DELETE_USERS_REQUEST_SUCCESS: {
+            // const { user:{email} } = payload;
+            // console.log(email)
+
+            return {
+                ...state,
+                isFetching: true,
+                data:payload
+            }
+        }
+        case actionTypes.DELETE_USERS_REQUEST_FAILURE: {
+            const { error } = payload;
+
+            return {
+                ...state,
+                isFetching: false,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 36 - 0
src/reducers/admin/test/getAnswers.js

@@ -0,0 +1,36 @@
+import * as actionTypes from '../../../constants/admin';
+import initialState from '../../initialState';
+
+export default function getAnswers(state = initialState.arrayAnswers, { payload, type, error }) {
+
+    switch (type) {
+        case actionTypes.GET_ANSWERS_REQUEST: {
+            return {
+                ...state,
+                isFetching: true,
+                isFlag: false,
+                payload
+            }
+        }
+        case actionTypes.GET_ANSWERS_REQUEST_SUCCESS: {
+            const {data:{answers}}=payload
+            return {
+                ...state,
+                isFetching: false,
+                isFlag: true,
+                answers:answers
+            }
+        }
+        case actionTypes.GET_ANSWERS_REQUEST_FAILURE: {
+
+            return {
+                ...state,
+                isFetching: false,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 36 - 0
src/reducers/admin/test/getQuestions.js

@@ -0,0 +1,36 @@
+import * as actionTypes from '../../../constants/admin';
+import initialState from '../../initialState';
+
+export default function getQuestions(state = initialState.arrayQuestions, { payload, type, error }) {
+
+    switch (type) {
+        case actionTypes.GET_QUESTIONS_REQUEST: {
+            return {
+                ...state,
+                isFetching: true,
+                isFlag: false,
+                payload
+            }
+        }
+        case actionTypes.GET_QUESTIONS_REQUEST_SUCCESS: {
+            const { data: { questions } } = payload
+            return {
+                ...state,
+                isFetching: false,
+                isFlag: true,
+                questions: questions
+            }
+        }
+        case actionTypes.GET_QUESTIONS_REQUEST_FAILURE: {
+
+            return {
+                ...state,
+                isFetching: false,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 37 - 0
src/reducers/admin/test/getTopic.js

@@ -0,0 +1,37 @@
+import * as actionTypes from '../../../constants/admin';
+import initialState from '../../initialState';
+
+export default function getTopic(state = initialState.topic, {payload, type, error}) {
+
+    switch (type) { 
+        case actionTypes.GET_TOPIC_REQUEST: {
+            return {
+                ...state,
+                isFetching: true,
+                isFlag:false,
+                payload
+            }
+        }
+        case actionTypes.GET_TOPIC_REQUEST_SUCCESS: {
+const {data:{topics}} =payload
+            return {
+                ...state,
+                isFetching: false,
+                isFlag:true,
+                topics
+            }
+        }
+        case actionTypes.GET_TOPIC_REQUEST_FAILURE: {
+
+            return {
+                ...state,
+                isFetching: false,
+                isFlag:false,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 34 - 0
src/reducers/admin/test/newTopic.js

@@ -0,0 +1,34 @@
+import * as actionTypes from '../../../constants/admin';
+import initialState from '../../initialState';
+
+export default function newTopic(state = initialState.newTopic, {payload, type, error}) {
+
+    switch (type) { // payload.type -> type
+        case actionTypes.CHANGE_TEST_REQUEST: {
+            return {
+                ...state,
+                isFetching: false,
+                // payload
+            }
+        }
+        case actionTypes.CHANGE_TOPIC_REQUEST_SUCCESS: {
+const {data:{topic}}=payload
+            return {
+                ...state,
+                isFetching: true,
+                data:topic
+            }
+        }
+        // case actionTypes.CREATE_TOPICS_REQUEST_FAILURE: {
+
+        //     return {
+        //         ...state,
+        //         isFetching: false,
+        //         error
+        //     }
+        // }
+        default: {
+            return state;
+        }
+    }
+}

+ 31 - 0
src/reducers/auth/logOut.js

@@ -0,0 +1,31 @@
+import * as actionTypes from './../../constants/auth';
+import initialState from './../initialState';
+
+export default function signInReducer(state = initialState.logOut, {type, error}) {
+
+    switch (type) {
+        case actionTypes.LOG_OUT_REQUEST: {
+            return {
+                ...state,
+                isFetching: true
+            }
+        }
+        case actionTypes.LOG_OUT_REQUEST_SUCCESS: {
+            return {
+                ...state,
+                isFetching: false,
+                isSuccessful: true
+            }
+        }
+        case actionTypes.LOG_OUT_REQUEST_FAILURE: {
+            return {
+                ...state,
+                isFetching: false,
+                error
+            }
+        }
+        default: {
+            return state;
+        }
+    }
+}

+ 0 - 0
src/reducers/auth/signIn.js


Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.