8 コミット edd01b5128 ... 5fde9ed58a

作者 SHA1 メッセージ 日付
  = 5fde9ed58a merge v2 5 年 前
  Svetlana 86c9135b21 merged Sveta -> signIn/Up changes, getting user prototype 5 年 前
  Svetlana 03c5a00ed8 action, back 5 年 前
  = bc6f365613 Route is rewritten using config && tocken auth prototype added 5 年 前
  = e10584aa72 test connected routes 5 年 前
  = b00ea32e26 profile additional && categories page prototypes 5 年 前
  = e739cfce03 backend tryout -> profile layout prototype 5 年 前
  = 1f38e95899 components struct changes -> admin && user && public 5 年 前
51 ファイル変更6492 行追加4063 行削除
  1. 1 0
      debug.log
  2. 5954 3934
      package-lock.json
  3. 2 1
      package.json
  4. 0 14
      src/PrivateRouter.js
  5. 5 1
      src/actions/auth/index.js
  6. 6 0
      src/actions/auth/tokenAuth/index.js
  7. 18 0
      src/actions/auth/users/users.js
  8. 1 1
      src/actions/index.js
  9. 0 12
      src/components/admin-components/createTestPage/index.js
  10. 1 1
      src/components/common/formInput/index.js
  11. 48 0
      src/components/common/protectedRoute/config.js
  12. 34 0
      src/components/common/protectedRoute/index.js
  13. 2 3
      src/components/auth/signInForm/index.js
  14. 0 0
      src/components/public-components/auth/signInForm/validate/index.js
  15. 1 2
      src/components/auth/signUpForm/index.js
  16. 2 1
      src/components/auth/signUpForm/validate/index.js
  17. 3 1
      src/components/footer/index.js
  18. 2 2
      src/components/header/index.js
  19. 3 3
      src/components/landingPage/index.js
  20. 1 1
      src/components/notFound/index.js
  21. 13 0
      src/components/public-components/permissionDenied/index.js
  22. 10 9
      src/components/admin-components/createTestPage/form/index.js
  23. 0 0
      src/components/user-components/admin-components/createTestForm/validate/index.js
  24. 49 0
      src/components/user-components/categoriesPage/index.js
  25. 0 0
      src/components/user-components/homePage/index.js
  26. 89 0
      src/components/user-components/profilePage/index.js
  27. 6 0
      src/constants/index.js
  28. 7 6
      src/constants/routes.js
  29. 1 2
      src/containers/auth/SignInPage/index.js
  30. 1 2
      src/containers/auth/SignUpPage/index.js
  31. 2 2
      src/containers/header/index.js
  32. 38 6
      src/reducers/user/index.js
  33. 58 38
      src/router.js
  34. 2 0
      src/saga/auth/index.js
  35. 6 9
      src/saga/auth/signIn/index.js
  36. 5 4
      src/saga/auth/signUp/index.js
  37. 20 0
      src/saga/auth/users/users.js
  38. 1 1
      src/styles/abstracts/_variables.scss
  39. 8 1
      src/styles/base/_base.scss
  40. 3 0
      src/styles/components/_button.scss
  41. 31 0
      src/styles/components/_categoriesPage.scss
  42. 5 0
      src/styles/components/_container.scss
  43. 0 0
      src/styles/components/_createTestPage.scss
  44. 0 6
      src/styles/components/_landingPage.scss
  45. 11 0
      src/styles/components/_page.scss
  46. 30 0
      src/styles/components/_profilePage.scss
  47. 1 0
      src/styles/components/_signPage.scss
  48. 3 0
      src/styles/index.scss
  49. 1 0
      src/utils/token.js
  50. 6 0
      грабли.txt
  51. 1 0
      костыли.txt

+ 1 - 0
debug.log

@@ -0,0 +1 @@
+[0109/234712.714:ERROR:settings.cc(319)] Settings magic is not 1129342067

ファイルの差分が大きいため隠しています
+ 5954 - 3934
package-lock.json


+ 2 - 1
package.json

@@ -3,6 +3,7 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
+    "axios": "^0.18.0",
     "bootstrap": "^4.1.3",
     "firebase": "^5.7.0",
     "node-sass": "^4.11.0",
@@ -13,7 +14,7 @@
     "react-loader-spinner": "^2.3.0",
     "react-redux": "^6.0.0",
     "react-router-dom": "^4.3.1",
-    "react-scripts": "2.1.1",
+    "react-scripts": "^2.1.3",
     "redux": "^4.0.1",
     "redux-form": "^8.0.4",
     "redux-logger": "^3.0.6",

+ 0 - 14
src/PrivateRouter.js

