├── .env.exmaple ├── .gitignore ├── LICENSE ├── Procfile ├── README.md ├── app ├── __test__ │ └── components │ │ ├── Home.test.js │ │ └── Task.test.js ├── actions │ ├── constant.js │ ├── currentUser.js │ └── task.js ├── assets │ ├── css │ │ ├── theme.css │ │ └── theme.js │ ├── images │ │ ├── banner.png │ │ ├── loading.svg │ │ └── logo.svg │ └── scss │ │ ├── shared │ │ └── _form.scss │ │ └── theme.scss ├── components │ ├── Form │ │ ├── Input │ │ │ └── index.js │ │ ├── Login │ │ │ ├── index.js │ │ │ └── validate.js │ │ ├── Register │ │ │ ├── index.js │ │ │ └── validate.js │ │ └── Task │ │ │ └── index.js │ ├── Loaders │ │ └── index.js │ ├── Login │ │ └── index.js │ └── Task │ │ ├── Form.js │ │ ├── _style.scss │ │ └── index.js ├── index.js ├── pages │ ├── Home │ │ ├── _style.scss │ │ └── index.js │ ├── Login │ │ └── index.js │ ├── Register │ │ └── index.js │ ├── index.js │ └── routes.js ├── reducers │ ├── currentUser.js │ ├── index.js │ ├── store.js │ └── tasks.js ├── renderServer │ ├── index.js │ └── template.js └── services │ ├── axios.js │ └── isAuth.js ├── config ├── env.js ├── jest │ ├── cssTransform.js │ └── fileTransform.js ├── paths.js ├── polyfills.js ├── webpack.config.dev.js ├── webpack.config.prod.js ├── webpack.config.prod.server.js └── webpackDevServer.config.js ├── docs └── images │ └── banner.png ├── nodemon.json ├── package.json ├── public ├── favicon.ico ├── index.html └── manifest.json ├── scripts ├── build.js ├── start.js └── test.js ├── server ├── api │ ├── heplers │ │ ├── auth.js │ │ └── jwt.js │ ├── models │ │ ├── index.js │ │ ├── task.js │ │ └── user.js │ └── v1.0.0 │ │ ├── auth.js │ │ ├── routes.js │ │ └── task.js ├── index.js └── setup.js ├── static.json └── yarn.lock /.env.exmaple: -------------------------------------------------------------------------------- 1 | NODE_ENV=development 2 | BASE_URL=http://localhost:3001 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | .env.local 16 | .env.development 17 | .env.development.local 18 | .env.test.local 19 | .env.production 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | .idea/ 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Hung HK 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: node server 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | ## Required 6 | 1. Install mongodb [click here](https://docs.mongodb.com/manual/installation) 7 | 2. Heroku account [click here](https://heroku.com) if you want to deploy with heroku 8 | 3. Amazon account [click here](https://aws.amazon.com/) if you want to deploy with amazon 9 | ## Use for development 10 | 1. `git clone git@github.com:hunghkit/reactjs-begin.git` 11 | 2. `yarn install` || `npm install` 12 | 3. Start mongodb: `mongod` 13 | 4. Add ENV: cp .env.example .env 14 | 5. Start dev reactjs: `yarn start` || `npm start` 15 | 6. Start dev server: `yarn server` || `npm run server` 16 | ## Add route in project 17 | Edit file app/pages/routes.js 18 | 19 | ``` 20 | 21 | {...} 22 | Add new route in here 23 | 24 | ``` 25 | 26 | ## Handle rerender with sync data from api in redux 27 | Look example at file app/components 28 | 1. Add action with call data from api 29 | 2. Add preRender static method with 2 params store of redux and url in request in Component in Route and call dispatch action with api 30 | ## Preview build project 31 | 1. Build: `yarn run build` || `npm run build` 32 | 2. Build and review in local: `yarn run build:dev` || `npm run build:dev` 33 | 3. Build and start project: `yarn run build:start` || `npm run build:start` 34 | ## Deployment with heroku 35 | - Setup: 36 | 1. `heroku create $APP_NAME` 37 | 2. `heroku buildpacks:add --index 1 https://github.com/mars/create-react-app-buildpack.git ` 38 | 3. `heroku buildpacks:add --index 2 heroku/nodejs` 39 | - Deploy: 40 | `git push heroku yourbanch:master` 41 | 42 | ## Done 43 | 1. Config data with create-react-app 44 | 2. Use scss with node-sass 45 | 3. Renderserver side with redux 46 | 4. Deploy with heroku 47 | 5. React router 48 | 6. Integrate redux 49 | 7. Integrate redux-form 50 | 8. JWT in server 51 | 9. React-Toolbox 52 | 10. Example with REST 53 | ## Relation 54 | 1. With reactjs see more [create react app](https://github.com/facebookincubator/create-react-app) 55 | 2. Proxy with development, you change port or url in proxy in package.json 56 | 3. React router dom see more [click here](https://github.com/ReactTraining/react-router) 57 | 4. Seo with reactjs see more [click here](https://github.com/nfl/react-helmet) 58 | 5. Api with express see more [click here](https://expressjs.com/en/guide/routing.html) 59 | 6. Database with mongoosejs see more [click here](http://mongoosejs.com/docs/guide.html) 60 | 7. Deployment with aws through Elastic Beanstalk [click here](http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/eb-cli3-install.html) 61 | 8. Dotenv [click here](https://github.com/bkeepers/dotenv) 62 | ## Demo [click here](https://reactjs-begin.herokuapp.com) 63 | ## Licence: MIT 64 | -------------------------------------------------------------------------------- /app/__test__/components/Home.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Home from 'components/Home'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /app/__test__/components/Task.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Task from 'components/Task'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /app/actions/constant.js: -------------------------------------------------------------------------------- 1 | export const ADD_TASKS_LIST = 'ADD_TASKS_LIST'; 2 | export const SET_CURRENT_USER = 'SET_CURRENT_USER'; 3 | -------------------------------------------------------------------------------- /app/actions/currentUser.js: -------------------------------------------------------------------------------- 1 | import { 2 | SET_CURRENT_USER, 3 | } from './constant'; 4 | 5 | export const onSetCurrentUser = (user) => ({ type: SET_CURRENT_USER, user }); 6 | -------------------------------------------------------------------------------- /app/actions/task.js: -------------------------------------------------------------------------------- 1 | import axios from 'services/axios'; 2 | 3 | import { 4 | ADD_TASKS_LIST, 5 | } from './constant'; 6 | 7 | export const onAddTasks = (data) => (dispatch) => { 8 | if (data) return dispatch({ tasks: data, type: ADD_TASKS_LIST }); 9 | 10 | return axios.get('/api/v1.0.0/tasks') 11 | .then((res) => res.data) 12 | .then(({ tasks }) => ({ tasks: tasks.reduce((obj, item) => ({ ...obj, [item._id]: item }), {}) }))//eslint-disable-line 13 | .then(({ tasks }) => dispatch({ tasks, type: ADD_TASKS_LIST })) 14 | .catch((err) => dispatch({ tasks: {}, err, type: ADD_TASKS_LIST })); 15 | }; 16 | 17 | export const onRemoveTask = (id) => (dispatch, getState) => { 18 | const tasks = { ...getState().tasks }; 19 | delete tasks[id]; 20 | return axios.delete(`/api/v1.0.0/tasks/${id}`) 21 | .then(() => dispatch({ tasks, type: ADD_TASKS_LIST })) 22 | .catch(() => dispatch({ tasks, type: ADD_TASKS_LIST })); 23 | }; 24 | -------------------------------------------------------------------------------- /app/assets/css/theme.css: -------------------------------------------------------------------------------- 1 | ._07g5{padding:10px 0;position:relative;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._07g5 *,._07g5 ::after,._07g5 ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._07g5._3qQkg ._3-Nb6{box-shadow:0 1px 6px rgba(0,0,0,.12),0 1px 4px rgba(0,0,0,.24);max-height:45vh;visibility:visible}._14fVf{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:wrap;flex-wrap:wrap;list-style:none;margin:0;padding:0 0 5px 0}.cBUoJ{margin:2.5px 5px 2.5px 0}._3-Nb6{background-color:#fff;list-style:none;max-height:0;overflow-x:hidden;overflow-y:auto;padding:0;position:absolute;transition-duration:.35s;transition-property:max-height,box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);visibility:hidden;width:100%;z-index:100}._3-Nb6:not(._3rmye){margin-top:-20px}._3-Nb6._3rmye{bottom:0}._3-Nb6::-webkit-scrollbar{height:0;width:0}._1erPE{cursor:pointer;font-size:16px;padding:10px}._1erPE.kDY3Z{background-color:#eee}._1ryxc{position:relative}._1ryxc::after{border-left:5.48571px solid transparent;border-right:5.48571px solid transparent;border-top:5.48571px solid rgba(0,0,0,.12);content:'';height:0;pointer-events:none;position:absolute;right:8px;top:50%;transition:-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1),-webkit-transform .35s cubic-bezier(.4,0,.2,1);width:0}._3Iv9P{background-color:#eee;border-radius:32px;color:#757575;display:inline-block;font-size:14px;line-height:32px;margin-right:2.5px;max-width:100%;overflow:hidden;padding:0 12px;position:relative;text-overflow:ellipsis;white-space:nowrap;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._3Iv9P *,._3Iv9P ::after,._3Iv9P ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._2o8mD{padding-left:0}._2o8mD>[data-react-toolbox=avatar]{height:32px;margin-right:8px;vertical-align:middle;width:32px}._2o8mD>[data-react-toolbox=avatar]>span{font-size:20px;line-height:32px}._2hlBs{padding-right:32px}._3nnfj{cursor:pointer;display:inline-block;height:24px;margin:4px;padding:4px;position:absolute;right:0;width:24px}._3nnfj:hover ._2sopz{background:#9e9e9e}._2sopz{background:#bdbdbd;border-radius:24px;vertical-align:top}._2sopz ._10NaZ{fill:transparent;stroke:#fff;stroke-width:4px}._3OjJz{background-color:#9e9e9e;border-radius:50%;color:#fff;display:inline-block;font-size:24px;height:40px;overflow:hidden;position:relative;text-align:center;vertical-align:middle;width:40px;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._3OjJz *,._3OjJz ::after,._3OjJz ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._3OjJz>svg{fill:currentColor;height:40px;width:1em}._3OjJz>img{height:auto;max-width:100%}._2Ueo9{background-color:transparent;background-position:center;background-size:cover;border-radius:50%;display:block;height:100%;position:absolute;width:100%}._26GdB{display:block;line-height:40px;width:100%}.lFVgC{padding:20px 0;position:relative;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}.lFVgC *,.lFVgC ::after,.lFVgC ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}.lFVgC._1nKdf{margin-left:48px}._3ga1V{color:rgba(0,0,0,.26);display:block;font-size:24px!important;height:48px;left:-48px;line-height:48px!important;position:absolute;text-align:center;top:16px;transition:color .35s cubic-bezier(.4,0,.2,1);width:48px}._4bZUj{background-color:transparent;border-bottom:1px solid rgba(0,0,0,.12);border-left:0;border-right:0;border-top:0;color:#212121;display:block;font-size:16px;outline:0;padding:8px 0;width:100%}._4bZUj:focus:not([disabled]):not([readonly])~._3FySS::after,._4bZUj:focus:not([disabled]):not([readonly])~._3FySS::before{width:50%}._4bZUj:focus:not([disabled]):not([readonly])~._34120:not(.GRQEP){color:#3f51b5}._4bZUj:focus:not([disabled]):not([readonly])~._34120>._2G0aY{color:#de3226}._4bZUj:focus:not([disabled]):not([readonly])~.bMyi_{display:block;opacity:1}._4bZUj:focus:not([disabled]):not([readonly])~._3ga1V{color:#3f51b5}._4bZUj:focus:not([disabled]):not([readonly])._34NWn~.bMyi_{opacity:0}._4bZUj._34NWn~._34120:not(.GRQEP),._4bZUj:focus:not([disabled]):not([readonly])~._34120:not(.GRQEP),._4bZUj[type=date]~._34120:not(.GRQEP),._4bZUj[type=time]~._34120:not(.GRQEP){font-size:12px;top:6px}._4bZUj._34NWn~._34120.GRQEP,._4bZUj._34NWn~.bMyi_{display:none}._34120{color:rgba(0,0,0,.26);font-size:16px;left:0;line-height:16px;pointer-events:none;position:absolute;top:32px;transition-duration:.35s;transition-property:top,font-size,color;transition-timing-function:cubic-bezier(.4,0,.2,1)}._34120.GRQEP~.bMyi_{display:none}.bMyi_{color:rgba(0,0,0,.26);font-size:16px;left:0;line-height:16px;opacity:1;pointer-events:none;position:absolute;top:32px;transition-duration:.35s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}._3FySS{display:block;position:relative;width:100%}._3FySS::after,._3FySS::before{background-color:#3f51b5;bottom:0;content:'';height:2px;position:absolute;transition-duration:.2s;transition-property:width,background-color;transition-timing-function:cubic-bezier(.4,0,.2,1);width:0}._3FySS::before{left:50%}._3FySS::after{right:50%}._1oTuT,._2k5Jz{color:#de3226;font-size:12px;line-height:20px;margin-bottom:-20px}._1oTuT{color:rgba(0,0,0,.26);position:absolute;right:0}._3ZfJq>._4bZUj{border-bottom-style:dotted;color:rgba(0,0,0,.26)}._2s74E{padding-bottom:0}._2s74E>._4bZUj{border-bottom-color:#de3226;margin-top:1px}._2s74E>._1oTuT,._2s74E>._34120{color:#de3226}._2s74E>._34120>._2G0aY{color:#de3226}._2gAMv{display:none}._2Agdx{-ms-flex-line-pack:center;align-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;cursor:pointer;display:inline-block;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;font-size:14px;font-weight:500;height:36px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;letter-spacing:0;line-height:36px;outline:0;padding:0;position:relative;text-align:center;text-decoration:none;text-transform:uppercase;transition:box-shadow .2s cubic-bezier(.4,0,1,1),background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1);white-space:nowrap;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._2Agdx *,._2Agdx ::after,._2Agdx ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._2Agdx>input{height:.1px;margin:0;opacity:0;overflow:hidden;padding:0;position:absolute;width:.1px;z-index:0}._2Agdx::-moz-focus-inner{border:0}._2Agdx>span:not([data-react-toolbox=tooltip]){display:inline-block;line-height:36px;vertical-align:middle}._2Agdx>svg{display:inline-block;fill:currentColor;font-size:120%;height:36px;vertical-align:top;width:1em}._2Agdx>*{pointer-events:none}._2Agdx>._3AVBi{overflow:hidden}._2Agdx[disabled]{color:rgba(0,0,0,.26);cursor:auto;pointer-events:none}._2GH_L{border-radius:2px;min-width:90px;padding:0 12px}._2GH_L ._3aBSX{font-size:120%;margin-right:6px;vertical-align:middle}._2GH_L>svg{margin-right:5px}._1ZxqC[disabled]{background-color:rgba(0,0,0,.12);box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12)}._1ZxqC:active{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12)}._1ZxqC:focus:not(:active){box-shadow:0 0 8px rgba(0,0,0,.18),0 8px 16px rgba(0,0,0,.36)}._221ic{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12)}._1jWAQ{background:0 0}._3IRMZ{border-radius:50%;box-shadow:0 1px 1.5px 0 rgba(0,0,0,.12),0 1px 1px 0 rgba(0,0,0,.24);font-size:24px;height:56px;width:56px}._3IRMZ ._3aBSX:not([data-react-toolbox=tooltip]){line-height:56px}._3IRMZ>._3AVBi{border-radius:50%}._3IRMZ._2DCN-{font-size:17.77778px;height:40px;width:40px}._3IRMZ._2DCN- ._3aBSX{line-height:40px}.hC5Z2{background:0 0;border-radius:50%;vertical-align:middle;width:36px}.hC5Z2 svg,.hC5Z2>._3aBSX{font-size:20px;line-height:36px;vertical-align:top}.hC5Z2>._3AVBi{border-radius:50%}._3tTAW:not([disabled])._221ic,._3tTAW:not([disabled])._3IRMZ{background:#3f51b5;color:#fff}._3tTAW:not([disabled])._1jWAQ,._3tTAW:not([disabled]).hC5Z2{color:#3f51b5}._3tTAW:not([disabled])._1jWAQ:focus:not(:active),._3tTAW:not([disabled]).hC5Z2:focus:not(:active){background:rgba(63,81,181,.2)}._3tTAW:not([disabled])._1jWAQ:hover{background:rgba(63,81,181,.2)}._2wp6F:not([disabled])._221ic,._2wp6F:not([disabled])._3IRMZ{background:#ff4081;color:#fff}._2wp6F:not([disabled])._1jWAQ,._2wp6F:not([disabled]).hC5Z2{color:#ff4081}._2wp6F:not([disabled])._1jWAQ:focus:not(:active),._2wp6F:not([disabled]).hC5Z2:focus:not(:active){background:rgba(255,64,129,.2)}._2wp6F:not([disabled])._1jWAQ:hover{background:rgba(255,64,129,.2)}._2CPs4:not([disabled])._221ic,._2CPs4:not([disabled])._3IRMZ{background-color:#fff;color:#212121}._2CPs4:not([disabled])._1jWAQ,._2CPs4:not([disabled]).hC5Z2{color:#212121}._2CPs4:not([disabled])._1jWAQ:focus:not(:active),._2CPs4:not([disabled]).hC5Z2:focus:not(:active){background:rgba(33,33,33,.2)}._2CPs4:not([disabled])._1jWAQ:hover{background:rgba(33,33,33,.2)}._2CPs4:not([disabled])._2SPZr._221ic,._2CPs4:not([disabled])._2SPZr._3IRMZ{background-color:#212121;color:#fff}._2CPs4:not([disabled])._2SPZr._1jWAQ,._2CPs4:not([disabled])._2SPZr.hC5Z2{color:#fff}._2CPs4:not([disabled])._2SPZr._1jWAQ:focus:not(:active),._2CPs4:not([disabled])._2SPZr.hC5Z2:focus:not(:active){background:rgba(33,33,33,.2)}._2CPs4:not([disabled])._2SPZr._1jWAQ:hover{background:rgba(33,33,33,.2)}._2CPs4._2SPZr[disabled]{background-color:rgba(0,0,0,.08);color:rgba(0,0,0,.54)}._16N7o{bottom:0;left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:1}._3SV_u{background-color:currentColor;border-radius:50%;left:50%;pointer-events:none;position:absolute;top:50%;-webkit-transform-origin:50% 50%;transform-origin:50% 50%;transition-duration:.8s;z-index:100}._3SV_u._2OZWa{opacity:.3;transition-property:none}._3SV_u._3O2Ue{opacity:.3;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}._3SV_u:not(._3O2Ue):not(._2OZWa){opacity:0;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}._8pay8{background:#fff;border-radius:2px;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;font-size:14px;overflow:hidden;width:100%;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._8pay8 *,._8pay8 ::after,._8pay8 ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._8pay8._1AHwB{box-shadow:0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12),0 5px 5px -3px rgba(0,0,0,.2)}._8pay8 [data-react-toolbox=avatar]{display:block}._3Yc6z{background-position:center center;background-repeat:no-repeat;background-size:cover;position:relative}._3Yc6z._1HBxg,._3Yc6z._35NNe{width:100%}._3Yc6z._1HBxg .ewAVM,._3Yc6z._35NNe .ewAVM{height:100%;position:absolute}._3Yc6z._1HBxg .ewAVM>iframe,._3Yc6z._1HBxg .ewAVM>img,._3Yc6z._1HBxg .ewAVM>video,._3Yc6z._35NNe .ewAVM>iframe,._3Yc6z._35NNe .ewAVM>img,._3Yc6z._35NNe .ewAVM>video{max-width:100%}._3Yc6z::after{content:'';display:block;height:0}._3Yc6z._35NNe::after{padding-top:56.25%}._3Yc6z._1HBxg::after{padding-top:100%}._3Yc6z .ewAVM{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;left:0;overflow:hidden;position:relative;top:0;width:100%}._3Yc6z ._1bBKz .K_kzH,._3Yc6z ._1bBKz .ZoLIG,._3Yc6z ._1bBKz ._1dU3o{background-color:rgba(0,0,0,.35)}._3Yc6z ._1dU3o ._3p3mO,._3Yc6z ._1dU3o ._3qCP3{color:#fff}._1dU3o{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}._1dU3o [data-react-toolbox=avatar]{margin-right:13px}._1dU3o ._3qCP3{font-size:20px;font-weight:500;letter-spacing:.02em;line-height:1;margin:0;padding:0}._1dU3o ._3p3mO{color:#757575;font-size:14px;font-weight:400;letter-spacing:0;line-height:24px;margin:0;padding:0}._1dU3o._2iwOK{padding:20px 16px 14px}._1dU3o._2iwOK ._3qCP3{font-size:24px;-moz-osx-font-smoothing:grayscale;font-weight:400;line-height:1.25}._1dU3o._1RHxe{padding:16px}._1dU3o._1RHxe ._3qCP3{font-size:22.4px;font-size:22.4px;font-size:1.4rem;letter-spacing:0;line-height:1.4}._1dU3o._1RHxe ._3p3mO{font-weight:500;line-height:1.4}.K_kzH,._1dU3o{padding:14px 16px}.K_kzH p,._1dU3o p{font-size:14px;font-weight:400;letter-spacing:0;line-height:24px;margin:0}.K_kzH:last-child,._1dU3o:last-child{padding-bottom:20px}.K_kzH+.K_kzH,._1dU3o+.K_kzH{padding-top:0}.ZoLIG{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;padding:8px}.ZoLIG [data-react-toolbox=button]{margin:0 4px;min-width:0;padding:0 8px}.ZoLIG [data-react-toolbox=button]:first-child{margin-left:0}.ZoLIG [data-react-toolbox=button]:last-child{margin-right:0}._3Tq32{display:block;height:18px;margin-bottom:15px;position:relative;white-space:nowrap;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._3Tq32 *,._3Tq32 ::after,._3Tq32 ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._3Tq32 ._2NWrZ{background-color:#3f51b5;opacity:.3;transition-duration:650ms}.dXU7C{color:#000;display:inline-block;font-size:14px;line-height:18px;padding-left:10px;vertical-align:top;white-space:nowrap}._271V1{height:0;opacity:0;overflow:hidden;position:absolute;width:0}._271V1:focus~._1CXAo::before{background-color:rgba(0,0,0,.01);border-radius:50%;content:'';height:41.4px;left:50%;margin-left:-20.7px;margin-top:-20.7px;pointer-events:none;position:absolute;top:50%;width:41.4px}._271V1:focus~._1CXAo.nSz7s::before{background-color:rgba(63,81,181,.26)}._1CXAo{border-color:#000;border-radius:2px;border-style:solid;border-width:2px;cursor:pointer;display:inline-block;height:18px;position:relative;transition-duration:.2s;transition-property:background-color;transition-timing-function:cubic-bezier(.4,0,.2,1);vertical-align:top;width:18px;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._1CXAo *,._1CXAo ::after,._1CXAo ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._1CXAo.nSz7s{background-color:#3f51b5;border-color:#3f51b5}._1CXAo.nSz7s::after{-webkit-animation:_3GU9D 140ms ease-out forwards;animation:_3GU9D 140ms ease-out forwards;border-bottom-width:2px;border-color:#fff;border-left:0;border-right-width:2px;border-style:solid;border-top:0;content:'';height:12px;left:4px;position:absolute;top:-1px;-webkit-transform:rotate(45deg);transform:rotate(45deg);width:7px}._2jVLS>.dXU7C{color:rgba(0,0,0,.26)}._2jVLS>._1CXAo{border-color:rgba(0,0,0,.26);cursor:auto}._2jVLS>._1CXAo.nSz7s{background-color:rgba(0,0,0,.26);border-color:transparent;cursor:auto}@-webkit-keyframes _3GU9D{0%{height:0;left:6px;top:9px;width:0}100%{height:12px;left:4px;top:-1px;width:7px}}@keyframes _3GU9D{0%{height:0;left:6px;top:9px;width:0}100%{height:12px;left:4px;top:-1px;width:7px}}._2ISvI:not(.Cf3yF)>.x7MhN{cursor:pointer}._2vLUd{background-color:#3f51b5;color:#fff;cursor:pointer;padding:16px 20px}._1VWY-{display:inline-block;font-size:14px;transition:opacity,font-size .35s cubic-bezier(.4,0,.2,1)}._3K2Ws{display:block;font-size:34px;font-weight:400;font-weight:500;line-height:40px;margin:0;text-transform:capitalize;transition:opacity .35s cubic-bezier(.4,0,.2,1)}._1t-4v{padding:10px 5px 0}._2OzvT ._3K2Ws{opacity:.6}._2OzvT ._1VWY-{font-size:16px}._2DDdC ._1VWY-{opacity:.6}._3fCV6{width:330px}._3fCV6>[role=body]{padding:0}._3fCV6>[role=navigation]>._2hL6u{color:#3f51b5}._3fCV6>[role=navigation]>._2hL6u:hover{background:rgba(63,81,181,.2)}._3fCV6>[role=navigation]>._2hL6u:focus:not(:active){background:rgba(63,81,181,.2)}._1X9ls{background:#fff;font-size:14px;height:270px;line-height:30px;overflow:hidden;position:relative;text-align:center}._1X9ls .Nv9Bc,._1X9ls ._3iPkS{cursor:pointer;height:36px;opacity:.7;position:absolute;top:0;z-index:100}._1X9ls .Nv9Bc{left:0}._1X9ls ._3iPkS{right:0}._2ESpD{display:inline-block;font-weight:500;line-height:30px}.zEdgW{font-size:18px;height:100%;list-style:none;margin:0;overflow-y:auto;padding:0}.zEdgW>li{cursor:pointer;line-height:2.4}.zEdgW>li._1pjXb{color:#3f51b5;font-size:2.4;font-weight:500}.PcByv{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;font-size:13px;height:30px;line-height:30px;opacity:.5}.PcByv>span{-webkit-box-flex:0;-ms-flex:0 0 14.28571%;flex:0 0 14.28571%}._1qh3T{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;font-size:13px}._2qF_L{-webkit-box-flex:0;-ms-flex:0 0 14.28571%;flex:0 0 14.28571%;padding:2px 0}._2qF_L>span{border-radius:50%;display:inline-block;height:30px;line-height:30px;width:30px}._2qF_L:hover:not(._1pjXb):not(.Cf3yF)>span{background:rgba(63,81,181,.21);color:#fff}._2qF_L._1pjXb>span{background:#3f51b5;color:#fff}._2qF_L:hover:not(.Cf3yF)>span{cursor:pointer}._2qF_L.Cf3yF{opacity:.25}._1hSm5{background-color:#fff}.Rk89h,._1nam4{position:absolute}._2bZap,.m5B3T{transition-duration:350ms;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;transition-timing-function:ease-in-out}.Rk89h{opacity:0;-webkit-transform:translateX(100%);transform:translateX(100%)}.Rk89h.m5B3T{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}._1nam4{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}._1nam4._2bZap{opacity:0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}._2WGqM,.bGml_{position:absolute;transition-duration:.35s;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;transition-timing-function:ease-in-out}.bGml_{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.bGml_._3Ghls{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}._2WGqM{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}._2WGqM._2WLHG{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}._3nrqp{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:100vh;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;position:fixed;top:0;width:100vw;z-index:200;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._3nrqp *,._3nrqp ::after,._3nrqp ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._3lw90{background-color:#fff;border-radius:2px;box-shadow:0 19px 60px rgba(0,0,0,.3),0 15px 20px rgba(0,0,0,.22);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-height:96vh;max-width:96vw;opacity:0;-webkit-transform:translateY(-40px);transform:translateY(-40px);transition:opacity .35s cubic-bezier(.4,0,.2,1),-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:opacity .35s cubic-bezier(.4,0,.2,1),transform .35s cubic-bezier(.4,0,.2,1);transition:opacity .35s cubic-bezier(.4,0,.2,1),transform .35s cubic-bezier(.4,0,.2,1),-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition-delay:70ms}._3lw90._3ea_1{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}._38VTT{width:30vw}@media screen and (max-width:720px){._38VTT{width:50vw}}@media screen and (max-width:600px){._38VTT{width:75vw}}._1K3iz{width:50vw}@media screen and (max-width:600px){._1K3iz{width:96vw}}._10LcP{width:96vw}._3tLXQ{width:96vw}@media screen and (max-width:600px){._3tLXQ{border-radius:0;max-height:100vh;max-width:100vw;min-height:100vh;width:100vw}}._2J-aP{color:#000;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;font-size:20px;font-weight:500;letter-spacing:.02em;line-height:1;margin:0 0 16px}._1Ivuq{color:#757575;-webkit-box-flex:2;-ms-flex-positive:2;flex-grow:2;padding:24px}._1Ivuq p{font-size:14px;font-weight:400;letter-spacing:0;line-height:24px;margin:0}.wgwdj{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;padding:8px;text-align:right}._22_c6{margin-left:8px;min-width:0;padding-left:8px;padding-right:8px}._2LA9x{background-color:#000;bottom:0;height:100vh;left:0;opacity:0;pointer-events:none;position:fixed;top:0;transition:opacity .35s cubic-bezier(.4,0,.2,1);width:100vw}._2LA9x._1mb5R{opacity:.6;pointer-events:all}._3eRY8{position:relative;z-index:200}._1sAOY{background-color:#fafafa;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);color:#424242;display:block;height:100vh;overflow-x:hidden;overflow-y:auto;pointer-events:none;position:fixed;top:0;-webkit-transform-style:preserve-3d;transform-style:preserve-3d;transition:-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1),-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition-delay:0s;width:280px;will-change:transform;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._1sAOY *,._1sAOY ::after,._1sAOY ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._1sAOY.EWFXC{pointer-events:all;-webkit-transform:translateX(0);transform:translateX(0);transition-delay:70ms}._1sAOY._2-4-H{border-left:1px solid #e0e0e0;right:0}._1sAOY._2-4-H:not(.EWFXC){-webkit-transform:translateX(100%);transform:translateX(100%)}._1sAOY.FKhpR{border-right:1px solid #e0e0e0;left:0}._1sAOY.FKhpR:not(.EWFXC){-webkit-transform:translateX(-100%);transform:translateX(-100%)}@media screen and (min-width:600px){._1sAOY{width:256px}}.ZzBNK{position:relative;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}.ZzBNK *,.ZzBNK ::after,.ZzBNK ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}.ZzBNK:not(._1DQ-E)>._2767w{max-height:0;visibility:hidden}.ZzBNK._1DQ-E>._2KjGM,.ZzBNK._1DQ-E>._6c1D5{opacity:.5}.ZzBNK._1DQ-E>._2767w{box-shadow:0 1px 6px rgba(0,0,0,.12),0 1px 4px rgba(0,0,0,.24);max-height:45vh;visibility:visible}.ZzBNK:not(._1OA-G)>._2767w{bottom:auto;top:0}.ZzBNK._1OA-G>._2767w{bottom:0;top:auto}.ZzBNK._1skVH{cursor:normal;pointer-events:none}._6c1D5>input{cursor:pointer}._6c1D5::after{border-left:5.48571px solid transparent;border-right:5.48571px solid transparent;border-top:5.48571px solid rgba(0,0,0,.12);content:'';height:0;pointer-events:none;position:absolute;right:8px;top:50%;transition:-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1),-webkit-transform .35s cubic-bezier(.4,0,.2,1);width:0}.d5bru{cursor:pointer;padding:20px 0;position:relative}.d5bru._3dZUG{padding-bottom:0}.d5bru._3dZUG>._2KjGM{color:#de3226}.d5bru._3dZUG>._6dCtT{border-bottom:1px solid #de3226}.d5bru._3dZUG>._2KjGM>._1j4LX{color:#de3226}.d5bru._1skVH{cursor:normal;pointer-events:none}.d5bru._1skVH>._6dCtT{border-bottom-style:dotted;opacity:.7}._6dCtT{background-color:transparent;border-bottom:1px solid rgba(0,0,0,.12);color:#212121;min-height:38.4px;padding:8px 0;position:relative}._2KjGM{color:rgba(0,0,0,.26);font-size:12px;left:0;line-height:16px;position:absolute;top:6px}._2KjGM ._1j4LX{color:#de3226}.fySw3{color:#de3226;font-size:12px;line-height:20px;margin-bottom:-20px}._2767w{background-color:#fff;border-radius:2px;list-style:none;margin:0;overflow-y:auto;padding:0;position:absolute;transition-duration:.35s;transition-property:max-height,box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);width:100%;z-index:100}._2767w>*{cursor:pointer;overflow:hidden;padding:10px;position:relative;cursor:not-allowed}._2767w>._3uiEo{color:#3f51b5}._2767w::-webkit-scrollbar{height:0;width:0}.wiKya{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;min-height:100vh;min-width:100%;position:relative;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}.wiKya *,.wiKya ::after,.wiKya ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._3aW3s{left:0;position:absolute;right:0;top:0}._3aW3s:not(._2uzOU){height:100vh;max-height:100vh;overflow-y:scroll}.Cte92,._2kCN0{z-index:100}.Cte92.qf0ha,._2kCN0.qf0ha{box-shadow:none}.Cte92._1y5eh,._2kCN0._1y5eh{height:calc(100vh - 64px);padding-top:5px;top:64px}@media screen and (max-width:480px) and (orientation:portrait){.Cte92._1y5eh,._2kCN0._1y5eh{height:calc(100vh - 56px);top:56px}}@media screen and (max-width:600px) and (orientation:landscape){.Cte92._1y5eh,._2kCN0._1y5eh{height:calc(100vh - 48px);top:48px}}._1S9wz,._3aW3s{transition:all .35s cubic-bezier(.4,0,.2,1)}._2Q-xL.F9Fy2{z-index:100}._2Q-xL ._3aW3s{top:64px}._2Q-xL ._3aW3s:not(._2uzOU){height:calc(100vh - 64px);max-height:calc(100vh - 64px);overflow-y:scroll}@media screen and (max-width:480px) and (orientation:portrait){._2Q-xL ._3aW3s{top:56px}}@media screen and (max-width:600px) and (orientation:landscape){._2Q-xL ._3aW3s{top:48px}}._2eOy5 .fZ13o{display:none}._2eOy5 ._3aW3s{left:280px}._2eOy5:not(._2kROG) .F9Fy2{padding-left:304px}@media screen and (min-width:600px){._2eOy5 ._3aW3s{left:256px}._2eOy5:not(._2kROG) .F9Fy2{padding-left:280px}}._2kROG ._2gpOZ{position:relative;z-index:1}._3yo9c .fZ13o{display:none}._3yo9c ._3aW3s{right:280px}._3yo9c:not(._1paQt) .F9Fy2{padding-right:304px}@media screen and (min-width:600px){._3yo9c ._3aW3s{right:256px}._3yo9c:not(._1paQt) .F9Fy2{padding-right:280px}}._1paQt ._1TUxm{position:relative;z-index:1}._1EWpa ._2kCN0{width:100%}@media screen and (min-width:840px){._1EWpa ._2kCN0{width:64px}._1EWpa._3yo9c ._3aW3s{right:64px}._1EWpa._3yo9c:not(._1paQt) .F9Fy2{padding-right:88px}}._37z5O ._2kCN0{width:100%}@media screen and (min-width:840px){._37z5O ._2kCN0{width:128px}._37z5O._3yo9c ._3aW3s{right:128px}._37z5O._3yo9c:not(._1paQt) .F9Fy2{padding-right:152px}}._24Dtc ._2kCN0{width:100%}@media screen and (min-width:840px){._24Dtc ._2kCN0{width:192px}._24Dtc._3yo9c ._3aW3s{right:192px}._24Dtc._3yo9c:not(._1paQt) .F9Fy2{padding-right:216px}}._28mqi ._2kCN0{width:100%}@media screen and (min-width:840px){._28mqi ._2kCN0{width:256px}._28mqi._3yo9c ._3aW3s{right:256px}._28mqi._3yo9c:not(._1paQt) .F9Fy2{padding-right:280px}}.K39iB ._2kCN0{width:100%}@media screen and (min-width:840px){.K39iB ._2kCN0{width:320px}.K39iB._3yo9c ._3aW3s{right:320px}.K39iB._3yo9c:not(._1paQt) .F9Fy2{padding-right:344px}}._2PjBX ._2kCN0{width:100%}@media screen and (min-width:840px){._2PjBX ._2kCN0{width:384px}._2PjBX._3yo9c ._3aW3s{right:384px}._2PjBX._3yo9c:not(._1paQt) .F9Fy2{padding-right:408px}}._16Oxc ._2kCN0{width:100%}@media screen and (min-width:840px){._16Oxc ._2kCN0{width:448px}._16Oxc._3yo9c ._3aW3s{right:448px}._16Oxc._3yo9c:not(._1paQt) .F9Fy2{padding-right:472px}}._3fr9v ._2kCN0{width:100%}@media screen and (min-width:840px){._3fr9v ._2kCN0{width:512px}._3fr9v._3yo9c ._3aW3s{right:512px}._3fr9v._3yo9c:not(._1paQt) .F9Fy2{padding-right:536px}}.iF_4K ._2kCN0{width:100%}@media screen and (min-width:840px){.iF_4K ._2kCN0{width:576px}.iF_4K._3yo9c ._3aW3s{right:576px}.iF_4K._3yo9c:not(._1paQt) .F9Fy2{padding-right:600px}}._3mnwI ._2kCN0{width:100%}@media screen and (min-width:840px){._3mnwI ._2kCN0{width:640px}._3mnwI._3yo9c ._3aW3s{right:640px}._3mnwI._3yo9c:not(._1paQt) .F9Fy2{padding-right:664px}}._2uccf ._2kCN0{width:100%}@media screen and (min-width:840px){._2uccf ._2kCN0{width:704px}._2uccf._3yo9c ._3aW3s{right:704px}._2uccf._3yo9c:not(._1paQt) .F9Fy2{padding-right:728px}}._1pU-9 ._2kCN0{width:100%}@media screen and (min-width:840px){._1pU-9 ._2kCN0{width:768px}._1pU-9._3yo9c ._3aW3s{right:768px}._1pU-9._3yo9c:not(._1paQt) .F9Fy2{padding-right:792px}}@media screen and (min-width:600px) and (orientation:landscape){._1EWpa ._2kCN0{width:56px}._1EWpa._3yo9c ._3aW3s{right:56px}._1EWpa._3yo9c:not(._1paQt) .F9Fy2{padding-right:80px}}@media screen and (min-width:600px) and (orientation:portrait){._1EWpa ._2kCN0{width:64px}._1EWpa._3yo9c ._3aW3s{right:64px}._1EWpa._3yo9c:not(._1paQt) .F9Fy2{padding-right:88px}}@media screen and (min-width:600px) and (orientation:landscape){._37z5O ._2kCN0{width:112px}._37z5O._3yo9c ._3aW3s{right:112px}._37z5O._3yo9c:not(._1paQt) .F9Fy2{padding-right:136px}}@media screen and (min-width:600px) and (orientation:portrait){._37z5O ._2kCN0{width:128px}._37z5O._3yo9c ._3aW3s{right:128px}._37z5O._3yo9c:not(._1paQt) .F9Fy2{padding-right:152px}}@media screen and (min-width:600px) and (orientation:landscape){._24Dtc ._2kCN0{width:168px}._24Dtc._3yo9c ._3aW3s{right:168px}._24Dtc._3yo9c:not(._1paQt) .F9Fy2{padding-right:192px}}@media screen and (min-width:600px) and (orientation:portrait){._24Dtc ._2kCN0{width:192px}._24Dtc._3yo9c ._3aW3s{right:192px}._24Dtc._3yo9c:not(._1paQt) .F9Fy2{padding-right:216px}}@media screen and (min-width:600px) and (orientation:landscape){._28mqi ._2kCN0{width:224px}._28mqi._3yo9c ._3aW3s{right:224px}._28mqi._3yo9c:not(._1paQt) .F9Fy2{padding-right:248px}}@media screen and (min-width:600px) and (orientation:portrait){._28mqi ._2kCN0{width:256px}._28mqi._3yo9c ._3aW3s{right:256px}._28mqi._3yo9c:not(._1paQt) .F9Fy2{padding-right:280px}}@media screen and (min-width:600px) and (orientation:landscape){.K39iB ._2kCN0{width:280px}.K39iB._3yo9c ._3aW3s{right:280px}.K39iB._3yo9c:not(._1paQt) .F9Fy2{padding-right:304px}}@media screen and (min-width:600px) and (orientation:portrait){.K39iB ._2kCN0{width:320px}.K39iB._3yo9c ._3aW3s{right:320px}.K39iB._3yo9c:not(._1paQt) .F9Fy2{padding-right:344px}}@media screen and (min-width:600px) and (orientation:landscape){._2PjBX ._2kCN0{width:336px}._2PjBX._3yo9c ._3aW3s{right:336px}._2PjBX._3yo9c:not(._1paQt) .F9Fy2{padding-right:360px}}@media screen and (min-width:600px) and (orientation:portrait){._2PjBX ._2kCN0{width:384px}._2PjBX._3yo9c ._3aW3s{right:384px}._2PjBX._3yo9c:not(._1paQt) .F9Fy2{padding-right:408px}}@media screen and (min-width:600px) and (orientation:landscape){._16Oxc ._2kCN0{width:392px}._16Oxc._3yo9c ._3aW3s{right:392px}._16Oxc._3yo9c:not(._1paQt) .F9Fy2{padding-right:416px}}@media screen and (min-width:600px) and (orientation:portrait){._16Oxc ._2kCN0{width:448px}._16Oxc._3yo9c ._3aW3s{right:448px}._16Oxc._3yo9c:not(._1paQt) .F9Fy2{padding-right:472px}}@media screen and (min-width:600px) and (orientation:landscape){._3fr9v ._2kCN0{width:448px}._3fr9v._3yo9c ._3aW3s{right:448px}._3fr9v._3yo9c:not(._1paQt) .F9Fy2{padding-right:472px}}@media screen and (min-width:600px) and (orientation:portrait){._3fr9v ._2kCN0{width:512px}._3fr9v._3yo9c ._3aW3s{right:512px}._3fr9v._3yo9c:not(._1paQt) .F9Fy2{padding-right:536px}}@media screen and (min-width:600px) and (orientation:landscape){.iF_4K ._2kCN0{width:504px}.iF_4K._3yo9c ._3aW3s{right:504px}.iF_4K._3yo9c:not(._1paQt) .F9Fy2{padding-right:528px}}@media screen and (min-width:600px) and (orientation:portrait){.iF_4K ._2kCN0{width:576px}.iF_4K._3yo9c ._3aW3s{right:576px}.iF_4K._3yo9c:not(._1paQt) .F9Fy2{padding-right:600px}}@media screen and (min-width:720px){._1EWpa ._2kCN0{width:64px}._1EWpa._3yo9c ._3aW3s{right:64px}._1EWpa._3yo9c:not(._1paQt) .F9Fy2{padding-right:88px}}@media screen and (min-width:720px){._37z5O ._2kCN0{width:128px}._37z5O._3yo9c ._3aW3s{right:128px}._37z5O._3yo9c:not(._1paQt) .F9Fy2{padding-right:152px}}@media screen and (min-width:720px){._24Dtc ._2kCN0{width:192px}._24Dtc._3yo9c ._3aW3s{right:192px}._24Dtc._3yo9c:not(._1paQt) .F9Fy2{padding-right:216px}}@media screen and (min-width:720px){._28mqi ._2kCN0{width:256px}._28mqi._3yo9c ._3aW3s{right:256px}._28mqi._3yo9c:not(._1paQt) .F9Fy2{padding-right:280px}}@media screen and (min-width:720px){.K39iB ._2kCN0{width:320px}.K39iB._3yo9c ._3aW3s{right:320px}.K39iB._3yo9c:not(._1paQt) .F9Fy2{padding-right:344px}}@media screen and (min-width:720px){._2PjBX ._2kCN0{width:384px}._2PjBX._3yo9c ._3aW3s{right:384px}._2PjBX._3yo9c:not(._1paQt) .F9Fy2{padding-right:408px}}@media screen and (min-width:720px){._16Oxc ._2kCN0{width:448px}._16Oxc._3yo9c ._3aW3s{right:448px}._16Oxc._3yo9c:not(._1paQt) .F9Fy2{padding-right:472px}}@media screen and (min-width:720px){._3fr9v ._2kCN0{width:512px}._3fr9v._3yo9c ._3aW3s{right:512px}._3fr9v._3yo9c:not(._1paQt) .F9Fy2{padding-right:536px}}@media screen and (min-width:720px){.iF_4K ._2kCN0{width:576px}.iF_4K._3yo9c ._3aW3s{right:576px}.iF_4K._3yo9c:not(._1paQt) .F9Fy2{padding-right:600px}}@media screen and (min-width:720px){._3mnwI ._2kCN0{width:640px}._3mnwI._3yo9c ._3aW3s{right:640px}._3mnwI._3yo9c:not(._1paQt) .F9Fy2{padding-right:664px}}._10h-v ._2kCN0{width:100%}.BYRr2 ._2kCN0{width:100%}._2L3ft ._2kCN0{width:100%}._31jol ._2kCN0{width:100%}._2Xvmh ._2kCN0{width:100%}._3T7B6 ._2kCN0{width:100%}@media screen and (min-width:720px){._10h-v ._3aW3s{right:25%}._10h-v ._2kCN0{width:25%}._10h-v:not(._1paQt) .F9Fy2{padding-right:calc(25% + 24px)}.BYRr2 ._3aW3s{right:33%}.BYRr2 ._2kCN0{width:33%}.BYRr2:not(._1paQt) .F9Fy2{padding-right:calc(33% + 24px)}._2L3ft ._3aW3s{right:50%}._2L3ft ._2kCN0{width:50%}._2L3ft:not(._1paQt) .F9Fy2{padding-right:calc(50% + 24px)}._31jol ._3aW3s{right:66%}._31jol ._2kCN0{width:66%}._31jol:not(._1paQt) .F9Fy2{padding-right:calc(66% + 24px)}._2Xvmh ._3aW3s{right:75%}._2Xvmh ._2kCN0{width:75%}._2Xvmh:not(._1paQt) .F9Fy2{padding-right:calc(75% + 24px)}._3T7B6 ._3aW3s{right:100%}._3T7B6 ._2kCN0{width:100%}._3T7B6:not(._1paQt) .F9Fy2{padding-right:calc(100% + 24px)}}._3Py1Z{background:#303f9f;color:#fff;font-family:Roboto,Helvetica,Arial,sans-serif;height:64px;padding:0 24px;transition-duration:.5s;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;transition-timing-function:cubic-bezier(.215,.61,.355,1);box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._3Py1Z *,._3Py1Z ::after,._3Py1Z ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._3Py1Z.PyOfn{-webkit-transform:translateY(-100%);transform:translateY(-100%)}._3Py1Z:not(._1J9he){box-shadow:0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12),0 2px 4px -1px rgba(0,0,0,.2)}._3Py1Z._2dwFx{left:0;position:fixed;right:0;top:0;z-index:300}._3Py1Z .lGWLJ{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:100%;position:relative;width:100%}._3Py1Z a{color:#fff}@media screen and (max-width:480px) and (orientation:portrait){._3Py1Z{height:56px}}@media screen and (max-width:600px) and (orientation:landscape){._3Py1Z{height:48px}}._37vtt{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:18px;font-weight:700;overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}._37vtt>small{font-size:18px;font-weight:400}._30BcY{margin-left:-12px}._1hv3P{margin-left:auto;margin-right:-12px}._1-mD4{font-size:18px;margin-right:10px}._1Od3D{-ms-flex-line-pack:center;align-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;line-height:1.5;position:relative;transition:opacity .35s cubic-bezier(.4,0,.2,1);box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._1Od3D *,._1Od3D ::after,._1Od3D ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._1Od3D:not(._3blKB){opacity:.5}._1Od3D:active,._1Od3D:hover{opacity:1}._1Od3D>*{vertical-align:middle}._1Od3D>abbr{text-transform:capitalize}._1Od3D>small{font-size:12px;margin-left:8px;text-align:center}.caNNQ{display:inline-block;list-style:none;margin:0;padding:8px 0;position:relative;text-align:left;white-space:nowrap;width:100%;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}.caNNQ *,.caNNQ ::after,.caNNQ ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}.caNNQ+._2Jg3-{margin-top:-8px}.q2l8C{color:#757575;font-size:14px;font-weight:500;line-height:48px;margin:-8px 0 0;padding-left:16px}._2Jg3-{background-color:#eee;border:0;height:1px;margin:-1px 0 0}._2Jg3-._1HHo_{margin-left:72px;margin-right:16px}.ni6RH{position:relative}.ni6RH>[data-react-toolbox=ripple]{overflow:hidden}.ni6RH ._2mi0Y{color:#757575}.ni6RH~._2Jg3-{margin-bottom:8px;margin-top:8px}._2GtDw{-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#212121;display:-webkit-box;display:-ms-flexbox;display:flex;min-height:48px;padding:0 16px;position:relative}._2GtDw._1OoR-:not(._38DD6):hover{background-color:#eee;cursor:pointer}._2GtDw._38DD6{pointer-events:none}._2GtDw._38DD6:not(.OVyge){opacity:.5}._2GtDw._38DD6>._3SG-0>[data-react-toolbox=label]{opacity:.5}.bHOJq [data-react-toolbox=font-icon]{width:18px}.bHOJq :last-child>[data-react-toolbox=font-icon]{margin-right:22px}.OQ3Je>:last-child{margin-right:0}.OQ3Je>:first-child{margin-left:16px}.OQ3Je,.bHOJq{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto}.VB7pN{display:-webkit-box;display:-ms-flexbox;display:flex;margin:8px 16px 8px 0}.VB7pN>*{padding:0}.VB7pN>[data-react-toolbox=font-icon]{color:#757575;font-size:24px}._2FBCh{display:block;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}._2FBCh.EO5bo{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:72px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}._3SG-0{-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;display:-webkit-box;display:-ms-flexbox;display:flex;height:100%;margin:0;min-height:48px;width:100%}._3SG-0>[data-react-toolbox=check]{margin-right:38px}._3SG-0>[data-react-toolbox=label]{padding-left:0}._12FqV{display:block}._12FqV:not(._3SxNr){color:#757575;font-size:14px;padding-top:3px;white-space:normal}._12FqV._3SxNr{color:#212121;font-size:16px}._2aMxm{display:inline-block;position:relative;text-align:center;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._2aMxm *,._2aMxm ::after,._2aMxm ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._2aMxm ._1b8Ml{cursor:pointer}._1gvr5{display:inline-block;position:relative}._1gvr5.SYeW8{left:0;position:absolute;top:0}._1gvr5.SYeW8>._2PdTB{-webkit-transform-origin:0 0;transform-origin:0 0}._1gvr5.DFQvY{position:absolute;right:0;top:0}._1gvr5.DFQvY>._2PdTB{-webkit-transform-origin:100% 0;transform-origin:100% 0}._1gvr5._3i7lA{bottom:0;left:0;position:absolute}._1gvr5._3i7lA>._2PdTB{-webkit-transform-origin:0 100%;transform-origin:0 100%}._1gvr5._3q-zB{bottom:0;position:absolute;right:0}._1gvr5._3q-zB>._2PdTB{-webkit-transform-origin:100% 100%;transform-origin:100% 100%}._1gvr5:not(._2xf5n){pointer-events:none;z-index:200}._1gvr5:not(._2xf5n)>._2PdTB{opacity:0;-webkit-transform:scale(0);transform:scale(0);transition:opacity .2s cubic-bezier(.4,0,.2,1),-webkit-transform .3s cubic-bezier(.4,0,.2,1);transition:transform .3s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1);transition:transform .3s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1),-webkit-transform .3s cubic-bezier(.4,0,.2,1);will-change:transform}._1gvr5:not(._2xf5n)>._2t8UE{left:0;margin:0;opacity:0;position:absolute;top:0}._1gvr5:not(._2xf5n)._3o1JI:not(._2Cekp)>._2PdTB{transition-delay:.3s}._1gvr5:not(._2xf5n)._3o1JI:not(._2Cekp)>._2t8UE{transition-delay:.3s}._1gvr5:not(._2xf5n)._2Cekp{pointer-events:all}._1gvr5:not(._2xf5n)._2Cekp>._2PdTB{opacity:1;-webkit-transform:scale(1);transform:scale(1)}._1gvr5:not(._2xf5n)._2Cekp>._2t8UE{opacity:1;transition:opacity .2s cubic-bezier(.4,0,.2,1),clip .3s cubic-bezier(.4,0,.2,1)}._2PdTB{background-color:#fff;border-radius:2px;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);display:block;left:0;position:absolute;top:0}._2t8UE{display:block;list-style:none;padding:8px 0;position:relative;text-align:left;white-space:nowrap}.lyzBJ{-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#212121;display:-webkit-box;display:-ms-flexbox;display:flex;font-size:16px;height:48px;overflow:hidden;padding:0 16px;position:relative}.lyzBJ:not(.zGTpA):hover{background-color:#eee;cursor:pointer}.lyzBJ.zGTpA{opacity:.5;pointer-events:none}.lyzBJ._2-j_P{background-color:transparent;font-weight:500}.lyzBJ ._2m_Cl{color:#757575}.lyzBJ ._1b8Ml{font-size:24px;width:38.4px}._3MsfE{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:16px}._1anRY{margin-left:16px}.VX5Lv{background-color:#eee;border:0;display:block;height:1px;margin:12px 0;outline:0;padding:0;width:100%}._1MJ9B>[data-react-toolbox=button],._1MJ9B>[data-react-toolbox=link]{display:inline-block;margin:0 5px}.xUlwz>[data-react-toolbox=button],.xUlwz>[data-react-toolbox=link]{display:block;margin:5px}._1MJ9B,.xUlwz{padding:5px;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._1MJ9B *,._1MJ9B ::after,._1MJ9B ::before,.xUlwz *,.xUlwz ::after,.xUlwz ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._1MJ9B>[data-react-toolbox=link],.xUlwz>[data-react-toolbox=link]{color:#000}._3vxHj{background:#eee;display:inline-block;height:4px;overflow:hidden;position:relative;width:100%}._3vxHj._1gPzb .I0PhY{-webkit-animation:_1cU21 1s linear infinite;animation:_1cU21 1s linear infinite;-webkit-transform-origin:center center;transform-origin:center center}.I0PhY,.SzbNd{bottom:0;left:0;position:absolute;right:0;top:0;-webkit-transform:scaleX(0);transform:scaleX(0);-webkit-transform-origin:left center;transform-origin:left center;transition-duration:.35s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.I0PhY{background-color:#3f51b5}.SzbNd{background-image:linear-gradient(to right,rgba(255,255,255,.7),rgba(255,255,255,.7)),linear-gradient(to right,#3f51b5,#3f51b5)}._2j3vC{display:inline-block;height:60px;position:relative;-webkit-transform:rotate(-90deg);transform:rotate(-90deg);width:60px}._2j3vC._1gPzb .DlWjM{-webkit-animation:zfZzh 2s linear infinite;animation:zfZzh 2s linear infinite}._2j3vC._1gPzb ._1xZSU{-webkit-animation:_3DSlU 1.5s ease-in-out infinite;animation:_3DSlU 1.5s ease-in-out infinite;stroke-dasharray:1.25,250;stroke-dashoffset:0}._2j3vC._1gPzb._3XHT8 ._1xZSU{-webkit-animation:_3DSlU 1.5s ease-in-out infinite,Z_PDt 6s ease-in-out infinite;animation:_3DSlU 1.5s ease-in-out infinite,Z_PDt 6s ease-in-out infinite}._2j3vC[disabled] .I0PhY,._3vxHj[disabled] .I0PhY{background-color:rgba(0,0,0,.26)}._2j3vC[disabled] .SzbNd,._3vxHj[disabled] .SzbNd{background-image:linear-gradient(to right,rgba(255,255,255,.7),rgba(255,255,255,.7)),linear-gradient(to right,rgba(0,0,0,.26),rgba(0,0,0,.26))}.DlWjM{height:100%;width:100%}._1xZSU{fill:none;stroke:#3f51b5;stroke-dasharray:0,250;stroke-dashoffset:0;stroke-linecap:round;stroke-miterlimit:20;stroke-width:4;transition:stroke-dasharray .35s cubic-bezier(.4,0,.2,1)}@-webkit-keyframes _1cU21{0%{-webkit-transform:translate(-50%) scaleX(0);transform:translate(-50%) scaleX(0)}50%{-webkit-transform:translate(0) scaleX(.3);transform:translate(0) scaleX(.3)}100%{-webkit-transform:translate(50%) scaleX(0);transform:translate(50%) scaleX(0)}}@keyframes _1cU21{0%{-webkit-transform:translate(-50%) scaleX(0);transform:translate(-50%) scaleX(0)}50%{-webkit-transform:translate(0) scaleX(.3);transform:translate(0) scaleX(.3)}100%{-webkit-transform:translate(50%) scaleX(0);transform:translate(50%) scaleX(0)}}@-webkit-keyframes zfZzh{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes zfZzh{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes _3DSlU{0%{stroke-dasharray:1.25,250;stroke-dashoffset:0}50%{stroke-dasharray:111.25,250;stroke-dashoffset:-43.75}100%{stroke-dasharray:111.25,250;stroke-dashoffset:-155}}@keyframes _3DSlU{0%{stroke-dasharray:1.25,250;stroke-dashoffset:0}50%{stroke-dasharray:111.25,250;stroke-dashoffset:-43.75}100%{stroke-dasharray:111.25,250;stroke-dashoffset:-155}}@-webkit-keyframes Z_PDt{0%{stroke:#4285f4}25%{stroke:#de3e35}50%{stroke:#f7c223}75%{stroke:#1b9a59}100%{stroke:#4285f4}}@keyframes Z_PDt{0%{stroke:#4285f4}25%{stroke:#de3e35}50%{stroke:#f7c223}75%{stroke:#1b9a59}100%{stroke:#4285f4}}._1vWJb{border:2px solid #000;border-radius:50%;cursor:pointer;display:inline-block;height:20px;position:relative;vertical-align:top;width:20px;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._1vWJb *,._1vWJb ::after,._1vWJb ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._1vWJb::before{background-color:#3f51b5;border-radius:50%;content:'';height:100%;left:0;position:absolute;top:0;-webkit-transform:scale(0);transform:scale(0);transition:-webkit-transform .2s cubic-bezier(.4,0,.2,1);transition:transform .2s cubic-bezier(.4,0,.2,1);transition:transform .2s cubic-bezier(.4,0,.2,1),-webkit-transform .2s cubic-bezier(.4,0,.2,1);width:100%}._1vWJb ._78FVB{background-color:#3f51b5;opacity:.3;transition-duration:650ms}._210O6{border:2px solid #3f51b5}._210O6::before{-webkit-transform:scale(.65);transform:scale(.65)}._36UDg{display:block;height:20px;margin-bottom:15px;position:relative;white-space:nowrap}._3guDD{color:#000;display:inline-block;font-size:14px;line-height:20px;padding-left:10px;vertical-align:top;white-space:nowrap}._2CPDD{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:0;height:0;margin:0;opacity:0;padding:0;position:absolute;width:0}._2CPDD:focus~._1vWJb{box-shadow:0 0 0 10px rgba(0,0,0,.1)}._2CPDD:focus~._210O6{box-shadow:0 0 0 10px rgba(63,81,181,.26)}._39I6g ._3guDD{color:rgba(0,0,0,.26)}._39I6g ._1vWJb{border-color:rgba(0,0,0,.26);cursor:auto}._39I6g ._210O6{border-color:rgba(0,0,0,.26);cursor:auto}._39I6g ._210O6::before{background-color:rgba(0,0,0,.26)}._-dLk{height:32px;margin-right:32px;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:calc(100% - 32px);box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._-dLk *,._-dLk ::after,._-dLk ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._-dLk:not(:last-child){margin-right:42px}._-dLk:not(:first-child){margin-left:10px}.kq8Om{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:transparent;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;height:32px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;left:0;position:relative;top:0;width:32px;z-index:200}._8VjZ5{background-color:#3f51b5;border-radius:50%;height:12px;transition-duration:.1s;transition-property:height,width,background-color,border;transition-timing-function:cubic-bezier(.4,0,.2,1);width:12px;z-index:100}._2x5j_{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;height:2px;left:0;pointer-events:none;position:absolute;top:15px;width:calc(100% + 2px)}._2x5j_::after{background-color:#000;border-radius:50%;content:'';display:block;height:2px;width:2px}._12aGJ{-webkit-box-flex:1;-ms-flex:1;flex:1}._12aGJ::after{background-color:#000;border-radius:50%;content:'';display:block;height:2px;width:2px}._2JHGy{margin-bottom:0;padding:0;width:50px}._2JHGy>input{text-align:center}._2R4jW{height:100%;left:16px;position:absolute;top:0;width:100%}._2R4jW ._3p0mR{height:2px;position:absolute;top:15px}._2R4jW ._3p0mR [data-ref=value]{transition-duration:0s}._3-BtZ:focus .kq8Om::before{background-color:#3f51b5;border-radius:50%;bottom:0;content:'';left:0;opacity:.26;position:absolute;right:0;top:0;z-index:1}._3-BtZ[disabled]{cursor:auto;pointer-events:none}._3-BtZ[disabled] ._8VjZ5{background-color:rgba(177,177,177,1)}._3-BtZ.hkAL6{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}._3-BtZ._28Oo0 ._8VjZ5::before{background-color:#3f51b5;border-radius:50% 50% 50% 0;content:'';height:26px;left:0;margin-left:3px;position:absolute;top:0;-webkit-transform:rotate(-45deg) scale(0) translate(0);transform:rotate(-45deg) scale(0) translate(0);transition:background-color .18s ease,-webkit-transform .2s ease;transition:transform .2s ease,background-color .18s ease;transition:transform .2s ease,background-color .18s ease,-webkit-transform .2s ease;width:26px}._3-BtZ._28Oo0 ._8VjZ5::after{color:#fff;content:attr(data-value);font-size:10px;height:26px;left:0;position:absolute;text-align:center;top:0;-webkit-transform:scale(0) translate(0);transform:scale(0) translate(0);transition:background-color .18s ease,-webkit-transform .2s ease;transition:transform .2s ease,background-color .18s ease;transition:transform .2s ease,background-color .18s ease,-webkit-transform .2s ease;width:32px}._3-BtZ._292qK._28Oo0 ._8VjZ5::before{-webkit-transform:rotate(-45deg) scale(1) translate(17px,-17px);transform:rotate(-45deg) scale(1) translate(17px,-17px);transition-delay:.1s}._3-BtZ._292qK._28Oo0 ._8VjZ5::after{-webkit-transform:scale(1) translate(0,-17px);transform:scale(1) translate(0,-17px);transition-delay:.1s}._3-BtZ._292qK:not(._28Oo0)._2Oh5L ._2R4jW{left:30px;width:calc(100% - 14px)}._3-BtZ._292qK:not(._28Oo0) ._8VjZ5{height:100%;-webkit-transform:translateZ(0);transform:translateZ(0);width:100%}._3-BtZ._2Oh5L ._8VjZ5{background-color:transparent;border:2px solid #eee}._3-BtZ._2Oh5L ._8VjZ5::before{background-color:#3f51b5}._3-BtZ._2Oh5L ._2R4jW{left:20px;transition:left .18s ease,width .18s ease;width:calc(100% - 2px * 2)}._3-BtZ._2Oh5L._28Oo0 ._8VjZ5{background-color:#fff}._3-BtZ._2Oh5L._28Oo0 ._2R4jW{left:16px;width:100%}.zDi3X{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#212121;border-radius:2px;bottom:0;color:#fff;display:-webkit-box;display:-ms-flexbox;display:flex;left:24px;margin:14px auto 0;padding:14px 24px;position:fixed;right:24px;transition:all .35s cubic-bezier(.4,0,.2,1) .35s;z-index:200;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}.zDi3X *,.zDi3X ::after,.zDi3X ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}.zDi3X._2Y0Cy ._2pCxU{color:#4caf50}.zDi3X._2li3o ._2pCxU{color:#eeff41}.zDi3X._3731C ._2pCxU{color:#f44336}.zDi3X:not(._38CsO){-webkit-transform:translateY(100%);transform:translateY(100%)}.zDi3X._38CsO{-webkit-transform:translateY(0);transform:translateY(0)}._1JIbY{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:14px}._2pCxU{margin:-7px -12px -7px 48px;min-width:inherit}._1T2D0{display:block;margin-bottom:15px;position:relative;white-space:normal;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._1T2D0 *,._1T2D0 ::after,._1T2D0 ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}.rxx-p{color:#000;display:inline-block;font-size:14px;line-height:24px;padding-left:10px;vertical-align:top;white-space:nowrap}._1pMry{border-radius:50%;cursor:pointer;height:20px;position:absolute;top:-3px;transition-duration:.28s;transition-property:left;transition-timing-function:cubic-bezier(.4,0,.2,1);width:20px;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._1pMry *,._1pMry ::after,._1pMry ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._1pMry ._1I9tv{background-color:#3f51b5;opacity:.3;transition-duration:650ms}._25ui_,.p92Yp{border-radius:14px;cursor:pointer;display:inline-block;height:14px;margin-top:5px;position:relative;vertical-align:top;width:36px}.p92Yp{background:rgba(63,81,181,.5)}.p92Yp ._1pMry{background:#3f51b5;box-shadow:0 3px 4px 0 rgba(0,0,0,.14),0 3px 3px -2px rgba(0,0,0,.2),0 1px 8px 0 rgba(0,0,0,.12);left:16px}._25ui_{background:rgba(0,0,0,.26)}._25ui_ ._1pMry{background:#fafafa;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);left:0}._25ui_ ._1I9tv{background:rgba(0,0,0,.4)}._3BTU_{height:0;opacity:0;overflow:hidden;width:0}._3BTU_:focus:not(:active)+._1ZBFp>._1pMry::before,._3BTU_:focus:not(:active)+._2Bwve>._1pMry::before{background-color:transparent;border-radius:50%;box-sizing:border-box;content:'';display:inline-block;height:8px;left:50%;position:absolute;top:50%;-webkit-transform:translate(-4px,-4px);transform:translate(-4px,-4px);width:8px}._3BTU_:focus:not(:active)+._2Bwve>._1pMry::before{background-color:rgba(63,81,181,.26);box-shadow:0 0 0 20px rgba(63,81,181,.26)}._3BTU_:focus:not(:active)+._1ZBFp>._1pMry::before{background-color:rgba(0,0,0,.1);box-shadow:0 0 0 20px rgba(0,0,0,.1)}._1CQ_q .rxx-p{color:rgba(0,0,0,.26)}._1CQ_q ._25ui_,._1CQ_q .p92Yp{background:rgba(0,0,0,.12);cursor:auto}._1CQ_q ._1pMry{background-color:#bdbdbd;border-color:transparent;cursor:auto}._2xofu{background-color:#fff;border-collapse:collapse;font-size:13px;width:100%;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._2xofu *,._2xofu ::after,._2xofu ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._1eF5Z{padding-bottom:3px;white-space:nowrap}._1qppP{color:rgba(0,0,0,.87);height:48px;transition-duration:.28s;transition-property:background-color;transition-timing-function:cubic-bezier(.4,0,.2,1)}._1qppP:hover{background-color:#eee}._1qppP._1H1dU{background-color:#f5f5f5}._18bqN,.gfcPv{padding:0 18px 12px 18px;text-align:left}._18bqN:first-of-type,.gfcPv:first-of-type{padding-left:24px}._18bqN:last-of-type,.gfcPv:last-of-type{padding-right:24px}._18bqN._3suRQ,.gfcPv._3suRQ{text-align:right}._18bqN{border-bottom:1px solid #e6e6e6;border-top:1px solid #e6e6e6;height:48px;padding-top:12px;vertical-align:middle}._18bqN._2yhwA{width:18px}._18bqN._2yhwA>*{margin:0}.gfcPv{color:rgba(0,0,0,.54);font-size:12px;font-weight:500;height:48px;line-height:24px;padding-bottom:8px;text-overflow:ellipsis;vertical-align:bottom}.gfcPv._2yhwA{width:18px}.gfcPv._2yhwA>*{margin:0 0 3px}.gfcPv._2r5OG{color:rgba(0,0,0,.87);cursor:pointer}.gfcPv._2r5OG:hover ._3NJs5{color:rgba(0,0,0,.26)}._3NJs5{display:inline-block;font-size:16px;margin-right:3px;transition:.28s -webkit-transform cubic-bezier(.4,0,.2,1);transition:.28s transform cubic-bezier(.4,0,.2,1);transition:.28s transform cubic-bezier(.4,0,.2,1),.28s -webkit-transform cubic-bezier(.4,0,.2,1);vertical-align:sub}._3NJs5.wZHUA{-webkit-transform:rotate(180deg);transform:rotate(180deg)}._2EaQV{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._2EaQV *,._2EaQV ::after,._2EaQV ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._3e55Z{box-shadow:inset 0 -1px #eee;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;position:relative}._3oZmF{display:-webkit-box;display:-ms-flexbox;display:flex}._3oZmF ._3e55Z{-webkit-box-flex:1;-ms-flex:1;flex:1}.wPL4g{color:#000;padding:0 12px}.i_TGW{-webkit-box-align:center;-ms-flex-align:center;align-items:center;box-shadow:inset 0 -1px #eee;cursor:pointer;display:-webkit-box;display:-ms-flexbox;display:flex}._1yb8L{color:rgba(0,0,0,.7);font-size:14px;font-weight:500;line-height:1;padding:17px 12px;position:relative;text-transform:uppercase;transition-duration:.35s;transition-property:box-shadow,color;transition-timing-function:cubic-bezier(.4,0,.2,1)}._1yb8L>._3c0W3{overflow:hidden}._1yb8L._2LZ7Z{color:#000}._1yb8L._2gi1s{opacity:.2}._1yb8L:not(._2gi1s){cursor:pointer}._1yb8L._3kq1J{display:none}._1yb8L._1OFOx{padding-bottom:13px;padding-top:13px;text-align:center}._1yb8L._1Yf4A ._1LUZH{margin-bottom:8px}._1LUZH{display:block;height:24px;line-height:24px;margin:0 auto}._1xgdB{background-color:#3f51b5;height:2px;margin-top:-2px;position:absolute;transition-duration:.35s;transition-property:left,width;transition-timing-function:cubic-bezier(.4,0,.2,1);width:0}._26SP9{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding:17px 12px}._26SP9:not(._2LZ7Z){display:none}._26SP9._2LZ7Z{display:-webkit-box;display:-ms-flexbox;display:flex}._3bROj ._1yb8L{-webkit-box-flex:1;-ms-flex:1;flex:1;text-align:center}._33mT_ ._3e55Z,._33mT_ .i_TGW{background-color:#3f51b5}._33mT_ ._1yb8L{color:rgba(255,255,255,.3)}._33mT_ ._1yb8L._2LZ7Z{color:#fff}._33mT_ .wPL4g{color:#fff}._33mT_ ._1xgdB{background-color:#ff4081}._2APuy:not(._2Vc_4)>._2Z4kT{cursor:pointer}._2u1sB{background:#3f51b5;color:#fff;font-size:52px;padding:10px;position:relative;text-align:center;width:100%}._3Bp7w,._3Kl2E{cursor:pointer;display:inline-block;opacity:.6}._1c2VQ{margin:0 5px;opacity:.6}._1vAVQ{font-size:16px;height:44px;line-height:22px;margin-top:-22px;position:absolute;right:20px;text-align:center;top:50%;width:40px}._14hQA,.aU9C9{cursor:pointer;display:block;opacity:.6}._1YlHq{width:300px}._1YlHq>[role=body]{overflow-y:visible;padding:0}._1YlHq>[role=navigation]>._1Kf0L{color:#3f51b5}._1YlHq>[role=navigation]>._1Kf0L:hover{background:rgba(63,81,181,.2)}._1YlHq>[role=navigation]>._1Kf0L:focus:not(:active){background:rgba(63,81,181,.2)}._1YlHq._26MJk ._14hQA,._1YlHq._2JeOG ._3Kl2E,._1YlHq._3H_-m .aU9C9,._1YlHq._3UMNx ._3Bp7w{opacity:1}._2CwF0{padding:15px 20px}.zCpyM{position:relative;z-index:100}._3paoD{background-color:#eee;border-radius:50%;position:absolute;width:100%}._3ui0r{border-radius:50%;cursor:pointer;left:50%;position:absolute;top:50%;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);z-index:100}.qr9pw{height:20px;margin-left:-10px;margin-top:-10px;pointer-events:none;position:relative;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:20px}.qr9pw._30yS_{color:#fff}._1rtAF{background-color:#3f51b5;bottom:50%;display:block;left:50%;margin-left:-2px;position:absolute;-webkit-transform-origin:50% 100%;transform-origin:50% 100%;width:4px}._1rtAF::before{background-color:#3f51b5;border-radius:50%;bottom:0;content:'';height:10px;left:50%;margin-bottom:-5px;margin-left:-5px;position:absolute;width:10px}._1rtAF._3eEHh>.VqPQb{background-color:rgba(63,81,181,.2)}._1rtAF._3eEHh>.VqPQb::after{background:#3f51b5;border-radius:50%;content:'';height:12px;left:50%;margin-left:-6px;margin-top:-6px;position:absolute;top:50%;width:12px}._1rtAF._3eEHh>.VqPQb::before{background:#3f51b5;bottom:0;content:'';height:22px;left:50%;margin-left:-2px;position:absolute;width:4px}.VqPQb{background-color:#3f51b5;border-radius:50%;cursor:pointer;height:34px;left:50%;margin-left:-17px;position:absolute;top:-34px;width:34px}._1tgJ3,._3DTnI{position:absolute}._1EUpH,._1Fr4_{transition:opacity,-webkit-transform;transition:transform,opacity;transition:transform,opacity,-webkit-transform;transition-duration:.5s;transition-timing-function:cubic-bezier(.4,0,.2,1)}._3DTnI{opacity:0;-webkit-transform:scale(.85);transform:scale(.85)}._3DTnI._1Fr4_{opacity:1;-webkit-transform:scale(1);transform:scale(1)}._1tgJ3{opacity:1;-webkit-transform:scale(1);transform:scale(1)}._1tgJ3._1EUpH{opacity:0;-webkit-transform:scale(1.25);transform:scale(1.25)}._1Lb15,._3LDEu{position:absolute}._18Ean,._3y67C{transition:opacity,-webkit-transform;transition:transform,opacity;transition:transform,opacity,-webkit-transform;transition-duration:.5s;transition-timing-function:cubic-bezier(.4,0,.2,1)}._1Lb15{opacity:0;-webkit-transform:scale(1.25);transform:scale(1.25)}._1Lb15._3y67C{opacity:1;-webkit-transform:scale(1);transform:scale(1)}._3LDEu{opacity:1;-webkit-transform:scale(1);transform:scale(1)}._3LDEu._18Ean{opacity:0;-webkit-transform:scale(.85);transform:scale(.85)}._1v8bI{display:block;font-family:Roboto,Helvetica,Arial,sans-serif;font-size:10px;font-weight:700;line-height:14px;max-width:170px;padding:5px;pointer-events:none;position:absolute;text-align:center;text-transform:none;-webkit-transform:scale(0) translateX(-50%);transform:scale(0) translateX(-50%);-webkit-transform-origin:top left;transform-origin:top left;transition:cubic-bezier(.4,0,.2,1) .2s transform;z-index:200;box-sizing:border-box;font-family:Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}._1v8bI *,._1v8bI ::after,._1v8bI ::before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-touch-callout:none}._1v8bI._2xWjx{-webkit-transform:scale(1) translateX(-50%);transform:scale(1) translateX(-50%)}._1v8bI._1PfOK{-webkit-transform:scale(0) translateX(-50%) translateY(-100%);transform:scale(0) translateX(-50%) translateY(-100%)}._1v8bI._1PfOK._2xWjx{-webkit-transform:scale(1) translateX(-50%) translateY(-100%);transform:scale(1) translateX(-50%) translateY(-100%)}._1v8bI._3uj3d{-webkit-transform:scale(0) translateX(-100%) translateY(-50%);transform:scale(0) translateX(-100%) translateY(-50%)}._1v8bI._3uj3d._2xWjx{-webkit-transform:scale(1) translateX(-100%) translateY(-50%);transform:scale(1) translateX(-100%) translateY(-50%)}._1v8bI._3UQWj{-webkit-transform:scale(0) translateX(0) translateY(-50%);transform:scale(0) translateX(0) translateY(-50%)}._1v8bI._3UQWj._2xWjx{-webkit-transform:scale(1) translateX(0) translateY(-50%);transform:scale(1) translateX(0) translateY(-50%)}._9q2WH{background:rgba(97,97,97,.9);border-radius:2px;color:#fff;display:block;padding:8px} 2 | -------------------------------------------------------------------------------- /app/assets/css/theme.js: -------------------------------------------------------------------------------- 1 | module.exports={"RTAutocomplete":{"autocomplete":"_07g5","focus":"_3qQkg","suggestions":"_3-Nb6","values":"_14fVf","value":"cBUoJ","up":"_3rmye","suggestion":"_1erPE","active":"kDY3Z","input":"_1ryxc"},"RTChip":{"chip":"_3Iv9P","avatar":"_2o8mD","deletable":"_2hlBs","delete":"_3nnfj","deleteIcon":"_2sopz","deleteX":"_10NaZ"},"RTAvatar":{"avatar":"_3OjJz","image":"_2Ueo9","letter":"_26GdB"},"RTInput":{"input":"lFVgC","withIcon":"_1nKdf","icon":"_3ga1V","inputElement":"_4bZUj","bar":"_3FySS","label":"_34120","fixed":"GRQEP","required":"_2G0aY","hint":"bMyi_","filled":"_34NWn","error":"_2k5Jz","counter":"_1oTuT","disabled":"_3ZfJq","errored":"_2s74E","hidden":"_2gAMv"},"RTButton":{"button":"_2Agdx","rippleWrapper":"_3AVBi","squared":"_2GH_L","icon":"_3aBSX","solid":"_1ZxqC","raised":"_221ic _2Agdx _2GH_L _1ZxqC","flat":"_1jWAQ _2Agdx _2GH_L","floating":"_3IRMZ _2Agdx _1ZxqC","mini":"_2DCN-","toggle":"hC5Z2 _2Agdx","primary":"_3tTAW","accent":"_2wp6F","neutral":"_2CPs4","inverse":"_2SPZr"},"RTRipple":{"rippleWrapper":"_16N7o","ripple":"_3SV_u","rippleRestarting":"_2OZWa","rippleActive":"_3O2Ue"},"RTCard":{"card":"_8pay8","raised":"_1AHwB","cardMedia":"_3Yc6z","wide":"_35NNe","square":"_1HBxg","content":"ewAVM","contentOverlay":"_1bBKz","cardTitle":"_1dU3o","cardActions":"ZoLIG","cardText":"K_kzH","title":"_3qCP3","subtitle":"_3p3mO","large":"_2iwOK","small":"_1RHxe"},"RTCheckbox":{"field":"_3Tq32","ripple":"_2NWrZ","text":"dXU7C","input":"_271V1","check":"_1CXAo","checked":"nSz7s","checkmark-expand":"_3GU9D","disabled":"_2jVLS"},"RTDatePicker":{"input":"_2ISvI","disabled":"Cf3yF","inputElement":"x7MhN","header":"_2vLUd","year":"_1VWY-","date":"_3K2Ws","calendarWrapper":"_1t-4v","yearsDisplay":"_2OzvT","monthsDisplay":"_2DDdC","dialog":"_3fCV6","button":"_2hL6u","calendar":"_1X9ls","prev":"Nv9Bc","next":"_3iPkS","title":"_2ESpD","years":"zEdgW","active":"_1pjXb","week":"PcByv","days":"_1qh3T","day":"_2qF_L","month":"_1hSm5","slideRightEnter":"Rk89h","slideRightLeave":"_1nam4","slideRightEnterActive":"m5B3T","slideRightLeaveActive":"_2bZap","slideLeftEnter":"bGml_","slideLeftLeave":"_2WGqM","slideLeftEnterActive":"_3Ghls","slideLeftLeaveActive":"_2WLHG"},"RTDialog":{"wrapper":"_3nrqp","dialog":"_3lw90","active":"_3ea_1","small":"_38VTT","normal":"_1K3iz","large":"_10LcP","fullscreen":"_3tLXQ","title":"_2J-aP","body":"_1Ivuq","navigation":"wgwdj","button":"_22_c6"},"RTOverlay":{"overlay":"_2LA9x","active":"_1mb5R"},"RTDrawer":{"wrapper":"_3eRY8","drawer":"_1sAOY","active":"EWFXC","right":"_2-4-H","left":"FKhpR"},"RTDropdown":{"dropdown":"ZzBNK","active":"_1DQ-E","values":"_2767w","label":"_2KjGM","value":"_6c1D5","up":"_1OA-G","disabled":"_1skVH","field":"d5bru","errored":"_3dZUG","templateValue":"_6dCtT","required":"_1j4LX","error":"fySw3","selected":"_3uiEo"},"RTLayout":{"layout":"wiKya","panel":"_3aW3s","bodyScroll":"_2uzOU","sidebarDrawer":"_2kCN0","navDrawerDrawer":"Cte92","pinned":"qf0ha","clipped":"_1y5eh","appbarInner":"_1S9wz","appbarFixed":"_2Q-xL","appbarAppBar":"F9Fy2","navDrawerPinned":"_2eOy5","appbarLeftIcon":"fZ13o","navDrawerClipped":"_2kROG","navDrawerWrapper":"_2gpOZ","sidebarPinned":"_3yo9c","sidebarClipped":"_1paQt","sidebarWrapper":"_1TUxm","sidebarWidth1":"_1EWpa","sidebarWidth2":"_37z5O","sidebarWidth3":"_24Dtc","sidebarWidth4":"_28mqi","sidebarWidth5":"K39iB","sidebarWidth6":"_2PjBX","sidebarWidth7":"_16Oxc","sidebarWidth8":"_3fr9v","sidebarWidth9":"iF_4K","sidebarWidth10":"_3mnwI","sidebarWidth11":"_2uccf","sidebarWidth12":"_1pU-9","sidebarWidth25":"_10h-v","sidebarWidth33":"BYRr2","sidebarWidth50":"_2L3ft","sidebarWidth66":"_31jol","sidebarWidth75":"_2Xvmh","sidebarWidth100":"_3T7B6"},"RTAppBar":{"appBar":"_3Py1Z","scrollHide":"PyOfn","flat":"_1J9he","fixed":"_2dwFx","inner":"lGWLJ","title":"_37vtt","leftIcon":"_30BcY","rightIcon":"_1hv3P"},"RTLink":{"icon":"_1-mD4","link":"_1Od3D","active":"_3blKB"},"RTList":{"list":"caNNQ","divider":"_2Jg3-","subheader":"q2l8C","inset":"_1HHo_","listItem":"ni6RH","ripple":"_2mi0Y","item":"_2GtDw","selectable":"_1OoR-","disabled":"_38DD6","checkboxItem":"OVyge","checkbox":"_3SG-0","left":"bHOJq","right":"OQ3Je","itemAction":"VB7pN","itemContentRoot":"_2FBCh","large":"EO5bo","itemText":"_12FqV","primary":"_3SxNr"},"RTMenu":{"iconMenu":"_2aMxm","icon":"_1b8Ml","menu":"_1gvr5","topLeft":"SYeW8","outline":"_2PdTB","topRight":"DFQvY","bottomLeft":"_3i7lA","bottomRight":"_3q-zB","static":"_2xf5n","menuInner":"_2t8UE","rippled":"_3o1JI","active":"_2Cekp","menuItem":"lyzBJ","disabled":"zGTpA","selected":"_2-j_P","ripple":"_2m_Cl","caption":"_3MsfE","shortcut":"_1anRY","menuDivider":"VX5Lv"},"RTNavigation":{"horizontal":"_1MJ9B","vertical":"xUlwz"},"RTProgressBar":{"linear":"_3vxHj","linear-indeterminate-bar":"_1cU21","indeterminate":"_1gPzb","value":"I0PhY","buffer":"SzbNd","circular":"_2j3vC","circular-indeterminate-bar-rotate":"zfZzh","circular-indeterminate-bar-dash":"_3DSlU","colors":"Z_PDt","circle":"DlWjM","path":"_1xZSU","multicolor":"_3XHT8"},"RTRadio":{"radio":"_1vWJb","ripple":"_78FVB","radioChecked":"_210O6 _1vWJb","field":"_36UDg","text":"_3guDD","input":"_2CPDD","disabled":"_39I6g _36UDg"},"RTSlider":{"container":"_-dLk","knob":"kq8Om","innerknob":"_8VjZ5","snaps":"_2x5j_","snap":"_12aGJ","input":"_2JHGy","progress":"_2R4jW","innerprogress":"_3p0mR","slider":"_3-BtZ","editable":"hkAL6","pinned":"_28Oo0","pressed":"_292qK","ring":"_2Oh5L"},"RTSnackbar":{"snackbar":"zDi3X","accept":"_2Y0Cy","button":"_2pCxU","warning":"_2li3o","cancel":"_3731C","active":"_38CsO","label":"_1JIbY"},"RTSwitch":{"field":"_1T2D0","text":"rxx-p","thumb":"_1pMry","ripple":"_1I9tv","on":"p92Yp","off":"_25ui_","input":"_3BTU_","switch-on":"_2Bwve","switch-off":"_1ZBFp","disabled":"_1CQ_q _1T2D0"},"RTTable":{"table":"_2xofu","head":"_1eF5Z","row":"_1qppP","selected":"_1H1dU","rowCell":"_18bqN","headCell":"gfcPv","numeric":"_3suRQ","checkboxCell":"_2yhwA","sorted":"_2r5OG","sortIcon":"_3NJs5","asc":"wZHUA"},"RTTabs":{"tabs":"_2EaQV","navigation":"_3e55Z","navigationContainer":"_3oZmF","arrow":"wPL4g","arrowContainer":"i_TGW","label":"_1yb8L","rippleWrapper":"_3c0W3","active":"_2LZ7Z","disabled":"_2gi1s","hidden":"_3kq1J","withIcon":"_1OFOx","withText":"_1Yf4A","icon":"_1LUZH","pointer":"_1xgdB","tab":"_26SP9","fixed":"_3bROj","inverse":"_33mT_"},"RTTimePicker":{"input":"_2APuy","disabled":"_2Vc_4","inputElement":"_2Z4kT","header":"_2u1sB","hours":"_3Kl2E","minutes":"_3Bp7w","separator":"_1c2VQ","ampm":"_1vAVQ","am":"_14hQA","pm":"aU9C9","dialog":"_1YlHq","button":"_1Kf0L","hoursDisplay":"_2JeOG","minutesDisplay":"_3UMNx","amFormat":"_26MJk","pmFormat":"_3H_-m","clock":"_2CwF0","placeholder":"zCpyM","clockWrapper":"_3paoD","face":"_3ui0r","number":"qr9pw","active":"_30yS_","hand":"_1rtAF","small":"_3eEHh","knob":"VqPQb","zoomInEnter":"_3DTnI","zoomInLeave":"_1tgJ3","zoomInEnterActive":"_1Fr4_","zoomInLeaveActive":"_1EUpH","zoomOutEnter":"_1Lb15","zoomOutLeave":"_3LDEu","zoomOutEnterActive":"_3y67C","zoomOutLeaveActive":"_18Ean"},"RTTooltip":{"tooltip":"_1v8bI","tooltipActive":"_2xWjx","tooltipTop":"_1PfOK","tooltipLeft":"_3uj3d","tooltipRight":"_3UQWj","tooltipInner":"_9q2WH"}} //eslint-disable-line 2 | -------------------------------------------------------------------------------- /app/assets/images/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hunghkit/reactjs-begin/6c2029171895a7993fa93fa389ff2b99f323ca0d/app/assets/images/banner.png -------------------------------------------------------------------------------- /app/assets/images/loading.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 14 | 15 | 16 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/assets/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/assets/scss/shared/_form.scss: -------------------------------------------------------------------------------- 1 | .form-shared { 2 | width: 100%; 3 | padding: 50px; 4 | max-width: 300px; 5 | margin: 50px auto; 6 | 7 | .btn-group { 8 | margin-top: 30px; 9 | text-align: center; 10 | 11 | button { 12 | margin: 5px; 13 | } 14 | } 15 | 16 | .error { 17 | color: red; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/assets/scss/theme.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | 6 | .page-container { 7 | &.loading { 8 | top: 0; 9 | left: 0; 10 | right: 0; 11 | bottom: 0; 12 | display: flex; 13 | position: fixed; 14 | align-items: center; 15 | justify-content: center; 16 | } 17 | } 18 | } 19 | 20 | @import './shared/form'; 21 | @import '~pages/Home/style'; 22 | @import '~components/Task/style'; 23 | -------------------------------------------------------------------------------- /app/components/Form/Input/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import InputBox from 'react-toolbox/lib/input'; 4 | 5 | const Input = ({ input, meta: { touched, error }, ...props }) => ( 6 | 11 | ); 12 | 13 | Input.propTypes = { 14 | input: PropTypes.shape({ 15 | name: PropTypes.string.isRequired, 16 | }).isRequired, 17 | meta: PropTypes.shape({ 18 | asyncValidating: PropTypes.bool, 19 | error: PropTypes.string, 20 | touched: PropTypes.bool, 21 | }).isRequired, 22 | label: PropTypes.node, 23 | type: PropTypes.string, 24 | }; 25 | 26 | export default Input; 27 | -------------------------------------------------------------------------------- /app/components/Form/Login/index.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { Link } from 'react-router-dom'; 4 | import { Field, reduxForm } from 'redux-form'; 5 | import Input from 'components/Form/Input'; 6 | import { Button } from 'react-toolbox/lib/button'; 7 | import { validate } from './validate'; 8 | 9 | class Form extends PureComponent { 10 | static propTypes = { 11 | reset: PropTypes.func, 12 | pristine: PropTypes.bool, 13 | message: PropTypes.string, 14 | submitting: PropTypes.bool, 15 | handleSubmit: PropTypes.func, 16 | }; 17 | 18 | render() { 19 | const { handleSubmit, pristine, message, reset, submitting } = this.props; 20 | 21 | return ( 22 |
26 |

