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 ( +
+

Welcome Back

+

+ Login to EduKolab{' '} + + 😉 + +

+
+ +
+
+ +
+ +
+ + + Create Account + +
+
+ ); + } +} + +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 ( +
+

Welcome Back

+

+ Login to EduKolab{' '} + + 😉 + +

+
+ +
+
+ +
+ +
+ + + Create Account + +
+
+ ); + } +} + +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 = () => ( + <> + + +
+
+
+ +
+ +
+ +
+

or login with

+
+ +
+
+
+
+
+ + ); +} + + +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 = () => ( + <> + + +
+
+
+ +
+ +
+ +
+

or login with

+
+ +
+
+
+
+
+ + ); +} + + +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 = () => ( + <> + + +
+
+
+ +
+ +
+ +
+

or login with

+
+ +
+
+
+
+
+ + ); +} + + +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 [![Codacy Badge](https://api.codacy.com/project/badge/Grade/c2a6c9e610854e1da519d5eeab79df0d)](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) -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/c2a6c9e610854e1da519d5eeab79df0d)](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 @@ - - -