@@ -1,14 +0,0 @@
-import React from 'react';
-import { Route, Redirect } from 'react-router';
-import * as routes from './constants/routes';
-
-export default ({ component: Component, user, ...rest }) => (
-    <Route
-        {...rest}
-        render={props => (
-            user
-                ? <Component {...props} />
-                : <Redirect to={routes.SIGN_IN} />
-        )}
-    />
-)

+ 5 - 1
src/actions/auth/index.js

@@ -1,7 +1,11 @@
 import * as signInActions from './signIn';
 import * as signUpActions from './signUp';
+import * as signOutActions from './signOut';
+import * as usersGetActions from './signOut';
 
 export default {
     ...signInActions,
-    ...signUpActions
+    ...signUpActions,
+    ...signOutActions,
+    ...usersGetActions
 }

+ 6 - 0
src/actions/auth/tokenAuth/index.js

@@ -0,0 +1,6 @@
+import { TOKEN_AUTH } from './../../../constants';
+
+export const tokenAuth = (payload) => ({
+    type: TOKEN_AUTH,
+    payload
+})

+ 18 - 0
src/actions/auth/users/users.js

@@ -0,0 +1,18 @@
+import * as types from '../../../constants';
+
+// all actions for signing up
+
+export const usersGetRequest= payload => ({
+    type: types.USERS_GET_REQUEST,
+    payload
+})
+
+export const usersGetRequestSucces = payload => ({
+    type: types.USERS_GET_REQUEST_SUCCESS,
+    payload
+})
+
+export const usersGetRequestFailure = error => ({
+    type: types.USERS_GET_REQUEST_SUCCESS_FAILURE ,
+    error
+})

+ 1 - 1
src/actions/index.js