Login

27 |

Dont have an account? Register

28 | {!!message &&
{message}
} 29 | 35 | 41 |
42 |
57 | 58 | ); 59 | } 60 | } 61 | 62 | export default reduxForm({ 63 | form: 'login', 64 | validate, 65 | })(Form); 66 | -------------------------------------------------------------------------------- /app/components/Form/Login/validate.js: -------------------------------------------------------------------------------- 1 | export const validate = (values) => { 2 | const errors = {}; 3 | if (!values.username) errors.username = 'Username can\'t be blank'; 4 | if (!values.password) errors.password = 'Password can\'t be blank'; 5 | return errors; 6 | }; 7 | -------------------------------------------------------------------------------- /app/components/Form/Register/index.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { Link } from 'react-router-dom'; 4 | import { Field, reduxForm } from 'redux-form'; 5 | import Input from 'components/Form/Input'; 6 | import { Button } from 'react-toolbox/lib/button'; 7 | import { validate } from './validate'; 8 | 9 | class Form extends PureComponent { 10 | static propTypes = { 11 | reset: PropTypes.func, 12 | pristine: PropTypes.bool, 13 | message: PropTypes.string, 14 | submitting: PropTypes.bool, 15 | handleSubmit: PropTypes.func, 16 | }; 17 | 18 | render() { 19 | const { handleSubmit, pristine, message, reset, submitting } = this.props; 20 | 21 | return ( 22 |
26 |

Register

27 |

Already have an account? Login

28 | {!!message &&
{message}
} 29 | 35 | 41 | 47 | 53 |
54 |
69 | 70 | ); 71 | } 72 | } 73 | 74 | export default reduxForm({ 75 | form: 'register', 76 | validate, 77 | })(Form); 78 | -------------------------------------------------------------------------------- /app/components/Form/Register/validate.js: -------------------------------------------------------------------------------- 1 | export const validate = (values) => { 2 | const errors = {}; 3 | if (!values.name) errors.name = 'Name can\'t be blank'; 4 | if (!values.username) errors.username = 'Username can\'t be blank'; 5 | if (!values.password) errors.password = 'Password can\'t be blank'; 6 | if (!values.confirmPassword) errors.confirmPassword = 'Confirm password can\'t be blank'; 7 | if (values.password !== values.confirmPassword) { 8 | errors.password = 'Password don\'t match'; 9 | errors.confirmPassword = 'Password don\'t match'; 10 | } 11 | 12 | return errors; 13 | }; 14 | -------------------------------------------------------------------------------- /app/components/Form/Task/index.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { Field, reduxForm } from 'redux-form'; 4 | import Input from 'components/Form/Input'; 5 | import { Button } from 'react-toolbox/lib/button'; 6 | 7 | class Form extends PureComponent { 8 | static propTypes = { 9 | reset: PropTypes.func, 10 | pristine: PropTypes.bool, 11 | message: PropTypes.string, 12 | submitting: PropTypes.bool, 13 | handleSubmit: PropTypes.func, 14 | mode: PropTypes.oneOf(['create', 'edit']), 15 | }; 16 | 17 | render() { 18 | const { handleSubmit, pristine, message, reset, submitting, mode } = this.props; 19 | 20 | return ( 21 |
25 | {!!message &&
{message}
} 26 | 33 | 39 |
40 |
55 | 56 | ); 57 | } 58 | } 59 | 60 | export default reduxForm({ 61 | form: 'task', 62 | })(Form); 63 | -------------------------------------------------------------------------------- /app/components/Loaders/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const Circle = ({ fill = '#ffffff', opacity = 1, width = '70px', height = '70px', ...props }) => ( //eslint-disable-line 4 | 5 | 6 | 11 | 12 | 13 | 14 | ); 15 | 16 | export const Loading = ({ fill = '#333333', width = '24px', height = '30px', ...props }) => ( //eslint-disable-line 17 | 18 | 19 | 28 | 29 | 30 | 39 | 40 | 41 | 50 | 51 | 52 | ); 53 | 54 | export default { Loading, Circle }; 55 | -------------------------------------------------------------------------------- /app/components/Login/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import Helmet from 'react-helmet'; 4 | import { withRouter } from 'react-router-dom'; 5 | import { connect } from 'react-redux'; 6 | import axios from 'services/axios'; 7 | import Form from 'components/Form/Login'; 8 | import { onSetCurrentUser } from 'actions/currentUser'; 9 | 10 | class Login extends Component { 11 | static propTypes = { 12 | setUser: PropTypes.func, 13 | history: PropTypes.object, 14 | }; 15 | 16 | constructor(props) { 17 | super(props); 18 | this.state = { mgs: '' }; 19 | this.onSubmit = this.onSubmit.bind(this); 20 | } 21 | 22 | componentWillMount() { 23 | this.setState({ mgs: '' }); 24 | } 25 | 26 | onSubmit(user) { 27 | axios.post('/api/v1.0.0/auth', { user }) 28 | .then((res) => res.data) 29 | .then(({ success, message, user: newUser = {} }) => { 30 | if (!success) return this.setState({ mgs: message }); 31 | this.props.setUser(newUser); 32 | return this.props.history.push('/'); 33 | }) 34 | .catch((err) => this.setState({ mgs: err.toString() })); 35 | } 36 | 37 | render() { 38 | const { mgs = '' } = this.state; 39 | 40 | return ( 41 |
42 | 48 |
49 |
50 | ); 51 | } 52 | } 53 | 54 | const mapDispatchToProps = (dispatch) => ({ 55 | setUser: (user = {}) => dispatch(onSetCurrentUser(user)), 56 | }); 57 | 58 | export default connect(null, mapDispatchToProps)(withRouter(Login)); 59 | -------------------------------------------------------------------------------- /app/components/Task/Form.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import axios from 'services/axios'; 4 | import { connect } from 'react-redux'; 5 | import TaskForm from 'components/Form/Task'; 6 | import { change as changeFieldValue } from 'redux-form'; 7 | 8 | export class Form extends Component { 9 | static propTypes = { 10 | onSuccess: PropTypes.func, 11 | changeFieldValue: PropTypes.func, 12 | }; 13 | 14 | static defaultProps = { 15 | onSuccess: () => {}, 16 | changeFieldValue: () => {}, 17 | }; 18 | 19 | constructor(props) { 20 | super(props); 21 | this.state = { message: '' }; 22 | this.onTask = this.onTask.bind(this); 23 | this.onSubmit = this.onSubmit.bind(this); 24 | } 25 | 26 | onTask(task = {}) { 27 | Object.entries(task).forEach((item) => this.props.changeFieldValue(...item)); 28 | } 29 | 30 | onSubmit({ title, id }) { 31 | let url = '/api/v1.0.0/tasks/'; 32 | let method = 'post'; 33 | let isNew = true; 34 | 35 | if (id) { 36 | url += id; 37 | method = 'put'; 38 | isNew = false; 39 | } 40 | 41 | this.setState({ message: '' }); 42 | 43 | axios[method](url, { task: { title } }) 44 | .then((res) => res.data) 45 | .then(({ task, success, message }) => { 46 | if (success) { 47 | this.props.onSuccess(task, isNew); 48 | this.form.reset(); 49 | } else this.setState({ message }); 50 | }) 51 | .catch((err) => this.setState({ message: err.toString() })); 52 | } 53 | 54 | render() { 55 | const { message } = this.state; 56 | return (this.form = ref)} onSubmit={this.onSubmit} message={message} />; 57 | } 58 | } 59 | 60 | const dispatchToProps = (dispatch) => ({ 61 | changeFieldValue: (field, value) => dispatch(changeFieldValue('task', field, value)), 62 | }); 63 | 64 | export default connect(null, dispatchToProps, null, { withRef: true })(Form); 65 | -------------------------------------------------------------------------------- /app/components/Task/_style.scss: -------------------------------------------------------------------------------- 1 | .task-component { 2 | margin: auto; 3 | max-width: 400px; 4 | 5 | ul { 6 | padding: 0; 7 | 8 | li { 9 | padding: 5px; 10 | color: #777777; 11 | border-bottom: 1px solid #eeeeee; 12 | 13 | .content { 14 | flex: 1; 15 | text-align: left; 16 | } 17 | } 18 | } 19 | 20 | .task-form-component { 21 | display: flex; 22 | flex-direction: column; 23 | 24 | button { 25 | margin-left: 5px; 26 | } 27 | 28 | .error { 29 | color: red; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/components/Task/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { connect } from 'react-redux'; 4 | import { onAddTasks, onRemoveTask } from 'actions/task'; 5 | import { IconButton } from 'react-toolbox/lib/button'; 6 | import { List, ListItem, ListSubHeader, ListDivider } from 'react-toolbox/lib/list'; 7 | 8 | import Form from './Form'; 9 | 10 | export class Task extends Component { 11 | static propTypes = { 12 | tasks: PropTypes.object, 13 | onAddTasks: PropTypes.func, 14 | onRemoveTask: PropTypes.func, 15 | } 16 | constructor(props) { 17 | super(props); 18 | this.renderTask = this.renderTask.bind(this); 19 | this.onSuccess = this.onSuccess.bind(this); 20 | this.onDelete = this.onDelete.bind(this); 21 | this.onEdit = this.onEdit.bind(this); 22 | } 23 | 24 | componentWillMount() { 25 | this.props.onAddTasks(); 26 | } 27 | 28 | onSuccess(newTask = {}) { 29 | const { _id: id } = newTask; 30 | const { tasks = {} } = this.props; 31 | const task = { ...(tasks[id] || {}), ...newTask }; 32 | if (tasks[id]) delete tasks[id]; 33 | 34 | this.props.onAddTasks({ [id]: task, ...this.props.tasks }); //eslint-disable-line 35 | } 36 | 37 | onDelete(e, id) { 38 | e.preventDefault(); 39 | if (window.confirm("Are you sure?")) { // eslint-disable-line 40 | this.props.onRemoveTask(id); 41 | } 42 | } 43 | 44 | onEdit(e, task) { 45 | e.preventDefault(); 46 | this.form.getWrappedInstance().onTask(task); 47 | } 48 | 49 | renderTask({ _id: id, title }, index) { 50 | return ( 51 | {title}} 55 | rightActions={[ 56 | this.onEdit(e, { id, title })} 61 | />, 62 | this.onDelete(e, id)} 67 | />, 68 | ]} 69 | /> 70 | ); 71 | } 72 | 73 | render() { 74 | const { tasks = {} } = this.props; 75 | const hasTask = Object.keys(tasks).length > 0; 76 | 77 | return ( 78 |
79 | this.form = ref} onSuccess={this.onSuccess} /> 80 | { hasTask && 81 | 82 | 83 | 84 | {Object.keys(tasks).map((key, index) => this.renderTask(tasks[key], index))} 85 | 86 | } 87 |
88 | ); 89 | } 90 | } 91 | 92 | 93 | const mapStateToProps = ({ tasks }) => ({ tasks }); 94 | 95 | const mapDispatchToProps = (dispatch) => ({ 96 | onAddTasks: (tasks) => dispatch(onAddTasks(tasks)), 97 | onRemoveTask: (id) => dispatch(onRemoveTask(id)), 98 | }); 99 | 100 | export default connect(mapStateToProps, mapDispatchToProps)(Task); 101 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import { CookiesProvider } from 'react-cookie'; 5 | import { ThemeProvider } from 'react-css-themr'; 6 | import { BrowserRouter } from 'react-router-dom'; 7 | 8 | import App from 'pages'; 9 | import store from 'reducers/store'; 10 | import theme from 'assets/css/theme'; 11 | 12 | render( 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | , 22 | document.getElementById('root')); 23 | -------------------------------------------------------------------------------- /app/pages/Home/_style.scss: -------------------------------------------------------------------------------- 1 | .home-pages { 2 | text-align: center; 3 | 4 | .header { 5 | background-color: #222; 6 | padding: 2em 1em; 7 | color: white; 8 | } 9 | 10 | .intro { 11 | font-size: large; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/pages/Home/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import logo from 'assets/images/banner.png'; 4 | import Task from 'components/Task'; 5 | import Helmet from 'react-helmet'; 6 | import { onAddTasks } from 'actions/task'; 7 | import { isAuth } from 'services/isAuth'; 8 | 9 | class Home extends Component { 10 | static preRender(store) { 11 | return store.dispatch(onAddTasks()); 12 | } 13 | 14 | static propTypes = { 15 | setUser: PropTypes.func, 16 | currentUser: PropTypes.object, 17 | }; 18 | 19 | constructor(props) { 20 | super(props); 21 | this.state = { 22 | message: 'Welcome to ReactJS Begin', 23 | }; 24 | } 25 | 26 | render() { 27 | const { message } = this.state; 28 | const { currentUser = {}, setUser = () => {} } = this.props; 29 | 30 | return ( 31 |
32 | 39 |
40 | logo 41 |

{message}

42 |

{currentUser.username}

43 |
44 |

45 | To get started click here 46 |

47 |

48 | The project was created by create-react-app, see more at here 49 |

50 | 51 |
52 | ); 53 | } 54 | } 55 | 56 | export default isAuth(Home); 57 | -------------------------------------------------------------------------------- /app/pages/Login/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Helmet from 'react-helmet'; 3 | import Form from 'components/Login'; 4 | 5 | const Login = () => ( 6 |
7 | 13 | 14 |
15 | ); 16 | 17 | export default Login; 18 | -------------------------------------------------------------------------------- /app/pages/Register/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import Helmet from 'react-helmet'; 4 | import axios from 'services/axios'; 5 | import Form from 'components/Form/Register'; 6 | 7 | class Register extends Component { 8 | static propTypes = { 9 | history: PropTypes.object, 10 | }; 11 | 12 | constructor(props) { 13 | super(props); 14 | this.state = { mgs: '' }; 15 | this.onSubmit = this.onSubmit.bind(this); 16 | } 17 | 18 | componentWillMount() { 19 | this.setState({ mgs: '' }); 20 | } 21 | 22 | onSubmit(user) { 23 | axios.post('/api/v1.0.0/auth/register', { user }) 24 | .then((res) => res.data) 25 | .then(({ success, message }) => { 26 | success ? this.props.history.push('/login') : this.setState({ mgs: message }); 27 | }) 28 | .catch((err) => this.setState({ mgs: err.toString() })); 29 | } 30 | 31 | render() { 32 | const { mgs = '' } = this.state; 33 | 34 | return ( 35 |
36 | 42 | 43 |
44 | ); 45 | } 46 | } 47 | 48 | export default Register; 49 | -------------------------------------------------------------------------------- /app/pages/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Helmet from 'react-helmet'; 3 | import PropTypes from 'prop-types'; 4 | import { connect } from 'react-redux'; 5 | import { Loading } from 'components/Loaders'; 6 | import { withRouter } from 'react-router-dom'; 7 | import axios from 'services/axios'; 8 | import 'assets/scss/theme.scss'; 9 | import { onSetCurrentUser } from 'actions/currentUser'; 10 | import Routes from './routes'; 11 | 12 | class Pages extends Component { 13 | static propTypes = { 14 | setUser: PropTypes.func, 15 | isServer: PropTypes.bool, 16 | }; 17 | 18 | constructor(props) { 19 | super(props); 20 | this.state = { loaded: false }; 21 | } 22 | 23 | componentWillMount() { 24 | axios.get('/api/v1.0.0/auth') 25 | .then((res) => res.data) 26 | .then(({ user }) => { 27 | if (user) this.props.setUser(user); 28 | }); 29 | } 30 | 31 | componentDidMount() { 32 | document.body.onload = () => { 33 | this.setState({ loaded: true }); 34 | }; 35 | } 36 | 37 | render() { 38 | const { loaded } = this.state; 39 | const { isServer } = this.props; 40 | if (!loaded && !isServer) return
; 41 | 42 | return ( 43 |
44 | 53 | 54 |
55 | ); 56 | } 57 | } 58 | 59 | const mapDispatchToProps = (dispatch) => ({ 60 | setUser: (user = {}) => dispatch(onSetCurrentUser(user)), 61 | }); 62 | 63 | export default withRouter(connect(null, mapDispatchToProps)(Pages)); 64 | -------------------------------------------------------------------------------- /app/pages/routes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route, Switch } from 'react-router-dom'; 3 | import Home from 'pages/Home'; 4 | import Login from 'pages/Login'; 5 | import Register from 'pages/Register'; 6 | 7 | const Routes = () => ( 8 | 9 | 10 | 11 | 12 | 13 | ); 14 | 15 | export default Routes; 16 | -------------------------------------------------------------------------------- /app/reducers/currentUser.js: -------------------------------------------------------------------------------- 1 | import Cookies from 'universal-cookie'; 2 | 3 | import { 4 | SET_CURRENT_USER, 5 | } from 'actions/constant'; 6 | 7 | export default (state = {}, { type, user = {} }) => { 8 | switch (type) { 9 | case SET_CURRENT_USER: { 10 | const cookies = new Cookies(); 11 | user.token ? cookies.set('token', user.token) : cookies.remove('token'); 12 | return user; 13 | } 14 | default: 15 | return state; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /app/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import { reducer as formReducer } from 'redux-form'; 3 | import tasks from './tasks'; 4 | import currentUser from './currentUser'; 5 | 6 | export default combineReducers({ 7 | tasks, 8 | currentUser, 9 | form: formReducer, 10 | }); 11 | -------------------------------------------------------------------------------- /app/reducers/store.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from 'redux'; 2 | import thunk from 'redux-thunk'; 3 | import reducers from './'; 4 | 5 | export default createStore( 6 | reducers, 7 | applyMiddleware(thunk) 8 | ); 9 | -------------------------------------------------------------------------------- /app/reducers/tasks.js: -------------------------------------------------------------------------------- 1 | import { 2 | ADD_TASKS_LIST, 3 | } from 'actions/constant'; 4 | 5 | export default (state = {}, { type, tasks }) => { 6 | switch (type) { 7 | case ADD_TASKS_LIST: 8 | return tasks; 9 | default: 10 | return state; 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /app/renderServer/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOMServer from 'react-dom/server'; 3 | import { matchPath } from 'react-router'; 4 | import { StaticRouter } from 'react-router-dom'; 5 | import { CookiesProvider } from 'react-cookie'; 6 | import { Helmet } from 'react-helmet'; 7 | import { Provider } from 'react-redux'; 8 | import App from 'pages'; 9 | import routes from 'pages/routes'; 10 | import store from 'reducers/store'; 11 | import Template from './template'; 12 | 13 | const components = (routesArr) => { 14 | if (!routesArr.props.children) return [routesArr.props]; 15 | if (!routesArr.props.children[0]) return [routesArr.props.children]; 16 | return routesArr.props.children; 17 | }; 18 | 19 | const matchRoutes = (routesArr, location, storeArg) => 20 | Promise.all( 21 | components(routesArr) 22 | .filter(({ props }) => matchPath(location, props)) 23 | .map(pre => pre.props) 24 | .filter(props => props.component.preRender) 25 | .map(props => props.component.preRender(storeArg, location)) 26 | ); 27 | 28 | export default (assets) => (req, res) => 29 | matchRoutes(routes(), req.url, store) 30 | .then(() => { 31 | const markup = ReactDOMServer.renderToString( 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | ); 40 | const helmet = Helmet.renderStatic(); 41 | 42 | res.status(200).send(Template({ 43 | markup, 44 | helmet, 45 | assets, 46 | })); 47 | }) 48 | .catch(err => res.json(err)); 49 | -------------------------------------------------------------------------------- /app/renderServer/template.js: -------------------------------------------------------------------------------- 1 | export default ({ markup, helmet, assets }) => (` 2 | 3 | 4 | 5 | ${helmet.title.toString()} 6 | ${helmet.meta.toString()} 7 | ${helmet.link.toString()} 8 | 9 | 10 | 11 | 12 |
${markup}
13 | 14 | 15 | 16 | `); 17 | -------------------------------------------------------------------------------- /app/services/axios.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const config = { 4 | baseURL: process.env.BASE_URL, 5 | }; 6 | 7 | export default axios.create(config); 8 | -------------------------------------------------------------------------------- /app/services/isAuth.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import Login from 'components/Login'; 4 | import { onSetCurrentUser } from 'actions/currentUser'; 5 | 6 | export const isAuth = (OldComponent) => { 7 | const newComponent = (props) => { 8 | if (props.currentUser.username) return ; 9 | return ; 10 | }; 11 | 12 | newComponent.propTypes = { 13 | currentUser: PropTypes.object, 14 | }; 15 | 16 | newComponent.defaultProps = { 17 | currentUser: {}, 18 | }; 19 | 20 | const mapDispatchToProps = (dispatch) => ({ 21 | setUser: (user = {}) => dispatch(onSetCurrentUser(user)), 22 | }); 23 | 24 | const mapStateToProps = ({ currentUser = {} }) => ({ currentUser }); 25 | return connect(mapStateToProps, mapDispatchToProps)(newComponent); 26 | }; 27 | 28 | export default isAuth; 29 | -------------------------------------------------------------------------------- /config/env.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const paths = require('./paths'); 4 | 5 | // Make sure that including paths.js after env.js will read .env variables. 6 | delete require.cache[require.resolve('./paths')]; 7 | 8 | const NODE_ENV = process.env.NODE_ENV; 9 | if (!NODE_ENV) { 10 | throw new Error( 11 | 'The NODE_ENV environment variable is required but was not specified.' 12 | ); 13 | } 14 | 15 | // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use 16 | const dotenvFiles = [ 17 | `${paths.dotenv}.${NODE_ENV}.local`, 18 | `${paths.dotenv}.${NODE_ENV}`, 19 | // Don't include `.env.local` for `test` environment 20 | // since normally you expect tests to produce the same 21 | // results for everyone 22 | NODE_ENV !== 'test' && `${paths.dotenv}.local`, 23 | paths.dotenv, 24 | ].filter(Boolean); 25 | 26 | // Load environment variables from .env* files. Suppress warnings using silent 27 | // if this file is missing. dotenv will never modify any environment variables 28 | // that have already been set. 29 | // https://github.com/motdotla/dotenv 30 | dotenvFiles.forEach(dotenvFile => { 31 | if (fs.existsSync(dotenvFile)) { 32 | require('dotenv').config({ 33 | path: dotenvFile, 34 | }); 35 | } 36 | }); 37 | 38 | // We support resolving modules according to `NODE_PATH`. 39 | // This lets you use absolute paths in imports inside large monorepos: 40 | // https://github.com/facebookincubator/create-react-app/issues/253. 41 | // It works similar to `NODE_PATH` in Node itself: 42 | // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders 43 | // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. 44 | // Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. 45 | // https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421 46 | // We also resolve them to make sure all tools using them work consistently. 47 | const appDirectory = fs.realpathSync(process.cwd()); 48 | process.env.NODE_PATH = (process.env.NODE_PATH || '') 49 | .split(path.delimiter) 50 | .filter(folder => folder && !path.isAbsolute(folder)) 51 | .map(folder => path.resolve(appDirectory, folder)) 52 | .join(path.delimiter); 53 | 54 | // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be 55 | // injected into the application via DefinePlugin in Webpack configuration. 56 | const REACT_APP = /^REACT_APP_/i; 57 | 58 | function getClientEnvironment(publicUrl) { 59 | const raw = Object.keys(process.env) 60 | .filter(key => REACT_APP.test(key)) 61 | .reduce( 62 | (env, key) => { 63 | env[key] = process.env[key]; 64 | return env; 65 | }, 66 | { 67 | // Useful for determining whether we’re running in production mode. 68 | // Most importantly, it switches React into the correct mode. 69 | NODE_ENV: process.env.NODE_ENV || 'development', 70 | BASE_URL: process.env.BASE_URL || '/', 71 | // Useful for resolving the correct path to static assets in `public`. 72 | // For example, . 73 | // This should only be used as an escape hatch. Normally you would put 74 | // images into the `src` and `import` them in code to get their paths. 75 | PUBLIC_URL: publicUrl, 76 | } 77 | ); 78 | // Stringify all values so we can feed into Webpack DefinePlugin 79 | const stringified = { 80 | 'process.env': Object.keys(raw).reduce((env, key) => { 81 | env[key] = JSON.stringify(raw[key]); 82 | return env; 83 | }, {}), 84 | }; 85 | 86 | return { raw, stringified }; 87 | } 88 | 89 | module.exports = getClientEnvironment; 90 | -------------------------------------------------------------------------------- /config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/tutorial-webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | 5 | // This is a custom Jest transformer turning file imports into filenames. 6 | // http://facebook.github.io/jest/docs/tutorial-webpack.html 7 | 8 | module.exports = { 9 | process(src, filename) { 10 | return `module.exports = ${JSON.stringify(path.basename(filename))};`; 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const url = require('url'); 6 | 7 | // Make sure any symlinks in the project folder are resolved: 8 | // https://github.com/facebookincubator/create-react-app/issues/637 9 | const appDirectory = fs.realpathSync(process.cwd()); 10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath); 11 | 12 | const envPublicUrl = process.env.PUBLIC_URL; 13 | 14 | function ensureSlash(path, needsSlash) { 15 | const hasSlash = path.endsWith('/'); 16 | if (hasSlash && !needsSlash) { 17 | return path.substr(path, path.length - 1); 18 | } else if (!hasSlash && needsSlash) { 19 | return `${path}/`; 20 | } else { 21 | return path; 22 | } 23 | } 24 | 25 | const getPublicUrl = appPackageJson => 26 | envPublicUrl || require(appPackageJson).homepage; 27 | 28 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer 29 | // "public path" at which the app is served. 30 | // Webpack needs to know it to put the right