diff --git a/.history/src/__tests__/components/app.test_20200601125027.js b/.history/src/__tests__/components/app.test_20200601125027.js
new file mode 100644
index 0000000..04c6908
--- /dev/null
+++ b/.history/src/__tests__/components/app.test_20200601125027.js
@@ -0,0 +1,16 @@
+import React from 'react';
+import { mount, shallow } from 'enzyme';
+import { Provider } from 'react-redux';
+import App from '../../app.js';
+import store from '../../redux/store.js';
+
+
+it('renders app component without crashing', () => {
+ shallow();
+});
+
+it('renders entire app without crashing', () => {
+ mount(
+
+ );
+});
diff --git a/.history/src/__tests__/components/app.test_20200610111723.js b/.history/src/__tests__/components/app.test_20200610111723.js
new file mode 100644
index 0000000..04c6908
--- /dev/null
+++ b/.history/src/__tests__/components/app.test_20200610111723.js
@@ -0,0 +1,16 @@
+import React from 'react';
+import { mount, shallow } from 'enzyme';
+import { Provider } from 'react-redux';
+import App from '../../app.js';
+import store from '../../redux/store.js';
+
+
+it('renders app component without crashing', () => {
+ shallow();
+});
+
+it('renders entire app without crashing', () => {
+ mount(
+
+ );
+});
diff --git a/.history/src/__tests__/components/app.test_20200610111724.js b/.history/src/__tests__/components/app.test_20200610111724.js
new file mode 100644
index 0000000..04c6908
--- /dev/null
+++ b/.history/src/__tests__/components/app.test_20200610111724.js
@@ -0,0 +1,16 @@
+import React from 'react';
+import { mount, shallow } from 'enzyme';
+import { Provider } from 'react-redux';
+import App from '../../app.js';
+import store from '../../redux/store.js';
+
+
+it('renders app component without crashing', () => {
+ shallow();
+});
+
+it('renders entire app without crashing', () => {
+ mount(
+
+ );
+});
diff --git a/.history/src/api/api_20200601125027.js b/.history/src/api/api_20200601125027.js
new file mode 100644
index 0000000..f9e17ae
--- /dev/null
+++ b/.history/src/api/api_20200601125027.js
@@ -0,0 +1,19 @@
+// axiosconfig.js
+import axios from 'axios';
+import store from '../redux/store.js';
+
+// configure base url
+const api = axios.create({
+ baseURL: 'https://edukolab-api-team-099-b-li6nmp.herokuapp.com/v1'
+});
+
+// intercept requests and add authorization token
+api.interceptors.request.use((config) => {
+ const { token } = store.getState().auth;
+ if (token) {
+ config.headers.authorization = `Bearer ${token}`;
+ }
+ return config;
+});
+
+export default api;
diff --git a/.history/src/api/api_20200610111716.js b/.history/src/api/api_20200610111716.js
new file mode 100644
index 0000000..f9e17ae
--- /dev/null
+++ b/.history/src/api/api_20200610111716.js
@@ -0,0 +1,19 @@
+// axiosconfig.js
+import axios from 'axios';
+import store from '../redux/store.js';
+
+// configure base url
+const api = axios.create({
+ baseURL: 'https://edukolab-api-team-099-b-li6nmp.herokuapp.com/v1'
+});
+
+// intercept requests and add authorization token
+api.interceptors.request.use((config) => {
+ const { token } = store.getState().auth;
+ if (token) {
+ config.headers.authorization = `Bearer ${token}`;
+ }
+ return config;
+});
+
+export default api;
diff --git a/.history/src/api/api_20200610111717.js b/.history/src/api/api_20200610111717.js
new file mode 100644
index 0000000..f9e17ae
--- /dev/null
+++ b/.history/src/api/api_20200610111717.js
@@ -0,0 +1,19 @@
+// axiosconfig.js
+import axios from 'axios';
+import store from '../redux/store.js';
+
+// configure base url
+const api = axios.create({
+ baseURL: 'https://edukolab-api-team-099-b-li6nmp.herokuapp.com/v1'
+});
+
+// intercept requests and add authorization token
+api.interceptors.request.use((config) => {
+ const { token } = store.getState().auth;
+ if (token) {
+ config.headers.authorization = `Bearer ${token}`;
+ }
+ return config;
+});
+
+export default api;
diff --git a/.history/src/components/auth/authForm_20200601125027.js b/.history/src/components/auth/authForm_20200601125027.js
new file mode 100644
index 0000000..233a8e9
--- /dev/null
+++ b/.history/src/components/auth/authForm_20200601125027.js
@@ -0,0 +1,142 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faAddressCard, faCheckCircle } from '@fortawesome/free-regular-svg-icons';
+
+import { faLock, faTimes } from '@fortawesome/free-solid-svg-icons';
+import { Link } from 'react-router-dom';
+import { Field, reduxForm } from 'redux-form';
+
+import '../../assets/css/auth/authForm.css';
+
+class AuthForm extends Component {
+ static propTypes = {
+ handleSubmit: PropTypes.func
+ };
+
+ renderValidateIcon = (touched, error) => {
+ let className = null;
+ let icon = null;
+ if (touched) {
+ className = error === undefined ? 'text-success' : 'text-danger';
+ icon = error === undefined ? faCheckCircle : faTimes;
+
+ return ;
+ }
+ return false;
+ }
+
+ renderField = ({
+ input, label, type, placeholder, icon, action, meta: { touched, error, warning }
+ }) => (
+
+
+
+
+
+
+
+
+
+
+
+ {this.renderValidateIcon(touched, error)}
+
+
+ { touched ? (
+ touched
+ && (error &&
{error}))
+ : warning &&
{warning}}
+
+ );
+
+ render() {
+ const { handleSubmit } = this.props;
+
+ return (
+
+ );
+ }
+}
+
+const warn = () => {
+ const warnings = {
+ contact: 'Phone number or email address',
+ password: 'Forgot password?'
+ };
+
+ return warnings;
+};
+
+const validate = (authUser) => {
+ const errors = {};
+ if (!authUser.fName) {
+ errors.fName = 'First Name is required';
+ }
+ if (!authUser.lName) {
+ errors.lName = 'Family Name is required';
+ }
+
+ if (!authUser.contact) {
+ errors.contact = 'Required';
+ } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(authUser.contact)) {
+ errors.contact = authUser.contact.length === 11 && authUser.contact.split('')[0] === '0'
+ ? undefined
+ : 'A valid email address or phone number is required';
+ }
+
+ if (!authUser.password) {
+ errors.password = 'Required';
+ } else if (!/\d/.test(authUser.password)) {
+ errors.password = 'Password must contain a number';
+ } else if (!/[A-Z]/.test(authUser.password)) {
+ errors.password = 'Password must contain an upperCase letter';
+ } else if (authUser.password.length < 6) {
+ errors.password = 'Password must be at least 6 characters long';
+ }
+
+ if (!authUser.cpassword) {
+ errors.cpassword = 'Required';
+ } else if (authUser.cpassword !== authUser.password) {
+ errors.cpassword = 'Passwords must match';
+ }
+
+ if (!authUser.role) {
+ errors.age = 'Required';
+ }
+
+ return errors;
+};
+
+export default reduxForm({ form: 'authForm', validate, warn })(AuthForm);
diff --git a/.history/src/components/auth/authForm_20200610111645.js b/.history/src/components/auth/authForm_20200610111645.js
new file mode 100644
index 0000000..233a8e9
--- /dev/null
+++ b/.history/src/components/auth/authForm_20200610111645.js
@@ -0,0 +1,142 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faAddressCard, faCheckCircle } from '@fortawesome/free-regular-svg-icons';
+
+import { faLock, faTimes } from '@fortawesome/free-solid-svg-icons';
+import { Link } from 'react-router-dom';
+import { Field, reduxForm } from 'redux-form';
+
+import '../../assets/css/auth/authForm.css';
+
+class AuthForm extends Component {
+ static propTypes = {
+ handleSubmit: PropTypes.func
+ };
+
+ renderValidateIcon = (touched, error) => {
+ let className = null;
+ let icon = null;
+ if (touched) {
+ className = error === undefined ? 'text-success' : 'text-danger';
+ icon = error === undefined ? faCheckCircle : faTimes;
+
+ return ;
+ }
+ return false;
+ }
+
+ renderField = ({
+ input, label, type, placeholder, icon, action, meta: { touched, error, warning }
+ }) => (
+
+
+
+
+
+
+
+
+
+
+
+ {this.renderValidateIcon(touched, error)}
+
+
+ { touched ? (
+ touched
+ && (error &&
{error}))
+ : warning &&
{warning}}
+
+ );
+
+ render() {
+ const { handleSubmit } = this.props;
+
+ return (
+
+ );
+ }
+}
+
+const warn = () => {
+ const warnings = {
+ contact: 'Phone number or email address',
+ password: 'Forgot password?'
+ };
+
+ return warnings;
+};
+
+const validate = (authUser) => {
+ const errors = {};
+ if (!authUser.fName) {
+ errors.fName = 'First Name is required';
+ }
+ if (!authUser.lName) {
+ errors.lName = 'Family Name is required';
+ }
+
+ if (!authUser.contact) {
+ errors.contact = 'Required';
+ } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(authUser.contact)) {
+ errors.contact = authUser.contact.length === 11 && authUser.contact.split('')[0] === '0'
+ ? undefined
+ : 'A valid email address or phone number is required';
+ }
+
+ if (!authUser.password) {
+ errors.password = 'Required';
+ } else if (!/\d/.test(authUser.password)) {
+ errors.password = 'Password must contain a number';
+ } else if (!/[A-Z]/.test(authUser.password)) {
+ errors.password = 'Password must contain an upperCase letter';
+ } else if (authUser.password.length < 6) {
+ errors.password = 'Password must be at least 6 characters long';
+ }
+
+ if (!authUser.cpassword) {
+ errors.cpassword = 'Required';
+ } else if (authUser.cpassword !== authUser.password) {
+ errors.cpassword = 'Passwords must match';
+ }
+
+ if (!authUser.role) {
+ errors.age = 'Required';
+ }
+
+ return errors;
+};
+
+export default reduxForm({ form: 'authForm', validate, warn })(AuthForm);
diff --git a/.history/src/components/auth/authHeader_20200601125027.js b/.history/src/components/auth/authHeader_20200601125027.js
new file mode 100644
index 0000000..4779a33
--- /dev/null
+++ b/.history/src/components/auth/authHeader_20200601125027.js
@@ -0,0 +1,38 @@
+import React, { Component } from 'react';
+import { Link } from 'react-router-dom';
+import blueLogo from '../../assets/img/logo_blue.png';
+import whiteLogo from '../../assets/img/logo_white.png';
+import '../../assets/css/auth/authHeader.css';
+
+export default class AuthHeader extends Component {
+ render = () => (
+
+ )
+}
diff --git a/.history/src/components/auth/authHeader_20200610111638.js b/.history/src/components/auth/authHeader_20200610111638.js
new file mode 100644
index 0000000..4779a33
--- /dev/null
+++ b/.history/src/components/auth/authHeader_20200610111638.js
@@ -0,0 +1,38 @@
+import React, { Component } from 'react';
+import { Link } from 'react-router-dom';
+import blueLogo from '../../assets/img/logo_blue.png';
+import whiteLogo from '../../assets/img/logo_white.png';
+import '../../assets/css/auth/authHeader.css';
+
+export default class AuthHeader extends Component {
+ render = () => (
+
+ )
+}
diff --git a/.history/src/components/auth/authRedirect_20200601125027.js b/.history/src/components/auth/authRedirect_20200601125027.js
new file mode 100644
index 0000000..818b82d
--- /dev/null
+++ b/.history/src/components/auth/authRedirect_20200601125027.js
@@ -0,0 +1,21 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { Redirect } from 'react-router-dom';
+
+class AuthRedirect extends Component {
+ static propTypes = { auth: PropTypes.object, type: PropTypes.string };
+
+ render = () => {
+ const { auth, type } = this.props;
+
+ if (type === 'logout') {
+ return auth.isSignedIn ? '' : ;
+ }
+ return auth.isSignedIn ? : '';
+ };
+}
+
+const mapStateToProps = ({ auth }) => ({ auth });
+
+export default connect(mapStateToProps)(AuthRedirect);
diff --git a/.history/src/components/auth/authRedirect_20200610111633.js b/.history/src/components/auth/authRedirect_20200610111633.js
new file mode 100644
index 0000000..818b82d
--- /dev/null
+++ b/.history/src/components/auth/authRedirect_20200610111633.js
@@ -0,0 +1,21 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { Redirect } from 'react-router-dom';
+
+class AuthRedirect extends Component {
+ static propTypes = { auth: PropTypes.object, type: PropTypes.string };
+
+ render = () => {
+ const { auth, type } = this.props;
+
+ if (type === 'logout') {
+ return auth.isSignedIn ? '' : ;
+ }
+ return auth.isSignedIn ? : '';
+ };
+}
+
+const mapStateToProps = ({ auth }) => ({ auth });
+
+export default connect(mapStateToProps)(AuthRedirect);
diff --git a/.history/src/components/auth/authRedirect_20200610111634.js b/.history/src/components/auth/authRedirect_20200610111634.js
new file mode 100644
index 0000000..818b82d
--- /dev/null
+++ b/.history/src/components/auth/authRedirect_20200610111634.js
@@ -0,0 +1,21 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { Redirect } from 'react-router-dom';
+
+class AuthRedirect extends Component {
+ static propTypes = { auth: PropTypes.object, type: PropTypes.string };
+
+ render = () => {
+ const { auth, type } = this.props;
+
+ if (type === 'logout') {
+ return auth.isSignedIn ? '' : ;
+ }
+ return auth.isSignedIn ? : '';
+ };
+}
+
+const mapStateToProps = ({ auth }) => ({ auth });
+
+export default connect(mapStateToProps)(AuthRedirect);
diff --git a/.history/src/components/auth/login/login_20200601125027.js b/.history/src/components/auth/login/login_20200601125027.js
new file mode 100644
index 0000000..79d67a7
--- /dev/null
+++ b/.history/src/components/auth/login/login_20200601125027.js
@@ -0,0 +1,47 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faFacebookF } from '@fortawesome/free-brands-svg-icons';
+import '../../../assets/css/auth/auth.css';
+import { connect } from 'react-redux';
+import loginSVG from '../../../assets/svg/undraw_secure_login_pdn4.svg';
+
+import AuthHeader from '../authHeader.js';
+import AuthForm from '../authForm.js';
+import AuthRedirect from '../authRedirect.js';
+import loginAction from '../../../redux/actions/auth/loginAction.js';
+
+class Login extends Component {
+ static propTypes = {
+ loginAction: PropTypes.func
+ }
+
+ submit = (authUser) => this.props.loginAction(authUser);
+
+ render = () => (
+ <>
+
+
+
+
+
+

+
+
+
+
+
+ >
+ );
+}
+
+
+export default connect(null, { loginAction })(Login);
diff --git a/.history/src/components/auth/login/login_20200610111655.js b/.history/src/components/auth/login/login_20200610111655.js
new file mode 100644
index 0000000..79d67a7
--- /dev/null
+++ b/.history/src/components/auth/login/login_20200610111655.js
@@ -0,0 +1,47 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faFacebookF } from '@fortawesome/free-brands-svg-icons';
+import '../../../assets/css/auth/auth.css';
+import { connect } from 'react-redux';
+import loginSVG from '../../../assets/svg/undraw_secure_login_pdn4.svg';
+
+import AuthHeader from '../authHeader.js';
+import AuthForm from '../authForm.js';
+import AuthRedirect from '../authRedirect.js';
+import loginAction from '../../../redux/actions/auth/loginAction.js';
+
+class Login extends Component {
+ static propTypes = {
+ loginAction: PropTypes.func
+ }
+
+ submit = (authUser) => this.props.loginAction(authUser);
+
+ render = () => (
+ <>
+
+
+
+
+
+

+
+
+
+
+
+ >
+ );
+}
+
+
+export default connect(null, { loginAction })(Login);
diff --git a/.history/src/components/auth/login/login_20200610111656.js b/.history/src/components/auth/login/login_20200610111656.js
new file mode 100644
index 0000000..79d67a7
--- /dev/null
+++ b/.history/src/components/auth/login/login_20200610111656.js
@@ -0,0 +1,47 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faFacebookF } from '@fortawesome/free-brands-svg-icons';
+import '../../../assets/css/auth/auth.css';
+import { connect } from 'react-redux';
+import loginSVG from '../../../assets/svg/undraw_secure_login_pdn4.svg';
+
+import AuthHeader from '../authHeader.js';
+import AuthForm from '../authForm.js';
+import AuthRedirect from '../authRedirect.js';
+import loginAction from '../../../redux/actions/auth/loginAction.js';
+
+class Login extends Component {
+ static propTypes = {
+ loginAction: PropTypes.func
+ }
+
+ submit = (authUser) => this.props.loginAction(authUser);
+
+ render = () => (
+ <>
+
+
+
+
+
+

+
+
+
+
+
+ >
+ );
+}
+
+
+export default connect(null, { loginAction })(Login);
diff --git a/.history/src/components/auth/logout/logout_20200601125027.js b/.history/src/components/auth/logout/logout_20200601125027.js
new file mode 100644
index 0000000..dba034c
--- /dev/null
+++ b/.history/src/components/auth/logout/logout_20200601125027.js
@@ -0,0 +1,17 @@
+import React, { Component } from 'react';
+import { PropTypes } from 'prop-types';
+import { connect } from 'react-redux';
+import logoutAction from '../../../redux/actions/auth/logoutAction.js';
+import AuthRedirect from '../authRedirect.js';
+
+class Logout extends Component {
+ static propTypes = {
+ logoutAction: PropTypes.func
+ };
+
+ render = () => ;
+
+ componentDidMount = () => this.props.logoutAction();
+}
+
+export default connect(null, { logoutAction })(Logout);
diff --git a/.history/src/components/auth/logout/logout_20200610111649.js b/.history/src/components/auth/logout/logout_20200610111649.js
new file mode 100644
index 0000000..dba034c
--- /dev/null
+++ b/.history/src/components/auth/logout/logout_20200610111649.js
@@ -0,0 +1,17 @@
+import React, { Component } from 'react';
+import { PropTypes } from 'prop-types';
+import { connect } from 'react-redux';
+import logoutAction from '../../../redux/actions/auth/logoutAction.js';
+import AuthRedirect from '../authRedirect.js';
+
+class Logout extends Component {
+ static propTypes = {
+ logoutAction: PropTypes.func
+ };
+
+ render = () => ;
+
+ componentDidMount = () => this.props.logoutAction();
+}
+
+export default connect(null, { logoutAction })(Logout);
diff --git a/.history/src/components/auth/logout/logout_20200610111650.js b/.history/src/components/auth/logout/logout_20200610111650.js
new file mode 100644
index 0000000..dba034c
--- /dev/null
+++ b/.history/src/components/auth/logout/logout_20200610111650.js
@@ -0,0 +1,17 @@
+import React, { Component } from 'react';
+import { PropTypes } from 'prop-types';
+import { connect } from 'react-redux';
+import logoutAction from '../../../redux/actions/auth/logoutAction.js';
+import AuthRedirect from '../authRedirect.js';
+
+class Logout extends Component {
+ static propTypes = {
+ logoutAction: PropTypes.func
+ };
+
+ render = () => ;
+
+ componentDidMount = () => this.props.logoutAction();
+}
+
+export default connect(null, { logoutAction })(Logout);
diff --git a/.history/src/components/home/home_20200601125027.js b/.history/src/components/home/home_20200601125027.js
new file mode 100644
index 0000000..1809fd6
--- /dev/null
+++ b/.history/src/components/home/home_20200601125027.js
@@ -0,0 +1,24 @@
+import React, { Component } from 'react';
+import { Link } from 'react-router-dom';
+import { connect } from 'react-redux';
+
+import PropTypes from 'prop-types';
+
+class Home extends Component {
+ static propTypes = {
+ auth: PropTypes.object
+ };
+
+ renderAuthButton = ({ isSignedIn }) => (isSignedIn ? Logout : Login);
+
+ render = () => (
+ <>
+ Welcome Home
+ {this.renderAuthButton(this.props.auth)}
+ >
+ );
+}
+
+const mapStateToProps = ({ auth }) => ({ auth });
+
+export default connect(mapStateToProps)(Home);
diff --git a/.history/src/components/home/home_20200610111626.js b/.history/src/components/home/home_20200610111626.js
new file mode 100644
index 0000000..1809fd6
--- /dev/null
+++ b/.history/src/components/home/home_20200610111626.js
@@ -0,0 +1,24 @@
+import React, { Component } from 'react';
+import { Link } from 'react-router-dom';
+import { connect } from 'react-redux';
+
+import PropTypes from 'prop-types';
+
+class Home extends Component {
+ static propTypes = {
+ auth: PropTypes.object
+ };
+
+ renderAuthButton = ({ isSignedIn }) => (isSignedIn ? Logout : Login);
+
+ render = () => (
+ <>
+ Welcome Home
+ {this.renderAuthButton(this.props.auth)}
+ >
+ );
+}
+
+const mapStateToProps = ({ auth }) => ({ auth });
+
+export default connect(mapStateToProps)(Home);
diff --git a/.history/src/components/home/home_20200610111627.js b/.history/src/components/home/home_20200610111627.js
new file mode 100644
index 0000000..1809fd6
--- /dev/null
+++ b/.history/src/components/home/home_20200610111627.js
@@ -0,0 +1,24 @@
+import React, { Component } from 'react';
+import { Link } from 'react-router-dom';
+import { connect } from 'react-redux';
+
+import PropTypes from 'prop-types';
+
+class Home extends Component {
+ static propTypes = {
+ auth: PropTypes.object
+ };
+
+ renderAuthButton = ({ isSignedIn }) => (isSignedIn ? Logout : Login);
+
+ render = () => (
+ <>
+ Welcome Home
+ {this.renderAuthButton(this.props.auth)}
+ >
+ );
+}
+
+const mapStateToProps = ({ auth }) => ({ auth });
+
+export default connect(mapStateToProps)(Home);
diff --git a/.history/src/index_20200601125027.js b/.history/src/index_20200601125027.js
new file mode 100644
index 0000000..3286872
--- /dev/null
+++ b/.history/src/index_20200601125027.js
@@ -0,0 +1,26 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { Provider } from 'react-redux';
+
+// jQuery & BootStrap
+import 'jquery/dist/jquery.min';
+import 'bootstrap/dist/css/bootstrap.min.css';
+import 'bootstrap/dist/js/bootstrap.min';
+import 'popper.js/dist/popper.min';
+
+import * as serviceWorker from './serviceWorker.js';
+// Import redux store
+import store from './redux/store.js';
+
+import App from './app.js';
+
+ReactDOM.render(
+
+
+ ,
+ document.getElementById('root')
+);
+
+if (!window.location.host.includes('localhost')) {
+ serviceWorker.register();
+}
diff --git a/.history/src/index_20200610111828.js b/.history/src/index_20200610111828.js
new file mode 100644
index 0000000..3286872
--- /dev/null
+++ b/.history/src/index_20200610111828.js
@@ -0,0 +1,26 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { Provider } from 'react-redux';
+
+// jQuery & BootStrap
+import 'jquery/dist/jquery.min';
+import 'bootstrap/dist/css/bootstrap.min.css';
+import 'bootstrap/dist/js/bootstrap.min';
+import 'popper.js/dist/popper.min';
+
+import * as serviceWorker from './serviceWorker.js';
+// Import redux store
+import store from './redux/store.js';
+
+import App from './app.js';
+
+ReactDOM.render(
+
+
+ ,
+ document.getElementById('root')
+);
+
+if (!window.location.host.includes('localhost')) {
+ serviceWorker.register();
+}
diff --git a/.history/src/redux/actions/auth/loginAction_20200601125027.js b/.history/src/redux/actions/auth/loginAction_20200601125027.js
new file mode 100644
index 0000000..c030a91
--- /dev/null
+++ b/.history/src/redux/actions/auth/loginAction_20200601125027.js
@@ -0,0 +1,6 @@
+import api from '../../../api/api.js';
+
+export default (payload) => ({
+ type: 'LOGIN',
+ payload: api.post('/auth/login', payload)
+});
diff --git a/.history/src/redux/actions/auth/loginAction_20200610111609.js b/.history/src/redux/actions/auth/loginAction_20200610111609.js
new file mode 100644
index 0000000..c030a91
--- /dev/null
+++ b/.history/src/redux/actions/auth/loginAction_20200610111609.js
@@ -0,0 +1,6 @@
+import api from '../../../api/api.js';
+
+export default (payload) => ({
+ type: 'LOGIN',
+ payload: api.post('/auth/login', payload)
+});
diff --git a/.history/src/redux/actions/auth/loginAction_20200610111610.js b/.history/src/redux/actions/auth/loginAction_20200610111610.js
new file mode 100644
index 0000000..c030a91
--- /dev/null
+++ b/.history/src/redux/actions/auth/loginAction_20200610111610.js
@@ -0,0 +1,6 @@
+import api from '../../../api/api.js';
+
+export default (payload) => ({
+ type: 'LOGIN',
+ payload: api.post('/auth/login', payload)
+});
diff --git a/.history/src/redux/actions/auth/logoutAction_20200601125027.js b/.history/src/redux/actions/auth/logoutAction_20200601125027.js
new file mode 100644
index 0000000..ed33365
--- /dev/null
+++ b/.history/src/redux/actions/auth/logoutAction_20200601125027.js
@@ -0,0 +1,3 @@
+import auth from '../types/authTypes.js';
+
+export default () => ({ type: auth.LOGOUT });
diff --git a/.history/src/redux/actions/auth/logoutAction_20200610111605.js b/.history/src/redux/actions/auth/logoutAction_20200610111605.js
new file mode 100644
index 0000000..ed33365
--- /dev/null
+++ b/.history/src/redux/actions/auth/logoutAction_20200610111605.js
@@ -0,0 +1,3 @@
+import auth from '../types/authTypes.js';
+
+export default () => ({ type: auth.LOGOUT });
diff --git a/.history/src/redux/actions/auth/logoutAction_20200610111606.js b/.history/src/redux/actions/auth/logoutAction_20200610111606.js
new file mode 100644
index 0000000..ed33365
--- /dev/null
+++ b/.history/src/redux/actions/auth/logoutAction_20200610111606.js
@@ -0,0 +1,3 @@
+import auth from '../types/authTypes.js';
+
+export default () => ({ type: auth.LOGOUT });
diff --git a/.history/src/redux/actions/types/authTypes_20200601125027.js b/.history/src/redux/actions/types/authTypes_20200601125027.js
new file mode 100644
index 0000000..530ff1c
--- /dev/null
+++ b/.history/src/redux/actions/types/authTypes_20200601125027.js
@@ -0,0 +1,8 @@
+export default {
+ LOGIN: {
+ LOGIN_PENDING: 'LOGIN_PENDING',
+ LOGIN_FULFILLED: 'LOGIN_FULFILLED',
+ LOGIN_REJECTED: 'LOGIN_REJECTED'
+ },
+ LOGOUT: 'LOGOUT'
+};
diff --git a/.history/src/redux/actions/types/authTypes_20200610111558.js b/.history/src/redux/actions/types/authTypes_20200610111558.js
new file mode 100644
index 0000000..530ff1c
--- /dev/null
+++ b/.history/src/redux/actions/types/authTypes_20200610111558.js
@@ -0,0 +1,8 @@
+export default {
+ LOGIN: {
+ LOGIN_PENDING: 'LOGIN_PENDING',
+ LOGIN_FULFILLED: 'LOGIN_FULFILLED',
+ LOGIN_REJECTED: 'LOGIN_REJECTED'
+ },
+ LOGOUT: 'LOGOUT'
+};
diff --git a/.history/src/redux/reducers/authReducer_20200601125027.js b/.history/src/redux/reducers/authReducer_20200601125027.js
new file mode 100644
index 0000000..6c170fd
--- /dev/null
+++ b/.history/src/redux/reducers/authReducer_20200601125027.js
@@ -0,0 +1,6 @@
+const INIT = { isSignedIn: false, token: undefined, user: undefined };
+
+export default (state = INIT, action) => ({
+ LOGIN_FULFILLED: { ...state, isSignedIn: true, user: action.payload && action.payload.data },
+ LOGOUT: { ...state, isSignedIn: false }
+}[action.type] || state);
diff --git a/.history/src/redux/reducers/authReducer_20200610111550.js b/.history/src/redux/reducers/authReducer_20200610111550.js
new file mode 100644
index 0000000..6c170fd
--- /dev/null
+++ b/.history/src/redux/reducers/authReducer_20200610111550.js
@@ -0,0 +1,6 @@
+const INIT = { isSignedIn: false, token: undefined, user: undefined };
+
+export default (state = INIT, action) => ({
+ LOGIN_FULFILLED: { ...state, isSignedIn: true, user: action.payload && action.payload.data },
+ LOGOUT: { ...state, isSignedIn: false }
+}[action.type] || state);
diff --git a/.history/src/redux/reducers/rootReducer_20200601125027.js b/.history/src/redux/reducers/rootReducer_20200601125027.js
new file mode 100644
index 0000000..a99c836
--- /dev/null
+++ b/.history/src/redux/reducers/rootReducer_20200601125027.js
@@ -0,0 +1,8 @@
+import { combineReducers } from 'redux';
+import { reducer as formReducer } from 'redux-form';
+import authReducer from './authReducer.js';
+
+export default combineReducers({
+ auth: authReducer,
+ form: formReducer
+});
diff --git a/.history/src/redux/reducers/rootReducer_20200610111801.js b/.history/src/redux/reducers/rootReducer_20200610111801.js
new file mode 100644
index 0000000..a99c836
--- /dev/null
+++ b/.history/src/redux/reducers/rootReducer_20200610111801.js
@@ -0,0 +1,8 @@
+import { combineReducers } from 'redux';
+import { reducer as formReducer } from 'redux-form';
+import authReducer from './authReducer.js';
+
+export default combineReducers({
+ auth: authReducer,
+ form: formReducer
+});
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..cfb3f05
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,21 @@
+{
+ "workbench.colorCustomizations": {
+ "activityBar.activeBackground": "#232866",
+ "activityBar.activeBorder": "#a63941",
+ "activityBar.background": "#232866",
+ "activityBar.foreground": "#e7e7e7",
+ "activityBar.inactiveForeground": "#e7e7e799",
+ "activityBarBadge.background": "#a63941",
+ "activityBarBadge.foreground": "#e7e7e7",
+ "statusBar.background": "#161940",
+ "statusBar.border": "#161940",
+ "statusBar.foreground": "#e7e7e7",
+ "statusBarItem.hoverBackground": "#232866",
+ "titleBar.activeBackground": "#161940",
+ "titleBar.activeForeground": "#e7e7e7",
+ "titleBar.border": "#161940",
+ "titleBar.inactiveBackground": "#16194099",
+ "titleBar.inactiveForeground": "#e7e7e799"
+ },
+ "peacock.color": "161940"
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 2b3a7e9..f698dbb 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,16 @@
-trainings, certifications and employment opportunities for teachers
+employment opportunities for teachers
[](https://app.codacy.com/gh/BuildForSDG/EduKolab-Frontend?utm_source=github.com&utm_medium=referral&utm_content=BuildForSDG/EduKolab-Frontend&utm_campaign=Badge_Grade_Settings)
-[](https://app.codacy.com/gh/BuildForSDG/team-099-frontend?utm_source=github.com&utm_medium=referral&utm_content=BuildForSDG/team-099-frontend&utm_campaign=Badge_Grade_Settings)
## About
-The name of our soolution is **EduKolab**.
+The name of our solution is **EduKolab**.
It is a web app that:
- connects teachers in primary && secondary schools with international cooperations for training and certification as well as
- offers trained & certified teachers to schools && guardians for employment
## Why
The problem we set out to solve is that of
-_**insuuficient supply of qualified teachers in your community, Nigeria, as well as other developing countries**_.
+_**insufficient supply of qualified teachers in your community, Nigeria, as well as other developing countries**_.
This project is geared at addressing the [4th Sustainable Developemnt Goal of Education](https://sustainabledevelopment.un.org/sdg4)
@@ -22,7 +21,7 @@ It is very important and relevant especially in this time for a good number of r
## Usage
URL to deployed staging-app is below
-[EduKolab Staging App](https://edukolab-staging-app.herokuapp.com/)
+[EduKolab Staging App](https://edukolab-client-staging-app.herokuapp.com/)
## Setup
1. Clone repo `git clone https://github.com/BuildForSDG/EduKolab-Frontend.git edukolab`
diff --git a/jest.config.js b/jest.config.js
index de0c5dc..82a3654 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -3,5 +3,5 @@ module.exports = {
rootDir: '__tests__',
testRegex: ['.spec.js$', '.test.js$'],
coverageDirectory: './coverage',
- testEnvironment: 'node',
+ testEnvironment: 'node'
};
diff --git a/package-lock.json b/package-lock.json
index 3c77daf..b04447e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1085,6 +1085,51 @@
"resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz",
"integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg=="
},
+ "@fortawesome/fontawesome-common-types": {
+ "version": "0.2.28",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.28.tgz",
+ "integrity": "sha512-gtis2/5yLdfI6n0ia0jH7NJs5i/Z/8M/ZbQL6jXQhCthEOe5Cr5NcQPhgTvFxNOtURE03/ZqUcEskdn2M+QaBg=="
+ },
+ "@fortawesome/fontawesome-svg-core": {
+ "version": "1.2.28",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.28.tgz",
+ "integrity": "sha512-4LeaNHWvrneoU0i8b5RTOJHKx7E+y7jYejplR7uSVB34+mp3Veg7cbKk7NBCLiI4TyoWS1wh9ZdoyLJR8wSAdg==",
+ "requires": {
+ "@fortawesome/fontawesome-common-types": "^0.2.28"
+ }
+ },
+ "@fortawesome/free-brands-svg-icons": {
+ "version": "5.13.0",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.13.0.tgz",
+ "integrity": "sha512-/6xXiJFCMEQxqxXbL0FPJpwq5Cv6MRrjsbJEmH/t5vOvB4dILDpnY0f7zZSlA8+TG7jwlt12miF/yZpZkykucA==",
+ "requires": {
+ "@fortawesome/fontawesome-common-types": "^0.2.28"
+ }
+ },
+ "@fortawesome/free-regular-svg-icons": {
+ "version": "5.13.0",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.13.0.tgz",
+ "integrity": "sha512-70FAyiS5j+ANYD4dh9NGowTorNDnyvQHHpCM7FpnF7GxtDjBUCKdrFqCPzesEIpNDFNd+La3vex+jDk4nnUfpA==",
+ "requires": {
+ "@fortawesome/fontawesome-common-types": "^0.2.28"
+ }
+ },
+ "@fortawesome/free-solid-svg-icons": {
+ "version": "5.13.0",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.13.0.tgz",
+ "integrity": "sha512-IHUgDJdomv6YtG4p3zl1B5wWf9ffinHIvebqQOmV3U+3SLw4fC+LUCCgwfETkbTtjy5/Qws2VoVf6z/ETQpFpg==",
+ "requires": {
+ "@fortawesome/fontawesome-common-types": "^0.2.28"
+ }
+ },
+ "@fortawesome/react-fontawesome": {
+ "version": "0.1.9",
+ "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.9.tgz",
+ "integrity": "sha512-49V3WNysLZU5fZ3sqSuys4nGRytsrxJktbv3vuaXkEoxv22C6T7TEG0TW6+nqVjMnkfCQd5xOnmJoZHMF78tOw==",
+ "requires": {
+ "prop-types": "^15.7.2"
+ }
+ },
"@hapi/address": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
@@ -2482,6 +2527,32 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
"integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug=="
},
+ "axios": {
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
+ "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
+ "requires": {
+ "follow-redirects": "1.5.10"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "follow-redirects": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
+ "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
+ "requires": {
+ "debug": "=3.1.0"
+ }
+ }
+ }
+ },
"axobject-query": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.1.2.tgz",
@@ -3035,6 +3106,11 @@
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
},
+ "bootstrap": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.5.0.tgz",
+ "integrity": "sha512-Z93QoXvodoVslA+PWNdk23Hze4RBYIkpb5h8I2HY2Tu2h7A0LpAgLcyrhrSUyo2/Oxm2l1fRZPs1e5hnxnliXA=="
+ },
"boxen": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
@@ -3550,6 +3626,11 @@
}
}
},
+ "classnames": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
+ "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
+ },
"clean-css": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
@@ -3689,6 +3770,11 @@
}
}
},
+ "clone-function": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/clone-function/-/clone-function-1.0.6.tgz",
+ "integrity": "sha1-QoRxk3dQvKnEjsv7wW9uIy90oD0="
+ },
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -4424,6 +4510,11 @@
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
},
+ "deep-diff": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz",
+ "integrity": "sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ="
+ },
"deep-equal": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
@@ -4687,6 +4778,15 @@
"utila": "~0.4"
}
},
+ "dom-helpers": {
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.1.4.tgz",
+ "integrity": "sha512-TjMyeVUvNEnOnhzs6uAn9Ya47GmMo3qq7m+Lr/3ON0Rs5kHvb8I+SQYjLUSYn7qhEm0QjW0yrBkvz9yOrwwz1A==",
+ "requires": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^2.6.7"
+ }
+ },
"dom-serializer": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
@@ -5058,6 +5158,11 @@
"next-tick": "~1.0.0"
}
},
+ "es6-error": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
+ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="
+ },
"es6-iterator": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
@@ -6565,6 +6670,14 @@
"minimalistic-crypto-utils": "^1.0.1"
}
},
+ "hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "requires": {
+ "react-is": "^16.7.0"
+ }
+ },
"hosted-git-info": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
@@ -7234,6 +7347,11 @@
"isobject": "^3.0.1"
}
},
+ "is-promise": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
+ "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
+ },
"is-regex": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
@@ -7931,6 +8049,11 @@
}
}
},
+ "jquery": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
+ "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg=="
+ },
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -8239,6 +8362,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
},
+ "lodash-es": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz",
+ "integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ=="
+ },
"lodash._baseisequal": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/lodash._baseisequal/-/lodash._baseisequal-3.0.7.tgz",
@@ -8599,6 +8727,15 @@
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.0.tgz",
"integrity": "sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY="
},
+ "mini-create-react-context": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz",
+ "integrity": "sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA==",
+ "requires": {
+ "@babel/runtime": "^7.5.5",
+ "tiny-warning": "^1.0.3"
+ }
+ },
"mini-css-extract-plugin": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz",
@@ -9066,6 +9203,11 @@
}
}
},
+ "object-foreach": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/object-foreach/-/object-foreach-0.1.2.tgz",
+ "integrity": "sha1-10IcW0DjtqPvV6xiQ2jSHY+NLew="
+ },
"object-hash": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.3.tgz",
@@ -9090,6 +9232,15 @@
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
},
+ "object-merge": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/object-merge/-/object-merge-2.5.1.tgz",
+ "integrity": "sha1-B36JFc446nKUeIRIxd0znjTfQic=",
+ "requires": {
+ "clone-function": ">=1.0.1",
+ "object-foreach": ">=0.1.2"
+ }
+ },
"object-path": {
"version": "0.11.4",
"resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz",
@@ -9621,6 +9772,11 @@
"ts-pnp": "^1.1.6"
}
},
+ "popper.js": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
+ "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ=="
+ },
"portfinder": {
"version": "1.0.26",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.26.tgz",
@@ -11157,6 +11313,77 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
+ "react-redux": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz",
+ "integrity": "sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA==",
+ "requires": {
+ "@babel/runtime": "^7.5.5",
+ "hoist-non-react-statics": "^3.3.0",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.7.2",
+ "react-is": "^16.9.0"
+ }
+ },
+ "react-router-dom": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz",
+ "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==",
+ "requires": {
+ "@babel/runtime": "^7.1.2",
+ "history": "^4.9.0",
+ "loose-envify": "^1.3.1",
+ "prop-types": "^15.6.2",
+ "react-router": "5.2.0",
+ "tiny-invariant": "^1.0.2",
+ "tiny-warning": "^1.0.0"
+ },
+ "dependencies": {
+ "history": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
+ "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==",
+ "requires": {
+ "@babel/runtime": "^7.1.2",
+ "loose-envify": "^1.2.0",
+ "resolve-pathname": "^3.0.0",
+ "tiny-invariant": "^1.0.2",
+ "tiny-warning": "^1.0.0",
+ "value-equal": "^1.0.1"
+ }
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+ },
+ "path-to-regexp": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
+ "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
+ "requires": {
+ "isarray": "0.0.1"
+ }
+ },
+ "react-router": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz",
+ "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==",
+ "requires": {
+ "@babel/runtime": "^7.1.2",
+ "history": "^4.9.0",
+ "hoist-non-react-statics": "^3.1.0",
+ "loose-envify": "^1.3.1",
+ "mini-create-react-context": "^0.4.0",
+ "path-to-regexp": "^1.7.0",
+ "prop-types": "^15.6.2",
+ "react-is": "^16.6.0",
+ "tiny-invariant": "^1.0.2",
+ "tiny-warning": "^1.0.0"
+ }
+ }
+ }
+ },
"react-scripts": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.1.tgz",
@@ -11429,6 +11656,27 @@
"scheduler": "^0.19.1"
}
},
+ "react-toastify": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-6.0.5.tgz",
+ "integrity": "sha512-1YXSb6Jr478c1TJEyVpxLHFvtmeXGMvdpZc0fke/7lK+MoLBC+NFgB74bq+C2SZe6LdK+K1voEURJoY88WqWvA==",
+ "requires": {
+ "classnames": "^2.2.6",
+ "prop-types": "^15.7.2",
+ "react-transition-group": "^4.4.1"
+ }
+ },
+ "react-transition-group": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
+ "integrity": "sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==",
+ "requires": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ }
+ },
"read-pkg": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
@@ -11491,6 +11739,62 @@
"strip-indent": "^3.0.0"
}
},
+ "redux": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz",
+ "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==",
+ "requires": {
+ "loose-envify": "^1.4.0",
+ "symbol-observable": "^1.2.0"
+ }
+ },
+ "redux-devtools-extension": {
+ "version": "2.13.8",
+ "resolved": "https://registry.npmjs.org/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz",
+ "integrity": "sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg=="
+ },
+ "redux-form": {
+ "version": "8.3.5",
+ "resolved": "https://registry.npmjs.org/redux-form/-/redux-form-8.3.5.tgz",
+ "integrity": "sha512-GSpi9pbEor2wmL2cie+svP8QCylbwjlpAFegOHPaxSrQQm2Mk8ZHVWVObJUfF9cXcczIzB/bH/xOdIqeNl1OCA==",
+ "requires": {
+ "@babel/runtime": "^7.8.4",
+ "es6-error": "^4.1.1",
+ "hoist-non-react-statics": "^3.3.2",
+ "invariant": "^2.2.4",
+ "is-promise": "^2.1.0",
+ "lodash": "^4.17.15",
+ "lodash-es": "^4.17.15",
+ "prop-types": "^15.6.1",
+ "react-is": "^16.12.0"
+ }
+ },
+ "redux-localstorage-simple": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/redux-localstorage-simple/-/redux-localstorage-simple-2.2.0.tgz",
+ "integrity": "sha512-BmgnJ3NkxTDvNsnHAZrRVDgODafg2Vtb17q2F2LEhuJ+EderZBJA6aqRsyqZC32BJWpu8PPtferv4Io9dpUf3w==",
+ "requires": {
+ "object-merge": "2.5.1"
+ }
+ },
+ "redux-logger": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-3.0.6.tgz",
+ "integrity": "sha1-91VZZvMJjzyIYExEnPC69XeCdL8=",
+ "requires": {
+ "deep-diff": "^0.3.5"
+ }
+ },
+ "redux-promise-middleware": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/redux-promise-middleware/-/redux-promise-middleware-6.1.2.tgz",
+ "integrity": "sha512-ZqZu/nnSzGgwTtNbGoGVontpk7LjTOv0kigtt3CcgXI9gpq+8WlfXTXRZD0WTD5yaohRq0q2nYmJXSTjwXs83Q=="
+ },
+ "redux-thunk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz",
+ "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw=="
+ },
"reflect.ownkeys": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz",
@@ -11729,6 +12033,11 @@
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
"integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
},
+ "resolve-pathname": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
+ "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
+ },
"resolve-url": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
@@ -12059,9 +12368,9 @@
"integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ=="
},
"serve": {
- "version": "11.3.0",
- "resolved": "https://registry.npmjs.org/serve/-/serve-11.3.0.tgz",
- "integrity": "sha512-AU0g50Q1y5EVFX56bl0YX5OtVjUX1N737/Htj93dQGKuHiuLvVB45PD8Muar70W6Kpdlz8aNJfoUqTyAq9EE/A==",
+ "version": "11.3.1",
+ "resolved": "https://registry.npmjs.org/serve/-/serve-11.3.1.tgz",
+ "integrity": "sha512-+tcx5eybTZT0scsp1PCb7HYjzBSfRF9fQIwyEU8ZYLioVuhHwywRYBBTF5WYlTXvC62eumK2bloDXAd7+9blGQ==",
"requires": {
"@zeit/schemas": "2.6.0",
"ajv": "6.5.3",
@@ -13101,6 +13410,11 @@
}
}
},
+ "symbol-observable": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
+ "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
+ },
"symbol-tree": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
@@ -13390,6 +13704,16 @@
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
},
+ "tiny-invariant": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",
+ "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw=="
+ },
+ "tiny-warning": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
+ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
+ },
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
@@ -13780,6 +14104,11 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "value-equal": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
+ "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw=="
+ },
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
diff --git a/package.json b/package.json
index 535b0b2..caa49ac 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,9 @@
{
"name": "edukolab",
"version": "0.0.1",
- "description": "A boilerplate for starting js code",
+ "description": "employment opportunities for teachers",
"keywords": [
- "edukolab-frontend",
- "boilerplate"
+ "edukolab-frontend"
],
"private": false,
"directories": {
@@ -35,17 +34,37 @@
},
"license": "MIT",
"dependencies": {
+ "@fortawesome/fontawesome-svg-core": "^1.2.28",
+ "@fortawesome/free-brands-svg-icons": "^5.13.0",
+ "@fortawesome/free-regular-svg-icons": "^5.13.0",
+ "@fortawesome/free-solid-svg-icons": "^5.13.0",
+ "@fortawesome/react-fontawesome": "^0.1.9",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
+ "axios": "^0.19.2",
+ "bootstrap": "^4.5.0",
"cross-env": "^7.0.2",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"jest-enzyme": "^7.1.2",
+ "jquery": "^3.5.1",
+ "popper.js": "^1.16.1",
+ "prop-types": "^15.7.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
+ "react-redux": "^7.2.0",
+ "react-router-dom": "^5.2.0",
"react-scripts": "3.4.1",
- "serve": "^11.3.0"
+ "react-toastify": "^6.0.5",
+ "redux": "^4.0.5",
+ "redux-devtools-extension": "^2.13.8",
+ "redux-form": "^8.3.5",
+ "redux-localstorage-simple": "^2.2.0",
+ "redux-logger": "^3.0.6",
+ "redux-promise-middleware": "^6.1.2",
+ "redux-thunk": "^2.3.0",
+ "serve": "^11.3.1"
},
"devDependencies": {
"@babel/core": "^7.9.0",
diff --git a/public/css/master.css b/public/css/master.css
deleted file mode 100644
index 61fcca8..0000000
--- a/public/css/master.css
+++ /dev/null
@@ -1,117 +0,0 @@
-/* CSS Document */
-* {
- font-family: 'Montserrat', sans-serif;
- box-sizing: border-box;
- word-wrap: break-word;
- transition: all 0.05s;
-}
-
-body,
-html {
- height: 100%;
-}
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- font-family: 'Roboto', serif;
-}
-
-a {
- text-decoration: none;
- box-shadow: none;
- background: inherit;
-}
-
-a:hover,
-a.active {
- color: #161940;
- font-weight: 600;
-}
-
-.form-control,
-.form-control:-webkit-autofill,
-.form-control:-webkit-autofill:hover,
-.form-control:-webkit-autofill:focus,
-.form-control:-webkit-autofill:active {
- box-shadow: none;
- -webkit-box-shadow: 0 0 0 100 #fff inset;
- font-family: 'Montserrat', sans-serif;
-}
-
-.btn,
-button,
-.btn:focus,
-button:focus,
-.btn:hover,
-button:hover {
- font-weight: 600;
- box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
- border: none;
- color: #fff;
-}
-
-.border-success {
- border-color: #099a7e;
-}
-
-.border-primary {
- border-color: #161940;
-}
-
-.border-warning {
- border-color: #e7816e;
-}
-
-.text-success,
-.btn-outline-success {
- color: #099a7e;
-}
-
-.text-primary,
-.btn-outline-primary {
- color: #161940;
-}
-
-.text-warning,
-.btn-outline-warning {
- color: #e7816e;
-}
-
-.bg-success,
-.btn-success,
-.btn-outline-success:hover {
- background: #099a7e;
-}
-
-.bg-primary,
-.btn-primary,
-.btn-outline-primary:hover {
- background: #161940;
-}
-
-.bg-warning,
-.btn-warning,
-.btn-outline-warning:hover {
- background: #e7816e;
-}
-
-.btn-link {
- box-shadow: none;
- color: #161940;
- font-weight: bold;
- padding-left: 0;
- text-decoration: none;
-}
-
-.clear {
- clear: both;
-}
-
-.pointer {
- box-shadow: none;
- cursor: pointer;
-}
diff --git a/public/index.html b/public/index.html
index 75a1969..748836a 100644
--- a/public/index.html
+++ b/public/index.html
@@ -48,9 +48,9 @@
-->
-
+
-
+
@@ -67,9 +67,6 @@
-
-
-