@@ -1,4 +1,4 @@
-import authActions from './auth/logIn';
+import authActions from './auth';
 
 export default {
     ...authActions

+ 0 - 12
src/components/admin-components/createTestPage/index.js

@@ -1,12 +0,0 @@
-import React from 'react';
-import Form from './form';
-
-export default class createTestPage extends React.Component {
-    render() {
-        return (
-            <div className="page create-test">
-                <Form /> 
-            </div>
-        )
-    }
-}

+ 1 - 1
src/components/common/formInput/index.js

@@ -3,6 +3,6 @@ import React, { Fragment } from 'react';
 export default ({ input, className, placeholder, type, meta: { touched, error } }) => (
     <Fragment>
         <input className={className} placeholder={placeholder} type={type} {...input} />
-        {touched && (error && <p style={{"color": "red", "text-transform": "uppercase"}}>⚠ {error}</p>)}
+        {touched && (error && <p style={{"color": "red", "textTransform": "uppercase"}}>⚠ {error}</p>)}
     </Fragment>
 )

+ 48 - 0
src/components/common/protectedRoute/config.js

@@ -0,0 +1,48 @@
+import * as routes from './../../../constants/routes';
+import { lazy } from 'react';
+
+const landingPage = lazy(() => import('./../../public-components/landingPage'));
+const homePage = lazy(() => import('./../../user-components/homePage'));
+const signInPage = lazy(() => import('./../../../containers/auth/SignInPage'));
+const signUpPage = lazy(() => import('./../../../containers/auth/SignUpPage'));
+const createTestForm = lazy(() => import('./../../user-components/admin-components/createTestForm'));
+const profilePage = lazy(() => import('./../../user-components/profilePage'));
+const categoriesPage = lazy(() => import('./../../user-components/categoriesPage'));
+
+export default [
+    {
+        path: routes.LANDING,
+        access: 'public',
+        component: landingPage
+    },
+    {
+        path: routes.SIGN_IN,
+        access: 'public',
+        component: signInPage
+    },
+    {
+        path: routes.SIGN_UP,
+        access: 'public',
+        component: signUpPage
+    },
+    {
+        path: routes.HOME,
+        access: 'user-only',
+        component: homePage
+    },
+    {
+        path: routes.CATEGORIES,
+        access: 'user-only',
+        component: categoriesPage
+    },
+    {
+        path: routes.PROFILE,
+        access: 'user-only',
+        component: profilePage
+    },
+    {
+        path: routes.CREATE_TEST,
+        access: 'admin-only',
+        component: createTestForm
+    }
+]

+ 34 - 0
src/components/common/protectedRoute/index.js

@@ -0,0 +1,34 @@
+import React from 'react';
+import { Route, Redirect } from 'react-router-dom';
+import config from './config';
+import * as routes from './../../../constants/routes';
+import PermissionDenied from './../../public-components/permissionDenied';
+
+export default ({ component: Component, user, access, ...rest  }) => (
+    <Route
+        {...rest}
+        render={props => {
+
+            if (access === 'public') {
+                return <Component {...props} />
+            }
+            
+            if ( (access === 'user-only' || access === 'admin-only') && !user.data ) {
+                return <Redirect to={routes.SIGN_IN}/>
+            }
+            
+            if (access === 'user-only' && user.data) {
+                return <Component {...props} />
+            }        
+
+            if (access === 'admin-only') {
+                if (user.isAdmin) {
+                    return <Component {...props} />
+                } 
+
+                return <PermissionDenied />
+            }
+            
+        }}
+    />
+)

+ 2 - 3
src/components/auth/signInForm/index.js

@@ -2,14 +2,13 @@ import React from 'react';
 import { Field, reduxForm } from 'redux-form'
 
 import validate from './validate'
-import formInput from './../../common/formInput'
+import formInput from './../../../common/formInput'
 
 import { Link } from 'react-router-dom'
-import * as routes from './../../../constants/routes'
+import * as routes from './../../../../constants/routes'
 
 class Form extends React.Component {
     sendRequest = values => {
-        // console.log("Redux-form values, onSubmithandler before signInRequest:", values);
         const { actions: { signInRequest } } = this.props;
         signInRequest(values);
     }

src/components/auth/signInForm/validate/index.js → src/components/public-components/auth/signInForm/validate/index.js


+ 1 - 2
src/components/auth/signUpForm/index.js

@@ -1,7 +1,7 @@
 import React from 'react';
 import { Field, reduxForm } from 'redux-form'
 import validate from './validate'
-import formInput from './../../common/formInput'
+import formInput from './../../../common/formInput'
 
 class Form extends React.Component {
 
@@ -13,7 +13,6 @@ class Form extends React.Component {
 
     render() {
         const { invalid, handleSubmit } = this.props;
-        console.log(this.props);
 
         return (
             <form className="sign-form" onSubmit={handleSubmit(this.sendRequest)}>

+ 2 - 1
src/components/auth/signUpForm/validate/index.js

@@ -11,7 +11,8 @@ export default function validate(values) {
     else if (login.length < 8 || login.length > 20) {
         errors.login = "Invalid login length: login should be from 8 to 20 symbols";
     }
-    else if (!/^[a-z0-9_-]{8,20}$/i.test(login)) {
+    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(login)) {
         errors.login = "Invalid login, try another one";
     }
     

+ 3 - 1
src/components/footer/index.js

@@ -1,4 +1,5 @@
 import React from 'react';
+import store from './../../../state';
 
 export default props => (
     <div className="footer">
@@ -6,6 +7,7 @@ export default props => (
             TOP-company
             "<span className="footer__us us__inline--red">T</span>est.<span className="footer__us us__inline--green">i</span>o"
         </p>
-        <p className="footer__copyright">&copy; 2018, "Test.io", all right reserved</p>
+        <p className="footer__copyright">&copy; 2018, 'Test.io', all right reserved</p>
+        <button style={{"z-index": 4000, "color": "red"}} onClick={() => console.log(store.getState())}>Redux - State</button>
     </div>
 )

+ 2 - 2
src/components/header/index.js

@@ -1,7 +1,7 @@
 import React, { Component } from 'react';
 import { Link } from "react-router-dom";
-import * as routes from './../../constants/routes';
-import { UserContext } from './../../containers/Header';
+import * as routes from './../../../constants/routes';
+import { UserContext } from './../../../containers/header';
 
 export default class header extends Component {
 

+ 3 - 3
src/components/landingPage/index.js

@@ -1,10 +1,10 @@
 import React from 'react';
 import { Link } from 'react-router-dom';
-import * as routes from './../../constants/routes'
+import * as routes from './../../../constants/routes'
 
 export default props => (
     <div className="page landing-page">
-        <div className="landing-page__about">
+        <div className="container landing-page__about">
             <h1 className="description__header">
                 We are the powerfull servise providing you the ability to create and manage
                 your own tests, in any categories, choosing your own marking methods.
@@ -16,7 +16,7 @@ export default props => (
                 can easily pass them, get marks and <span className="description__inline--pretty">share</span> ones!
             </p>
         </div>
-        <div className="landing-page__links-container">
+        <div className="container landing-page__links-container">
             <Link to={routes.SIGN_IN} className="landing-page__links landing-page__links--sign-in">
                 Sign in
             </Link>

+ 1 - 1
src/components/notFound/index.js

@@ -1,6 +1,6 @@
 import React from 'react';
 import { Link } from 'react-router-dom';
-import { HOME } from './../../constants/routes'
+import { HOME } from './../../../constants/routes'
 
 export default props => (
     <div className="page not-found">

+ 13 - 0
src/components/public-components/permissionDenied/index.js

@@ -0,0 +1,13 @@
+import React from 'react';
+import { Link } from 'react-router-dom';
+
+
+export default () => (
+    <div className="page permission-denied-page">
+        <h1 className="permission-denied-page__header">
+            Sorry, but looks like u are not the admin...
+        </h1>
+        <p>Buy our superior premium pack to be able to create new tests!</p>
+        <Link className="">Buy!</Link>
+    </div>
+)

+ 10 - 9
src/components/admin-components/createTestPage/form/index.js

@@ -1,33 +1,34 @@
 import React from 'react';
 import { reduxForm, Field } from 'redux-form';
 import validate from './validate';
-import fieldInput from './../../../common/formInput';
+import formInput from './../../../common/formInput'
 
 class Form extends React.Component {
-    handleSubmit(event) {
-        event.preventDefault();
-        alert("lol");
+    sendRequest(values) {
+        console.log('sendRequest createTestForm page values:', values);
     }
 
     render() {
+        const { handleSubmit } = this.props;
+
         return (
-            <form action="">
+            <form className="page" onSubmit={handleSubmit(this.sendRequest)}>
                 <h2>Make a title-page for your test!</h2>
 
                 <div className="title-page__block">
                     <p className="titles">Title</p>
                     <Field
-                        className="title-page__block--"
+                        className="title-page__block"
                         name="title"
                         type="input"
                         placeholder=""
-                        component={fieldInput}
+                        component={formInput}
                     />
                 </div>
 
                 <div className="title-page__block">
                     <p className="titles">Description</p>
-                    <Field name="description" type="input" placeholder="" className="" component={fieldInput} />
+                    <Field name="description" type="input" placeholder="" className="" component={formInput} />
                 </div>
 
                 <div className="title-page__block">
@@ -38,7 +39,7 @@ class Form extends React.Component {
                 <button className="">Create card</button>
             </form>
         )
-    }
+    }   
 }
 
 export default reduxForm({

src/components/admin-components/createTestPage/form/validate/index.js → src/components/user-components/admin-components/createTestForm/validate/index.js


+ 49 - 0
src/components/user-components/categoriesPage/index.js

@@ -0,0 +1,49 @@
+import React from 'react';
+import axios from 'axios';
+
+class categoriesPage extends React.Component {
+
+    state = {
+        categories: []
+    }
+
+    getCategories = () => {
+        axios.get('http://127.0.0.1:2000/api/categories')
+            .then(({ data }) => this.setState({
+                categories: data
+            }))
+            .catch(({ message }) => console.warn(message))
+    }
+
+    componentDidMount() {
+        this.getCategories()
+    }
+
+    render() {
+        const { categories } = this.state;
+        console.log("Categories - ", categories);
+
+        return ( 
+            <div className="page page--bottom-only categories-page">
+                <div className="container categories-grid">
+                    {categories.map(el => (
+                        <div
+                            className="categories-grid__element"
+                            style={{ background: `url("${el.cover}") no-repeat center center` }}
+                        >
+                            <a href={el.title}>
+                                <div className="container categories-grid__content-wrapper">
+                                    <h2>{el.title}</h2>
+                                    <hr className="divider" />
+                                    <p>{el.description}</p>
+                                </div>
+                            </a>
+                        </div>
+                    ))}
+                </div>
+            </div>
+        )
+    }
+}
+
+export default categoriesPage;

src/components/homePage/index.js → src/components/user-components/homePage/index.js


+ 89 - 0
src/components/user-components/profilePage/index.js

@@ -0,0 +1,89 @@
+import React from 'react';
+import { connect } from 'react-redux';
+// import { bindActionCreators } from 'redux'
+// import {} from './../../../actions'
+import axios from 'axios';
+
+// redux-connected container
+
+class profilePage extends React.Component {
+
+    state = {
+        user: {}
+    }
+
+    getUser = () => {
+        const randomUserId = Math.ceil(Math.random() * 10);
+
+        axios.post(`https://quiz.maxcrc.de/api/v1/user`,{
+            "login": 'ddd',
+            "password":"jhgfhgg"
+
+        })
+            .then(({ data }) => this.setState({
+                user: data
+            }))
+            .catch(({ message }) => console.warn(message))
+    }
+
+    componentDidMount() {
+        this.getUser();
+    }
+
+    render() {
+        const { user } = this.state;
+
+        console.log(user);
+
+        return (
+            <div className="page page--bottom-only profile-page">
+                <section className="container section section--about">
+                    <h2 className="section__element section__element--header">{user.login}</h2>
+                    <img className="section__element section__element--image" src={user.avatar} alt="avatar" />
+                    <div className="sedtion__element section__element--login">
+                        <h3>Login</h3>
+                        <p>{user.login}<button className="link link--btn right">Change login</button></p>
+                    </div>
+                    <div className="section__element section__element--">
+                        <h3>E-mail</h3>
+                        <p>{user.email}<button className="link link--btn right">Change e-mail</button></p>
+                    </div>
+                    <div className="section__element section__element--">
+                        <h3>Status</h3>
+                        <p>{user.description}</p>
+                    </div>
+                </section>
+                <section className="container section section--stats">
+                    <div className="section__element section__element--">
+                        <h3>Member Since</h3>
+                        <p>{new Date(user.createdAt).toLocaleString()}</p>
+                    </div>
+                    <div className="section__element section__element--comments">
+                        <h3>Last comments</h3>
+                        <p className="comments-block">
+                            {
+                                user.comments && user.comments
+                                    .slice(0, 60)
+                                    .map(el =>
+                                        <p>
+                                            <h4>{new Date(el.createdAt).toLocaleString()}</h4>
+                                            {el.text}
+                                        </p>)
+                            }
+                        </p>
+                    </div>
+                </section>
+            </div>
+        )
+    }
+
+}
+
+const
+    mapStateToProps = state => ({
+        user: state.user
+    })
+// mapDispatchToProps = dispatch => bindActionCreators({}, dispatch)
+
+export default connect(mapStateToProps)(profilePage);
+

+ 6 - 0
src/constants/index.js

@@ -12,3 +12,9 @@ export const USER_IS_SIGNED_IN = 'USER_IS_SIGNED_IN';
 export const USER_IS_NOT_SIGNED_IN = 'USER_IS_NOT_SIGNED_IN';
 
 export const SIGN_OUT = 'SIGN_OUT';
+
+export const USERS_GET_REQUEST = 'USERS_GET_REQUEST';
+export const USERS_GET_REQUEST_SUCCESS = 'USERS_GET_REQUEST_SUCCESS';
+export const USERS_GET_REQUEST_SUCCESS_FAILURE = 'USERS_GET_REQUEST_FAILURE';
+
+export const TOKEN_AUTH = 'TOKEN_AUTH';

+ 7 - 6
src/constants/routes.js

@@ -1,13 +1,14 @@
+// Be careful ! Check all dependencies in protectedRoute/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 ACCOUNT = '/account';
-export const ADMIN = '/admin';
-export const PASSWORD_FORGET = '/pw-forget';
-export const CREATE_TEST = '/create-test';
 export const CREATE_CATEGORY = '/create-category';
+export const CATEGORIES = '/categories';
+export const PROFILE = '/profile';
+export const CREATE_TEST = '/create-test';
 export const DELETE_USER = '/delete-user'
 export const TESTS = '/test';
-export const CATEGORIES = '/categories';
-export const PROFILE = '/profile';
+export const PASSWORD_FORGET = '/pw-forget';

+ 1 - 2
src/containers/auth/SignInPage/index.js

@@ -6,12 +6,11 @@ import { connect } from 'react-redux';
 import { Redirect } from 'react-router';
 import { HOME } from './../../../constants/routes';
 
-import SignInForm from './../../../components/auth/signInForm'
+import SignInForm from './../../../components/public-components/auth/signInForm'
 
 class SignInPage extends React.Component {
 
     render() {
-        console.log("SignInPage containers props:", this.props);
         const { signInRequest, user } = this.props;
         return (
             !(user.data)

+ 1 - 2
src/containers/auth/SignUpPage/index.js

@@ -6,12 +6,11 @@ import { connect } from 'react-redux';
 import { Redirect } from 'react-router'
 import { HOME } from './../../../constants/routes';
 
-import SignUpForm from './../../../components/auth/signUpForm'
+import SignUpForm from './../../../components/public-components/auth/signUpForm';
 
 class SignUpPage extends React.Component {
 
     render() {
-        console.log("SignInPage containers props:", this.props);
         const { signUpRequest, user } = this.props;
         return (
             !(user.data)

+ 2 - 2
src/containers/header/index.js

@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
 import { func, object } from 'prop-types';
 import { bindActionCreators } from 'redux' 
 
-import HeaderComponent from './../../components/header';
+import HeaderComponent from './../../components/public-components/header';
 
 import {signOut} from './../../actions/auth/signOut'
 
@@ -25,7 +25,7 @@ class Header extends Component {
                     signOut
                 }}
             >
-                <HeaderComponent />
+                <HeaderComponent />;
             </UserContext.Provider>
         )
         

+ 38 - 6
src/reducers/user/index.js

@@ -1,18 +1,31 @@
-import initialState from './../initialState'
-import * as types from './../../constants'
+import initialState from './../initialState';
+import * as types from './../../constants';
 
 export default function (state = initialState.user, { type, error, payload: data }) {
     switch(type) {
+
+        case types.TOKEN_AUTH: {
+            return {
+                ...state,
+                data
+            }
+        }
+
+        // SIGN_UP
+
         case types.SIGN_UP_REQUEST: {
             return {
                 ...state,
-                gettingUser: true
+                gettingUser: true,
+                error: null,
+                data: null
             }
         }
         case types.SIGN_UP_REQUEST_SUCCESS: {
             return {
                 ...state,
                 gettingUser: false,
+                error: null,
                 data
             }
         }
@@ -20,35 +33,54 @@ export default function (state = initialState.user, { type, error, payload: data
             return {
                 ...state,
                 gettingUser: false,
+                data: null,
                 error
             }
         }
+
+        // SIGN_IN
+
         case types.SIGN_IN_REQUEST: {
             return {
                 ...state,
-                gettingUser: true
+                gettingUser: true,
+                error: null,
+                data: null
             }
         }
         case types.SIGN_IN_REQUEST_SUCCESS: {
             return {
                 ...state,
                 gettingUser: false,
+                error: null,
                 data                
             }
         }
-        case types.SIGN_UP_REQUEST_FAILURE: {
+        case types.SIGN_IN_REQUEST_FAILURE: {
             return {
                 ...state,
                 gettingUser: false,
+                data: null,
                 error
             }
         }
+
+        // SIGN_OUT
+
         case types.SIGN_OUT: {
             return initialState.user
         }
+
+        // DEFAULT
+
         default: {
             return {...state}
             
         }
     }
-}
+}
+
+
+
+
+

+ 58 - 38
src/router.js

@@ -1,43 +1,63 @@
 import React, { Suspense, lazy } from "react";
-import { Switch, Route } from "react-router-dom";
+import { Switch, Route, withRouter } from "react-router-dom";
+import { connect } from 'react-redux';
+import { tokenAuth } from './actions/auth/tokenAuth'
 
-import * as routes from './constants/routes'
-
-import Header from "./containers/Header"
-import landingPage from './components/landingPage'
-import Footer from './components/footer'
-import PrivateRouter from './PrivateRouter'
+import Header from "./containers/header";
+import Footer from './components/public-components/footer';
 
 import Spinner from "./components/common/spinner";
 
-const notFound   = lazy(() => import("./components/notFound"));
-const homePage   = lazy(() => import("./components/homePage"));
-const signInPage = lazy(() => import("./containers/auth/SignInPage"));
-const signUpPage = lazy(() => import("./containers/auth/SignUpPage"));
-const createTestPage = lazy(() => import("./components/admin-components/createTestPage"));
-
-export default () => (
-    <div className="app">
-        <Header />
-        <Suspense fallback={<Spinner />}>
-            <Switch>
-                <Route path={routes.LANDING} exact component={landingPage} />
-                <Route path={routes.SIGN_IN} exact component={signInPage} />
-                <Route path={routes.SIGN_UP} exact component={signUpPage} />
-                <Route path={routes.HOME} exact component={homePage} />
-
-                {/* <PrivateRouter path={routes.HOME} user={false} component={homePage}/> */}
-                <PrivateRouter path={routes.TESTS} user={false} component={null}/>
-                <PrivateRouter path={routes.CATEGORIES} user={false} component={null}/>
-                <PrivateRouter path={routes.PROFILE} user={false} component={null} />
-
-                <PrivateRouter path={routes.CREATE_TEST} user={true} component={createTestPage} />
-                <PrivateRouter path={routes.CREATE_CATEGORY} user={false} component={createTestPage} />
-                <PrivateRouter path={routes.DELETE_USER} user={false} component={createTestPage} />
-                
-                <Route component={notFound} />
-            </Switch>
-        </Suspense>
-        <Footer />
-    </div>
-);
+import ProtectedRoute from './components/common/protectedRoute';
+import config from './components/common/protectedRoute/config';
+
+import fakeToken from './utils/token'
+import { bindActionCreators } from "redux";
+
+const notFound = lazy(() => import('./components/public-components/notFound'));
+
+class Router extends React.Component {
+
+    componentDidMount() {
+        const storagedUser = localStorage.getItem(fakeToken);
+        const { tokenAuth } = this.props;
+
+        storagedUser && tokenAuth(storagedUser);
+    }
+
+    render() {
+        const { user } = this.props;
+
+        //map located here because of switch-bag
+
+        const protectedRoutes = config.map(route =>
+            <ProtectedRoute
+                path={route.path}
+                component={route.component}
+                access={route.access}
+                user={user}
+                exact
+            />
+        );
+
+        return (
+            <div className="app">
+                <Header />
+                <Suspense fallback={<Spinner />}>
+                    <Switch>
+                        {protectedRoutes}
+                        <Route component={notFound} />
+                    </Switch>
+                </Suspense>
+                <Footer />
+            </div>
+        )
+    }
+}
+
+const mapStateToProps = state => ({
+    user: state.user
+})
+const mapDispatchToProps = dispatch => bindActionCreators({ tokenAuth }, dispatch);
+
+export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Router));

+ 2 - 0
src/saga/auth/index.js

@@ -3,10 +3,12 @@ import * as types from "./../../constants"
 
 import signIn from './signIn';
 import signUp from './signUp';
+import getUsers from './users/users';
 
 export default function*() {
     yield takeEvery(types.SIGN_IN_REQUEST, signIn);
     yield takeEvery(types.SIGN_UP_REQUEST, signUp);
+    yield takeEvery(types.USERS_GET_REQUEST, getUsers);
 }
 
 

+ 6 - 9
src/saga/auth/signIn/index.js

@@ -1,24 +1,21 @@
 import { put, call } from "redux-saga/effects";
 import * as actions from './../../../actions/auth/signIn'
+import axios from 'axios';
 
-import { SIGN_IN_URL } from './../../../constants'
 
 // worker-saga for signing in
 
 export default function* ({ payload: requestBody }) {
     try {
         // console.log('received request body from sign-in worker saga', requestBody);
-        const payload = yield call(() => 
-            fetch(SIGN_IN_URL, {
-                method: 'POST',
-                body: JSON.stringify(requestBody)
-            })
-                .then(res => res.json())
+        const payload = yield call(() =>
+            axios.post(`https://quiz.maxcrc.de/api/v1/user`, {...requestBody})
+                .then(({ data }) => data)
         );
         // console.log("Payload", payload);
         yield put(actions.signInRequestSucces(payload));
     }
-    catch (exception) {
-        yield put(actions.signInRequestFailure(exception.message))
+    catch ({ message }) {
+        yield put(actions.signInRequestFailure(message))
     }
 }

+ 5 - 4
src/saga/auth/signUp/index.js

@@ -1,5 +1,6 @@
 import { put, call } from "redux-saga/effects";
 import * as actions from './../../../actions/auth/signUp'
+import axios from 'axios';
 
 import { SIGN_UP_URL } from '../../../constants'
 
@@ -8,11 +9,11 @@ import { SIGN_UP_URL } from '../../../constants'
 export default function* ({ payload: requestBody }) {
     try {
         const payload = yield call(() => 
-        fetch(SIGN_UP_URL, {
-            method: 'POST',
-            body: JSON.stringify(requestBody)
+        axios.post(`https://quiz.maxcrc.de/api/v1/user`, {
+            ...requestBody
         })
-            .then(res => res.json())
+            .then(({ data }) => data)
+
     );
         yield put(actions.signUpRequestSucces(payload));
     }

+ 20 - 0
src/saga/auth/users/users.js

@@ -0,0 +1,20 @@
+import { put, call } from "redux-saga/effects";
+import * as actions from './../../../actions/auth/users/users'
+import axios from 'axios';
+
+
+
+export default function* ({ payload: requestBody }) {
+    try {
+        // console.log('received request body from sign-in worker saga', requestBody);
+        const payload = yield call(() =>
+            axios.get(`https://quiz.maxcrc.de/api/v1/user`)
+                .then(({ data }) => data)
+        );
+        // console.log("Payload", payload);
+        yield put(actions.usersGetRequestSucces(payload));
+    }
+    catch ({ message }) {
+        yield put(actions.usersGetRequestFailure(message))
+    }
+}

+ 1 - 1
src/styles/abstracts/_variables.scss

@@ -15,5 +15,5 @@ $color-lightsteelgrey-transparent: rgba(190, 195, 221, .9);
 $color-lightsteelblue: #B0C4DE;
 $color-lightsteelblue-transparent: rgba(176, 196, 222, .9);
 
-$padding-top-fixed: 175px;
+$padding-top-fixed: 155px;
 $padding-bottom-fixed: 45px;

+ 8 - 1
src/styles/base/_base.scss

@@ -31,4 +31,11 @@ code {
     font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
     monospace;
 }
-  
+
+// recheck
+
+@media screen and (max-width: 1200px) {
+    * {
+        transition: none !important;
+    }
+}

+ 3 - 0
src/styles/components/_button.scss

@@ -31,6 +31,9 @@
             padding: 3vh 6vh;
             font-weight: 400;
         }
+        &-right {
+            float: right;
+        }
     }
     
 }

+ 31 - 0
src/styles/components/_categoriesPage.scss

@@ -0,0 +1,31 @@
+
+
+.categories {
+    &-page {
+        width: 95%;
+        margin: auto;
+    }
+    &-grid {
+        display: flex;
+        flex-wrap: wrap;
+        font-family: 'Cormorant Infant', serif;
+        text-align: center;
+        &__element {
+            min-width: 250px;
+            max-width: 370px;
+            margin: 1vw auto;
+            border: 2px solid lightsteelblue;
+            height: 300px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+        }
+        &__content-wrapper {
+            width: 80%;
+            height: 80%;
+        }
+        .divider {
+            width: 60%;
+        }
+    }
+}

+ 5 - 0
src/styles/components/_container.scss

@@ -0,0 +1,5 @@
+.container {
+    margin: auto;
+    background: $color-lightgrey-transparent;
+    box-shadow: 0 0 10px grey;
+}

+ 0 - 0
src/styles/components/_createTestPage.scss


+ 0 - 6
src/styles/components/_landingPage.scss

@@ -5,12 +5,6 @@
     background-size: cover;
     background-position: top center;
     font-family: 'Cormorant Infant', serif;
-    &__about,
-    &__links-container, {
-        margin: auto;
-        background: rgba(211,211,211, .9);
-        box-shadow: 0 0 10px grey;
-    }
     &__about {
         width: 65%;
         text-align: center;

+ 11 - 0
src/styles/components/_page.scss

@@ -1,5 +1,16 @@
 .page {
     padding-top: $padding-top-fixed;
     padding-bottom: $padding-bottom-fixed;
+    &--bottom-only {
+        padding-top: $padding-top-fixed - 40px;
+    }
 }
+
+// .app {
+//     background-image: url('https://structureofintellect.files.wordpress.com/2017/09/bubble-test.jpg');
+//     background-attachment: fixed;
+//     background-repeat: no-repeat;
+//     background-size: cover;
+//     background-position: top center;
+// }
     

+ 30 - 0
src/styles/components/_profilePage.scss

@@ -0,0 +1,30 @@
+.profile-page {
+    display: flex;
+    flex-wrap: wrap;
+    font-family: 'Cormorant Infant', serif;
+    font-size: 20px;
+    .section {
+        flex-grow: 1;
+        flex-basis: 400px;
+        margin: 10px;
+        padding: 10px;
+        &__element {
+            &--image {
+                border: 3px solid $color-lightsteelblue;
+                margin-bottom: 20px;
+            }
+            p {
+                margin-top: 5px;
+            }
+            .comments-block {
+                height: 250px;
+                overflow: auto;
+            }
+            
+        }
+    }
+    .right {
+        float: right;
+    }
+}
+

+ 1 - 0
src/styles/components/_signPage.scss

@@ -1,5 +1,6 @@
 .sign {
     &-form {
+        // background: $color-lightgrey-transparent;
         font-size: 18px;
         font-family: 'Poiret One', cursive;
         font-weight: bold;

+ 3 - 0
src/styles/index.scss

@@ -4,6 +4,7 @@
 @import "base/typography";
 
 @import "components/page";
+@import "components/container";
 @import "components/button";
 @import "components/header";
 @import "components/spinner";
@@ -11,4 +12,6 @@
 @import "components/footer";
 @import "components/signPage";
 @import "components/notFound";
+@import "components/profilePage";
+@import "components/categoriesPage";
 

+ 1 - 0
src/utils/token.js

@@ -0,0 +1 @@
+export default "fake-token-lol-kek";

+ 6 - 0
грабли.txt

@@ -0,0 +1,6 @@
+1. Редакс ломает роутер.
+Возможный костыль:
+https://github.com/ReactTraining/react-router/blob/v4.0.0-beta.8/packages/react-router/docs/guides/blocked-updates.md
+2. Анимация на кнопках хэдэра и нотфаунд не работает, хотя работает на кнопках формы.
+ХЗ
+3. Нету адекватного способа прокинуть юзера в роутер -> см. пункт 1.

+ 1 - 0
костыли.txt

@@ -0,0 +1 @@
+Все еще впереди...