diff --git a/.babelrc b/.babelrc
index 5557047..0938dbc 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,4 +1,12 @@
{
- "presets": ["@babel/preset-env","@babel/preset-react"],
- "plugins": ["transform-class-properties"]
+ "presets": [
+ "@babel/preset-env",
+ "@babel/preset-react"
+ ],
+ "plugins": [
+ "transform-class-properties",
+ "@babel/plugin-proposal-class-properties",
+ "@babel/plugin-transform-regenerator",
+ "@babel/plugin-transform-runtime"
+ ]
}
diff --git a/.codeclimate.yml b/.codeclimate.yml
new file mode 100644
index 0000000..80ed262
--- /dev/null
+++ b/.codeclimate.yml
@@ -0,0 +1,10 @@
+version: "2"
+checks:
+ method-lines:
+ config:
+ threshold: 40
+ method-complexity:
+ config:
+ threshold: 6
+exclude_patterns:
+- "**/__tests__/"
diff --git a/.eslintrc.json b/.eslintrc.json
index 2617ee6..0c443aa 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -33,6 +33,9 @@
}
],
"react/no-array-index-key": 0,
- "jsx-a11y/anchor-is-valid": 0
+ "jsx-a11y/anchor-is-valid": 0,
+ "no-shadow": 0,
+ "no-nested-ternary": 0,
+ "react/jsx-props-no-spreading": 0
}
}
diff --git a/package.json b/package.json
index 467f554..7e7ccc5 100644
--- a/package.json
+++ b/package.json
@@ -34,14 +34,19 @@
"homepage": "https://github.com/Stackup-Rwanda/stackup2-barefoot-frontend#readme",
"dependencies": {
"@babel/core": "^7.9.6",
+ "@babel/plugin-transform-runtime": "^7.10.1",
+ "@babel/polyfill": "^7.10.1",
+ "@babel/preset-env": "^7.10.2",
"@babel/preset-react": "^7.9.4",
"@material-ui/core": "^4.10.0",
"@material-ui/icons": "^4.9.1",
+ "@material-ui/lab": "^4.0.0-alpha.55",
"@storybook/addon-actions": "^5.3.18",
"@storybook/addon-links": "^5.3.18",
"@storybook/addons": "^5.3.18",
"@storybook/react": "^5.3.18",
"@testing-library/react": "^10.0.4",
+ "axios": "^0.19.2",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.0.1",
"babel-loader": "^8.1.0",
@@ -59,23 +64,28 @@
"jest": "^26.0.1",
"jest-html-reporters": "^1.2.1",
"jest-transform-stub": "^2.0.0",
+ "less-loader": "^6.1.0",
"mini-css-extract-plugin": "^0.9.0",
"prop-types": "^15.7.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
+ "react-loader-spinner": "^3.1.14",
"react-redux": "^7.2.0",
"react-router-dom": "^5.2.0",
+ "react-slick": "^0.26.1",
"react-test-renderer": "^16.13.1",
"redux": "^4.0.5",
"redux-devtools-extension": "^2.13.8",
"redux-mock-store": "^1.5.4",
"redux-thunk": "^2.3.0",
+ "slick-carousel": "^1.8.1",
"style-loader": "^1.2.1",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.11.0"
},
"devDependencies": {
+ "dotenv-webpack": "^1.8.0",
"eslint": "^6.8.0",
"eslint-config-airbnb": "^18.1.0",
"eslint-plugin-import": "^2.20.2",
diff --git a/src/__tests__/App.test.js b/src/__tests__/App.test.js
index 3edf03d..6aa16bc 100644
--- a/src/__tests__/App.test.js
+++ b/src/__tests__/App.test.js
@@ -4,32 +4,39 @@ import { mount, shallow } from 'enzyme';
import React from 'react';
import { Provider } from 'react-redux';
import renderer from 'react-test-renderer';
+import { cleanup } from '@testing-library/react';
import configureStore from 'redux-mock-store';
import App from '../entry/App';
-import LandingPage from '../views/LandingPage/LandingPage';
-import reducer from '../reducers/reducer';
-import firstMessage from '../actions/actions';
+// import LandingPage from '../views/LandingPage/LandingPage';
+// import reducer from '../reducers/reducer';
+// import firstMessage from '../actions/actions';
-const mockStore = configureStore([]);
-const store = mockStore({
- message: 'Welcome',
-});
-store.dispatch = jest.fn();
-const component = renderer.create(
-
-
- ,
-);
+// const mockStore = configureStore([]);
+// const store = mockStore({
+// message: 'Welcome',
+// });
+// store.dispatch = jest.fn();
+// const component = renderer.create(
+//
+//
+// ,
+// );
describe('App tests', () => {
- it('Will prove that the app is rendered from App component', () => {
- const appRender = shallow();
- expect(appRender.contains());
- });
+ afterEach(cleanup);
- it('should return welcome when no action provided', () => {
- expect(reducer(undefined, {})).toEqual({ message: 'Welcome' });
- });
- it('should return Redux when action is provided with value', () => {
- expect(reducer(undefined, { ...firstMessage, value: 'Redux' })).toEqual({ message: 'Redux' });
+ it('Should match the App component snapshot', () => {
+ const tree = renderer.create().toJSON();
+ expect(tree).toMatchSnapshot();
});
+ // it('Will prove that the app is rendered from App component', () => {
+ // const appRender = shallow();
+ // expect(appRender.contains());
+ // });
+
+ // it('should return welcome when no action provided', () => {
+ // expect(reducer(undefined, {})).toEqual({ message: 'Welcome' });
+ // });
+ // it('should return Redux when action is provided with value', () => {
+ // expect(reducer(undefined, { ...firstMessage, value: 'Redux' })).toEqual({ message: 'Redux' });
+ // });
});
diff --git a/src/__tests__/RequestsTablePage.test.js b/src/__tests__/RequestsTablePage.test.js
new file mode 100644
index 0000000..ef685d7
--- /dev/null
+++ b/src/__tests__/RequestsTablePage.test.js
@@ -0,0 +1,62 @@
+/* eslint-disable no-undef */
+import React from 'react';
+import { mount } from 'enzyme';
+import { cleanup } from '@testing-library/react';
+import thunk from 'redux-thunk';
+import { Provider } from 'react-redux';
+import configureStore from 'redux-mock-store';
+import { BrowserRouter as Router } from 'react-router-dom';
+import RequestsTablePage from '../views/RequestsTablePage/RequestsTablePage';
+import requests from './data/data';
+
+const mockStore = configureStore([]);
+const store = mockStore(
+ {
+ loading: true,
+ tripRequests: [],
+ error: '',
+ },
+);
+store.dispatch = jest.fn();
+
+const fetchTripRequests = jest.fn();
+const props = {
+ requests,
+ fetchTripRequests,
+};
+
+describe('', () => {
+ afterEach(cleanup);
+ it('Should return true if the RequestsTablePage component exists', () => {
+ const tree = mount(
+
+
+
+
+ ,
+ );
+ expect(tree.find('Card').exists()).toBe(true);
+ });
+
+ it('Should render props for the RequestsTablePage component', () => {
+ const tree = mount(
+
+
+
+
+ ,
+ );
+ expect(tree.find('StyledTableCell').exists()).toBe(true);
+ });
+
+ it('Should match the RequestsTablePage snapshot', () => {
+ const tree = mount(
+
+
+
+
+ ,
+ );
+ expect(tree).toMatchSnapshot();
+ });
+});
diff --git a/src/__tests__/SectionHeader.test.js b/src/__tests__/SectionHeader.test.js
new file mode 100644
index 0000000..2a05537
--- /dev/null
+++ b/src/__tests__/SectionHeader.test.js
@@ -0,0 +1,12 @@
+import React from 'react';
+import renderer from 'react-test-renderer';
+import { cleanup } from '@testing-library/react';
+import SectionHeader from '../components/SectionHeader/SectionHeader';
+
+describe('', () => {
+ afterEach(cleanup);
+ it('Should match the SectionHeader component snapshot', () => {
+ const tree = renderer.create().toJSON();
+ expect(tree).toMatchSnapshot();
+ });
+});
diff --git a/src/__tests__/__snapshots__/NavBar.test.js.snap b/src/__tests__/__snapshots__/NavBar.test.js.snap
deleted file mode 100644
index 56d5cf0..0000000
--- a/src/__tests__/__snapshots__/NavBar.test.js.snap
+++ /dev/null
@@ -1,50 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[` Should match the NavBar component snapshot 1`] = `
-
-`;
diff --git a/src/__tests__/__snapshots__/SectionHeader.test.js.snap b/src/__tests__/__snapshots__/SectionHeader.test.js.snap
new file mode 100644
index 0000000..f7b4ae4
--- /dev/null
+++ b/src/__tests__/__snapshots__/SectionHeader.test.js.snap
@@ -0,0 +1,7 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` Should match the SectionHeader component snapshot 1`] = `
+
+`;
diff --git a/src/__tests__/data/data.js b/src/__tests__/data/data.js
new file mode 100644
index 0000000..9ff6949
--- /dev/null
+++ b/src/__tests__/data/data.js
@@ -0,0 +1,32 @@
+const requests = {
+ tripRequests: [
+ {
+ id: 1,
+ trips: [
+ {
+ travelDate: '2020-09-15',
+ travelFrom: 'Kigali',
+ travelTo: 'Durban',
+ },
+ ],
+ travelReason: 'Africa Tech Summit',
+ accommodation: true,
+ status: 'pending',
+ },
+ {
+ id: 2,
+ trips: [
+ {
+ travelDate: '2020-09-10',
+ travelFrom: 'Kigali',
+ travelTo: 'Dubai',
+ },
+ ],
+ travelReason: 'Africa Tech Summit',
+ accommodation: true,
+ status: 'pending',
+ },
+ ],
+};
+
+export default requests;
diff --git a/src/actions/actions.js b/src/actions/actions.js
deleted file mode 100644
index 780bf61..0000000
--- a/src/actions/actions.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const firstMessage = {
- type: 'FIRST_MESSAGE',
-};
-
-export default firstMessage;
diff --git a/src/assets/styles/sass/index.scss b/src/assets/styles/sass/index.scss
index 8501e4f..b741745 100644
--- a/src/assets/styles/sass/index.scss
+++ b/src/assets/styles/sass/index.scss
@@ -137,7 +137,7 @@ body {
}
.testimony-item {
- display: flex;
+ display: flex !important;
flex-direction: row;
justify-content: center;
align-items: center;
@@ -169,6 +169,10 @@ body {
font-size: 14pt;
}
+.testimony-description {
+ margin-left: 2px;
+}
+
.testimony-author {
font-size: 10pt;
}
diff --git a/src/components/RequestsTable/RequestsTable.js b/src/components/RequestsTable/RequestsTable.js
new file mode 100644
index 0000000..b32638b
--- /dev/null
+++ b/src/components/RequestsTable/RequestsTable.js
@@ -0,0 +1,121 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles, makeStyles } from '@material-ui/core/styles';
+import Table from '@material-ui/core/Table';
+import TableBody from '@material-ui/core/TableBody';
+import TableCell from '@material-ui/core/TableCell';
+import TableContainer from '@material-ui/core/TableContainer';
+import TableHead from '@material-ui/core/TableHead';
+import TableRow from '@material-ui/core/TableRow';
+import RemoveCircleOutline from '@material-ui/icons/RemoveCircleOutline';
+import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline';
+import ActionsMenu from '../../views/ActionsMenu/ActionsMenu';
+
+const StyledTableCell = withStyles((theme) => ({
+ head: {
+ backgroundColor: theme.palette.secondary.contrastText,
+ color: theme.palette.primary.dark,
+ },
+ body: {
+ fontSize: 14,
+ },
+}))(TableCell);
+
+const StyledTableRow = withStyles((theme) => ({
+ root: {
+ '&:nth-of-type(odd)': {
+ backgroundColor: theme.palette.action.hover,
+ },
+ },
+}))(TableRow);
+
+const useStyles = makeStyles({
+ table: {
+ minWidth: 700,
+ },
+ tableCell: {
+ fontSize: 12,
+ },
+ tableIcons: {
+ fontSize: 16,
+ },
+ noData: {
+ fontSize: 14,
+ color: '#777777',
+ backgroundColor: '#FFFFFF',
+ textAlign: 'center',
+ },
+});
+
+const requesterActions = [
+ {
+ id: 1,
+ name: 'Edit',
+ },
+ {
+ id: 2,
+ name: 'Book Accommodation',
+ },
+ {
+ id: 3,
+ name: 'Rate Accommodation',
+ },
+ {
+ id: 4,
+ name: 'Like/Dislike Accommodation',
+ },
+];
+
+const RequestsTable = ({ requests }) => {
+ const classes = useStyles();
+
+ return (
+
+
+
+
+ Date
+ Departure
+ Destination
+ Reason
+ Accommodation
+ Status
+
+
+
+
+ {requests.length > 0 ? (requests.map((row) => (
+
+
+ {row.trips[0].travelDate}
+
+ {row.trips[0].travelFrom}
+ {row.trips[0].travelTo}
+ {row.travelReason}
+ {row.accommodation ? 'Yes' : 'No'}
+
+ {row.status === 'pending' ? : }
+
+
+
+
+
+ ))
+ ) : (
+
+
+ Oops! Looks like you have not yet made any requests.
+
+
+ )}
+
+
+
+ );
+};
+
+RequestsTable.propTypes = {
+ requests: PropTypes.arrayOf().isRequired,
+};
+
+export default RequestsTable;
diff --git a/src/components/SectionHeader/SectionHeader.js b/src/components/SectionHeader/SectionHeader.js
new file mode 100644
index 0000000..b59d777
--- /dev/null
+++ b/src/components/SectionHeader/SectionHeader.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { makeStyles } from '@material-ui/core/styles';
+import Typography from '@material-ui/core/Typography';
+
+const useStyles = makeStyles({
+ title: {
+ color: '#484848',
+ backgroundColor: '#00a7990f',
+ padding: 24,
+ fontSize: 14,
+ fontFamily: 'Roboto',
+ fontWeight: 500,
+ },
+});
+
+const SectionHeader = ({ title }) => {
+ const classes = useStyles();
+
+ return (
+
+ {title}
+
+ );
+};
+
+SectionHeader.propTypes = {
+ title: PropTypes.string.isRequired,
+};
+
+export default SectionHeader;
diff --git a/src/entry/App.js b/src/entry/App.js
index 2f18277..74b5f39 100644
--- a/src/entry/App.js
+++ b/src/entry/App.js
@@ -5,6 +5,7 @@ import CssBaseline from '@material-ui/core/CssBaseline';
import theme from '../assets/styles/theme';
import LandingPage from '../views/LandingPage/LandingPage';
import NavBar from '../views/NavBar/NavBar';
+import RequestsTablePage from '../views/RequestsTablePage/RequestsTablePage';
const App = () => (
@@ -12,7 +13,8 @@ const App = () => (
-
+
+
diff --git a/src/entry/index.js b/src/entry/index.js
index cdff617..ce45dad 100644
--- a/src/entry/index.js
+++ b/src/entry/index.js
@@ -1,14 +1,14 @@
import React from 'react';
import ReactDOM from 'react-dom';
-import { createStore } from 'redux';
import { Provider } from 'react-redux';
-import { composeWithDevTools } from 'redux-devtools-extension';
import App from './App';
import '../assets/styles/sass/index.scss';
import '../assets/styles/css/index.css';
-import reducer from '../reducers/reducer';
+import store from '../redux/store';
-const store = createStore(reducer, composeWithDevTools());
-
-ReactDOM.render(, document.getElementById('root'));
+ReactDOM.render(
+
+
+ , document.getElementById('root'),
+);
diff --git a/src/reducers/reducer.js b/src/reducers/reducer.js
deleted file mode 100644
index 0fbe134..0000000
--- a/src/reducers/reducer.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import firstMessage from '../actions/actions';
-
-const initialState = {
- message: 'Welcome',
-};
-const reducer = (state = initialState, action) => {
- switch (action.type) {
- case firstMessage.type:
- return {
- message: `${action.value}`,
- };
- default:
- return state;
- }
-};
-
-export default reducer;
diff --git a/src/redux/rootReducer.js b/src/redux/rootReducer.js
new file mode 100644
index 0000000..f0d7080
--- /dev/null
+++ b/src/redux/rootReducer.js
@@ -0,0 +1,8 @@
+import { combineReducers } from 'redux';
+import tripRequestsReducer from './tripRequests/tripRequestsReducer';
+
+const rootReducer = combineReducers({
+ tripRequests: tripRequestsReducer,
+});
+
+export default rootReducer;
diff --git a/src/redux/store.js b/src/redux/store.js
new file mode 100644
index 0000000..2bbb5bc
--- /dev/null
+++ b/src/redux/store.js
@@ -0,0 +1,11 @@
+import { createStore, applyMiddleware } from 'redux';
+import thunk from 'redux-thunk';
+import { composeWithDevTools } from 'redux-devtools-extension';
+import rootReducer from './rootReducer';
+
+const store = createStore(
+ rootReducer,
+ composeWithDevTools(applyMiddleware(thunk)),
+);
+
+export default store;
diff --git a/src/redux/tripRequests/__tests__/tripRequestsActions.test.js b/src/redux/tripRequests/__tests__/tripRequestsActions.test.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/redux/tripRequests/__tests__/tripRequestsReducer.test.js b/src/redux/tripRequests/__tests__/tripRequestsReducer.test.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/redux/tripRequests/tripRequestsActions.js b/src/redux/tripRequests/tripRequestsActions.js
new file mode 100644
index 0000000..cb5a68b
--- /dev/null
+++ b/src/redux/tripRequests/tripRequestsActions.js
@@ -0,0 +1,46 @@
+import axios from 'axios';
+import {
+ FETCH_TRIP_REQUESTS_REQUEST,
+ FETCH_TRIP_REQUESTS_SUCCESS,
+ FETCH_TRIP_REQUESTS_FAILURE,
+} from './tripRequestsTypes';
+
+export const fetchTripRequestsRequest = () => ({
+ type: FETCH_TRIP_REQUESTS_REQUEST,
+});
+
+export const fetchTripRequestsSuccess = (tripRequests) => ({
+ type: FETCH_TRIP_REQUESTS_SUCCESS,
+ payload: tripRequests,
+});
+
+export const fetchTripRequestsFailure = (error) => ({
+ type: FETCH_TRIP_REQUESTS_FAILURE,
+ payload: error,
+});
+
+const api = axios.create({
+ baseURL: process.env.REACT_APP_API_URL,
+ headers: {
+ Authorization: `Bearer ${process.env.REACT_APP_SOME_TOKEN}`,
+ 'Content-Type': 'application/json',
+ },
+ method: 'GET',
+});
+
+export const fetchTripRequests = () => async (dispatch) => {
+ try {
+ dispatch(fetchTripRequestsRequest);
+ const res = await api.get('/trips');
+ const tripRequests = res.data.data.foundRequests;
+ dispatch(fetchTripRequestsSuccess(tripRequests));
+ } catch (error) {
+ if (error.response.status === 400) {
+ const errorMessage = error.response.data.error;
+ dispatch(fetchTripRequestsFailure(errorMessage));
+ } else {
+ const tripRequests = [];
+ dispatch(fetchTripRequestsSuccess(tripRequests));
+ }
+ }
+};
diff --git a/src/redux/tripRequests/tripRequestsReducer.js b/src/redux/tripRequests/tripRequestsReducer.js
new file mode 100644
index 0000000..46f6bca
--- /dev/null
+++ b/src/redux/tripRequests/tripRequestsReducer.js
@@ -0,0 +1,36 @@
+import {
+ FETCH_TRIP_REQUESTS_REQUEST,
+ FETCH_TRIP_REQUESTS_SUCCESS,
+ FETCH_TRIP_REQUESTS_FAILURE,
+} from './tripRequestsTypes';
+
+const initialState = {
+ loading: true,
+ tripRequests: [],
+ error: '',
+};
+
+const tripRequestsReducer = (state = initialState, { type, payload }) => {
+ switch (type) {
+ case FETCH_TRIP_REQUESTS_REQUEST:
+ return {
+ ...state,
+ loading: true,
+ };
+ case FETCH_TRIP_REQUESTS_SUCCESS:
+ return {
+ loading: false,
+ tripRequests: payload,
+ error: '',
+ };
+ case FETCH_TRIP_REQUESTS_FAILURE:
+ return {
+ loading: false,
+ tripRequests: [],
+ error: payload,
+ };
+ default: return state;
+ }
+};
+
+export default tripRequestsReducer;
diff --git a/src/redux/tripRequests/tripRequestsTypes.js b/src/redux/tripRequests/tripRequestsTypes.js
new file mode 100644
index 0000000..5a2b7dd
--- /dev/null
+++ b/src/redux/tripRequests/tripRequestsTypes.js
@@ -0,0 +1,3 @@
+export const FETCH_TRIP_REQUESTS_REQUEST = 'FETCH_TRIP_REQUESTS_REQUEST';
+export const FETCH_TRIP_REQUESTS_SUCCESS = 'FETCH_TRIP_REQUESTS_SUCCESS';
+export const FETCH_TRIP_REQUESTS_FAILURE = 'FETCH_TRIP_REQUESTS_FAILURE';
diff --git a/src/views/ActionsMenu/ActionsMenu.js b/src/views/ActionsMenu/ActionsMenu.js
new file mode 100644
index 0000000..d990bc7
--- /dev/null
+++ b/src/views/ActionsMenu/ActionsMenu.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { makeStyles } from '@material-ui/core/styles';
+import Button from '@material-ui/core/Button';
+import Menu from '@material-ui/core/Menu';
+import MenuItem from '@material-ui/core/MenuItem';
+import MoreVert from '@material-ui/icons/MoreVert';
+
+const useStyles = makeStyles({
+ tableIcons: {
+ fontSize: 16,
+ },
+ item: {
+ fontSize: 12,
+ color: '#484848',
+ },
+});
+
+const ActionsMenu = ({ actions }) => {
+ const [anchorEl, setAnchorEl] = React.useState(null);
+
+ const handleClick = (event) => {
+ setAnchorEl(event.currentTarget);
+ };
+
+ const handleClose = () => {
+ setAnchorEl(null);
+ };
+
+ const classes = useStyles();
+
+ return (
+
+
+
+
+ );
+};
+
+ActionsMenu.propTypes = {
+ actions: PropTypes.arrayOf().isRequired,
+};
+
+export default ActionsMenu;
diff --git a/src/views/ActionsMenu/__tests__/ActionsMenu.test.js b/src/views/ActionsMenu/__tests__/ActionsMenu.test.js
new file mode 100644
index 0000000..62e28e6
--- /dev/null
+++ b/src/views/ActionsMenu/__tests__/ActionsMenu.test.js
@@ -0,0 +1,32 @@
+/* eslint-disable no-undef */
+import React from 'react';
+import renderer from 'react-test-renderer';
+import { cleanup } from '@testing-library/react';
+import ActionsMenu from '../ActionsMenu';
+
+const requesterActions = [
+ {
+ id: 1,
+ name: 'Edit',
+ },
+ {
+ id: 2,
+ name: 'Book Accommodation',
+ },
+ {
+ id: 3,
+ name: 'Rate Accommodation',
+ },
+ {
+ id: 4,
+ name: 'Like/Dislike Accommodation',
+ },
+];
+
+describe('', () => {
+ afterEach(cleanup);
+ it('Should match the ActionsMenu component snapshot', () => {
+ const tree = renderer.create().toJSON();
+ expect(tree).toMatchSnapshot();
+ });
+});
diff --git a/src/views/Footer/__tests__/Footer.test.js b/src/views/Footer/__tests__/Footer.test.js
new file mode 100644
index 0000000..b960928
--- /dev/null
+++ b/src/views/Footer/__tests__/Footer.test.js
@@ -0,0 +1,13 @@
+/* eslint-disable no-undef */
+import React from 'react';
+import renderer from 'react-test-renderer';
+import { cleanup } from '@testing-library/react';
+import Footer from '../Footer';
+
+describe('', () => {
+ afterEach(cleanup);
+ it('Should match the Footer component snapshot', () => {
+ const tree = renderer.create().toJSON();
+ expect(tree).toMatchSnapshot();
+ });
+});
diff --git a/src/views/Footer/__tests__/__snapshots__/Footer.test.js.snap b/src/views/Footer/__tests__/__snapshots__/Footer.test.js.snap
new file mode 100644
index 0000000..d66cf69
--- /dev/null
+++ b/src/views/Footer/__tests__/__snapshots__/Footer.test.js.snap
@@ -0,0 +1,101 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` Should match the Footer component snapshot 1`] = `
+
+`;
diff --git a/src/views/LandingPage/LandingPage.js b/src/views/LandingPage/LandingPage.js
index 1031b82..1b7e06e 100644
--- a/src/views/LandingPage/LandingPage.js
+++ b/src/views/LandingPage/LandingPage.js
@@ -1,7 +1,7 @@
import React from 'react';
import Button from '@material-ui/core/Button';
import Remove from '@material-ui/icons/Remove';
-import FormatQuoteRounded from '@material-ui/icons/FormatQuoteRounded';
+import Testimonials from './Testimonials';
import CustomCard from '../../components/CustomCard/CustomCard';
import Footer from '../Footer/Footer';
@@ -28,18 +28,7 @@ const LandingPage = () => (
-
-
-
-
-
- Barefoot Nomad
- has helped my company's staff travels &
- find the best accommodations there is.
-
-
Elon Musk - CEO of Tesla Inc.
-
-
+
diff --git a/src/views/LandingPage/Testimonials.js b/src/views/LandingPage/Testimonials.js
new file mode 100644
index 0000000..c2e5893
--- /dev/null
+++ b/src/views/LandingPage/Testimonials.js
@@ -0,0 +1,63 @@
+import React from 'react';
+import 'slick-carousel/slick/slick.css';
+import 'slick-carousel/slick/slick-theme.css';
+import Slider from 'react-slick';
+import FormatQuoteRounded from '@material-ui/icons/FormatQuoteRounded';
+
+const settings = {
+ autoplay: true,
+ centerMode: true,
+ dots: true,
+ infinite: true,
+ speed: 1000,
+ slidesToShow: 1,
+ slidesToScroll: 1,
+ swipeToSlide: true,
+ lazyLoad: true,
+ autoplaySpeed: 5000,
+ cssEase: 'linear',
+};
+
+const data = [
+ {
+ id: 1,
+ text: `has helped my company's staff travels and
+ find the best accommodations there is.`,
+ author: 'Elon Musk - CEO of Tesla Inc.',
+ },
+ {
+ id: 2,
+ text: `is awesome! Organizing my staff's
+ travels is very easy and fast.`,
+ author: 'Jack Dorsey - Founder of Twitter',
+ },
+ {
+ id: 3,
+ text: 'has helped me to manage my work travels effectively. I highly recommend it.',
+ author: '@the22mastermind - Software Engineer',
+ },
+];
+
+const Testimonials = () => (
+
+ {
+ data.map((testimony) => (
+
+
+
+
+
+ Barefoot Nomad
+
+ {testimony.text}
+
+
+
{testimony.author}
+
+
+ ))
+ }
+
+);
+
+export default Testimonials;
diff --git a/src/views/LandingPage/__tests__/LandingPage.test.js b/src/views/LandingPage/__tests__/LandingPage.test.js
new file mode 100644
index 0000000..770c3c0
--- /dev/null
+++ b/src/views/LandingPage/__tests__/LandingPage.test.js
@@ -0,0 +1,14 @@
+/* eslint-disable no-undef */
+import React from 'react';
+import { shallow } from 'enzyme';
+import { cleanup } from '@testing-library/react';
+import LandingPage from '../LandingPage';
+
+describe('
', () => {
+ afterEach(cleanup);
+
+ it('Should test the LandingPage component', () => {
+ const tree = shallow(
);
+ expect(tree.find('.container').exists()).toBe(true);
+ });
+});
diff --git a/src/views/LoadingSpinner/LoadingSpinner.js b/src/views/LoadingSpinner/LoadingSpinner.js
new file mode 100644
index 0000000..19da621
--- /dev/null
+++ b/src/views/LoadingSpinner/LoadingSpinner.js
@@ -0,0 +1,15 @@
+import React from 'react';
+import 'react-loader-spinner/dist/loader/css/react-spinner-loader.css';
+import Loader from 'react-loader-spinner';
+
+const LoadingSpinner = () => (
+
+);
+
+export default LoadingSpinner;
diff --git a/src/views/LoadingSpinner/__tests__/LoadingSpinner.test.js b/src/views/LoadingSpinner/__tests__/LoadingSpinner.test.js
new file mode 100644
index 0000000..8b93ff5
--- /dev/null
+++ b/src/views/LoadingSpinner/__tests__/LoadingSpinner.test.js
@@ -0,0 +1,13 @@
+/* eslint-disable no-undef */
+import React from 'react';
+import renderer from 'react-test-renderer';
+import { cleanup } from '@testing-library/react';
+import LoadingSpinner from '../LoadingSpinner';
+
+describe('
', () => {
+ afterEach(cleanup);
+ it('Should match the LoadingSpinner component snapshot', () => {
+ const tree = renderer.create(
).toJSON();
+ expect(tree).toMatchSnapshot();
+ });
+});
diff --git a/src/views/LoadingSpinner/__tests__/__snapshots__/LoadingSpinner.test.js.snap b/src/views/LoadingSpinner/__tests__/__snapshots__/LoadingSpinner.test.js.snap
new file mode 100644
index 0000000..3e32fa7
--- /dev/null
+++ b/src/views/LoadingSpinner/__tests__/__snapshots__/LoadingSpinner.test.js.snap
@@ -0,0 +1,100 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`
Should match the LoadingSpinner component snapshot 1`] = `
+
+
+
+`;
diff --git a/src/views/NavBar/NavBar.js b/src/views/NavBar/NavBar.js
index 3a2bed4..7cb01e3 100644
--- a/src/views/NavBar/NavBar.js
+++ b/src/views/NavBar/NavBar.js
@@ -2,7 +2,7 @@ import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
-import Link from '@material-ui/core/Link';
+import { Link } from 'react-router-dom';
const useStyles = makeStyles((theme) => ({
root: {
@@ -25,8 +25,8 @@ const NavBar = () => {
Nomad
- Login
- Create account
+ Login
+ Create account
diff --git a/src/views/RequestsTablePage/RequestsTablePage.js b/src/views/RequestsTablePage/RequestsTablePage.js
new file mode 100644
index 0000000..b2d97b4
--- /dev/null
+++ b/src/views/RequestsTablePage/RequestsTablePage.js
@@ -0,0 +1,97 @@
+import React, { useEffect } from 'react';
+import { connect } from 'react-redux';
+import PropTypes from 'prop-types';
+import { makeStyles } from '@material-ui/core/styles';
+import Card from '@material-ui/core/Card';
+import CardContent from '@material-ui/core/CardContent';
+import SectionHeader from '../../components/SectionHeader/SectionHeader';
+import UserProfileCard from '../UserProfileCard/UserProfileCard';
+import RequestsTable from '../../components/RequestsTable/RequestsTable';
+import LoadingSpinner from '../LoadingSpinner/LoadingSpinner';
+import ToastNotification from '../ToastNotification/ToastNotification';
+import { fetchTripRequests } from '../../redux/tripRequests/tripRequestsActions';
+
+const useStyles = makeStyles({
+ root: {
+ backgroundColor: '#FFFFFF',
+ minHeight: 544,
+ boxShadow: 'none',
+ padding: 14,
+ display: 'flex',
+ alignItems: 'flex-start',
+ justifyContent: 'space-between',
+ },
+ content: {
+ padding: 0,
+ border: '1px solid #00a79926',
+ width: '75%',
+ },
+ leftPane: {
+ width: '20%',
+ padding: 0,
+ margin: 0,
+ minHeight: 544,
+ },
+ loader: {
+ backgroundColor: '#FFFFFF',
+ minHeight: 544,
+ boxShadow: 'none',
+ padding: 14,
+ display: 'flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+});
+
+const RequestsTablePage = ({ requests, fetchTripRequests }) => {
+ useEffect(() => {
+ fetchTripRequests();
+ }, []);
+
+ const classes = useStyles();
+
+ return requests.loading ? (
+
+
+
+ )
+ : requests.error ? (
+
+
+
+ ) : (
+
+
+
+
+
+
+
+
+
+ );
+};
+
+RequestsTablePage.propTypes = {
+ loading: PropTypes.bool.isRequired,
+ error: PropTypes.string.isRequired,
+ requests: PropTypes.objectOf().isRequired,
+ fetchTripRequests: PropTypes.func.isRequired,
+};
+
+const mapStateToProps = (state) => {
+ return {
+ loading: state.loading,
+ error: state.error,
+ requests: state.tripRequests,
+ };
+};
+
+const mapDispatchToProps = (dispatch) => ({
+ fetchTripRequests: () => dispatch(fetchTripRequests()),
+});
+
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps,
+)(RequestsTablePage);
diff --git a/src/views/ToastNotification/ToastNotification.js b/src/views/ToastNotification/ToastNotification.js
new file mode 100644
index 0000000..e7ba0de
--- /dev/null
+++ b/src/views/ToastNotification/ToastNotification.js
@@ -0,0 +1,35 @@
+import React, { useState } from 'react';
+import PropTypes from 'prop-types';
+import Snackbar from '@material-ui/core/Snackbar';
+import MuiAlert from '@material-ui/lab/Alert';
+import { makeStyles } from '@material-ui/core/styles';
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ width: '100%',
+ '& > * + *': {
+ marginTop: theme.spacing(2),
+ },
+ },
+}));
+
+const ToastNotification = ({ error }) => {
+ const classes = useStyles();
+ const [open] = useState(true);
+
+ return (
+
+
+
+ {error}
+
+
+
+ );
+};
+
+ToastNotification.propTypes = {
+ error: PropTypes.string.isRequired,
+};
+
+export default ToastNotification;
diff --git a/src/views/ToastNotification/__tests__/ToastNotification.test.js b/src/views/ToastNotification/__tests__/ToastNotification.test.js
new file mode 100644
index 0000000..35bf38d
--- /dev/null
+++ b/src/views/ToastNotification/__tests__/ToastNotification.test.js
@@ -0,0 +1,13 @@
+/* eslint-disable no-undef */
+import React from 'react';
+import renderer from 'react-test-renderer';
+import { cleanup } from '@testing-library/react';
+import ToastNotification from '../ToastNotification';
+
+describe('', () => {
+ afterEach(cleanup);
+ it('Should match the SectionHeader component snapshot', () => {
+ const tree = renderer.create().toJSON();
+ expect(tree).toMatchSnapshot();
+ });
+});
diff --git a/src/views/UserProfileCard/UserProfileCard.js b/src/views/UserProfileCard/UserProfileCard.js
new file mode 100644
index 0000000..90923df
--- /dev/null
+++ b/src/views/UserProfileCard/UserProfileCard.js
@@ -0,0 +1,134 @@
+import React from 'react';
+import Link from '@material-ui/core/Link';
+import { makeStyles } from '@material-ui/core/styles';
+import AccountCircle from '@material-ui/icons/AccountCircle';
+import Help from '@material-ui/icons/Help';
+
+const useStyles = makeStyles({
+ wrapper: {
+ width: '100%',
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'space-between',
+ alignItems: 'flex-start',
+ backgroundColor: '#FFFFFF',
+ minHeight: 544,
+ fontFamily: 'Roboto, Arial, sans-serif',
+ },
+ profileSection: {
+ width: '100%',
+ border: '1px solid #00A799',
+ padding: 12,
+ },
+ userIconWrapper: {
+ width: '100%',
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: 24,
+ },
+ userIcon: {
+ fontSize: 72,
+ },
+ username: {
+ color: '#484848',
+ fontSize: 14,
+ fontWeight: 700,
+ },
+ row: {
+ display: 'flex',
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: 12,
+ },
+ label: {
+ color: '#00A799',
+ fontSize: 12,
+ fontWeight: 700,
+ },
+ text: {
+ color: '#484848',
+ fontSize: 12,
+ },
+ linkWrapper: {
+ textAlign: 'right',
+ },
+ link: {
+ color: '#00A799',
+ fontSize: 12,
+ textAlign: 'right',
+ marginBottom: 6,
+ },
+ helpSection: {
+ display: 'flex',
+ flexDirection: 'row',
+ justifyContent: 'flex-start',
+ alignItems: 'center',
+ },
+ helpIcon: {
+ fontSize: 18,
+ marginRight: 6,
+ },
+});
+
+const userPreferences = [
+ {
+ id: 1,
+ label: 'Email',
+ value: 'username@barefoot.com',
+ },
+ {
+ id: 2,
+ label: 'DOB',
+ value: '12-24-1986',
+ },
+ {
+ id: 3,
+ label: 'Position',
+ value: 'Senior Software Engineer',
+ },
+ {
+ id: 4,
+ label: 'Currency',
+ value: 'USD',
+ },
+ {
+ id: 5,
+ label: 'Language',
+ value: 'English',
+ },
+];
+
+const UserProfileCard = () => {
+ const classes = useStyles();
+
+ return (
+
+
+
+ {
+ userPreferences.map((item) => (
+
+ {item.label}
+ {item.value}
+
+ ))
+ }
+
+ Edit profile
+
+
+
+
+ Help & Support
+
+
+ );
+};
+
+export default UserProfileCard;
diff --git a/tests.config.js b/tests.config.js
index 82edfc9..445808a 100644
--- a/tests.config.js
+++ b/tests.config.js
@@ -1,4 +1,13 @@
+/* eslint-disable func-names */
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
+
+window.matchMedia = window.matchMedia || function () {
+ return {
+ matches: false,
+ addListener() { },
+ removeListener() { },
+ };
+};
diff --git a/webpack.config.js b/webpack.config.js
index c7cdd4b..68b6164 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,11 +1,11 @@
const HtmlWebPackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');
-require('dotenv').config();
+const Dotenv = require('dotenv-webpack');
module.exports = (env) => ({
context: __dirname,
- entry: './src/entry/index.js',
+ entry: ['./src/entry/index.js'],
output: {
path: path.resolve(__dirname, 'build'),
filename: 'barefoot-nomad-build.js',
@@ -14,7 +14,7 @@ module.exports = (env) => ({
mode: env ? 'production' : 'development',
devServer: {
inline: true,
- port: process.env.PORT,
+ port: process.env.REACT_APP_PORT,
contentBase: path.join(__dirname, 'build'),
},
@@ -23,15 +23,19 @@ module.exports = (env) => ({
{
test: /\.js$/,
exclude: /node_modules/,
- use: ['babel-loader'],
+ use: {
+ loader: 'babel-loader',
+ options: {
+ presets: ['@babel/preset-env'],
+ },
+ },
},
{
test: /\.(scss|css)$/,
- exclude: /node_modules/,
loader: ['style-loader', 'css-loader', 'sass-loader'],
},
{
- test: /\.(png|jpg|svg|gif|jpeg)?$/,
+ test: /\.(png|jpg|svg|gif|jpeg|woff|woff2|eot|ttf|otf)?$/,
use: ['file-loader'],
},
],
@@ -45,6 +49,7 @@ module.exports = (env) => ({
filename: '[name].css',
chunkFilename: '[id].css',
}),
+ new Dotenv(),
],
performance: {
hints: false,
diff --git a/yarn.lock b/yarn.lock
index d731685..a4c6958 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -999,6 +999,16 @@
dependencies:
"@babel/helper-plugin-utils" "^7.10.1"
+"@babel/plugin-transform-runtime@^7.10.1":
+ version "7.10.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.10.1.tgz#fd1887f749637fb2ed86dc278e79eb41df37f4b1"
+ integrity sha512-4w2tcglDVEwXJ5qxsY++DgWQdNJcCCsPxfT34wCUwIf2E7dI7pMpH8JczkMBbgBTNzBX62SZlNJ9H+De6Zebaw==
+ dependencies:
+ "@babel/helper-module-imports" "^7.10.1"
+ "@babel/helper-plugin-utils" "^7.10.1"
+ resolve "^1.8.1"
+ semver "^5.5.1"
+
"@babel/plugin-transform-shorthand-properties@^7.10.1":
version "7.10.1"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.1.tgz#e8b54f238a1ccbae482c4dce946180ae7b3143f3"
@@ -1051,7 +1061,15 @@
"@babel/helper-create-regexp-features-plugin" "^7.10.1"
"@babel/helper-plugin-utils" "^7.10.1"
-"@babel/preset-env@^7.4.5":
+"@babel/polyfill@^7.10.1":
+ version "7.10.1"
+ resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.10.1.tgz#d56d4c8be8dd6ec4dce2649474e9b707089f739f"
+ integrity sha512-TviueJ4PBW5p48ra8IMtLXVkDucrlOZAIZ+EXqS3Ot4eukHbWiqcn7DcqpA1k5PcKtmJ4Xl9xwdv6yQvvcA+3g==
+ dependencies:
+ core-js "^2.6.5"
+ regenerator-runtime "^0.13.4"
+
+"@babel/preset-env@^7.10.2", "@babel/preset-env@^7.4.5":
version "7.10.2"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.10.2.tgz#715930f2cf8573b0928005ee562bed52fb65fdfb"
integrity sha512-MjqhX0RZaEgK/KueRzh+3yPSk30oqDKJ5HP5tqTSB1e2gzGS3PLy7K0BIpnp78+0anFuSwOeuCf1zZO7RzRvEA==
@@ -1584,6 +1602,17 @@
dependencies:
"@babel/runtime" "^7.4.4"
+"@material-ui/lab@^4.0.0-alpha.55":
+ version "4.0.0-alpha.55"
+ resolved "https://registry.yarnpkg.com/@material-ui/lab/-/lab-4.0.0-alpha.55.tgz#82a850dc59654e04ee3a31be1b34eb3bf64d5585"
+ integrity sha512-mPHiS52Z1AT6NlWNp07xxTkoKGU3DZhoGdVtLKGy2+uMH5t4/UPtiZLRab7hR3hvuHvguxgV4tkBC9ww3xqUzA==
+ dependencies:
+ "@babel/runtime" "^7.4.4"
+ "@material-ui/utils" "^4.9.6"
+ clsx "^1.0.4"
+ prop-types "^15.7.2"
+ react-is "^16.8.0"
+
"@material-ui/styles@^4.10.0":
version "4.10.0"
resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.10.0.tgz#2406dc23aa358217aa8cc772e6237bd7f0544071"
@@ -2920,6 +2949,11 @@ arrify@^1.0.1:
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
+asap@~2.0.3:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
+ integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
+
asn1.js@^4.0.0:
version "4.10.1"
resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0"
@@ -3034,6 +3068,13 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e"
integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==
+axios@^0.19.2:
+ version "0.19.2"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
+ integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
+ dependencies:
+ follow-redirects "1.5.10"
+
axobject-query@^2.0.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.1.2.tgz#2bdffc0371e643e5f03ba99065d5179b9ca79799"
@@ -4163,6 +4204,11 @@ clone-deep@^4.0.1:
kind-of "^6.0.2"
shallow-clone "^3.0.0"
+clone@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
+ integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=
+
clsx@^1.0.4:
version "1.1.0"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.0.tgz#62937c6adfea771247c34b54d320fb99624f5702"
@@ -4409,7 +4455,7 @@ core-js-pure@^3.0.0, core-js-pure@^3.0.1:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
-core-js@^2.4.0:
+core-js@^2.4.0, core-js@^2.6.5:
version "2.6.11"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
@@ -4689,6 +4735,13 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.
dependencies:
ms "2.0.0"
+debug@=3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+ integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
+ dependencies:
+ ms "2.0.0"
+
debug@^3.0.0, debug@^3.1.1, debug@^3.2.5:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
@@ -5034,7 +5087,7 @@ dotenv-expand@^5.1.0:
resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0"
integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==
-dotenv-webpack@^1.7.0:
+dotenv-webpack@^1.7.0, dotenv-webpack@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/dotenv-webpack/-/dotenv-webpack-1.8.0.tgz#7ca79cef2497dd4079d43e81e0796bc9d0f68a5e"
integrity sha512-o8pq6NLBehtrqA8Jv8jFQNtG9nhRtVqmoD4yWbgUyoU3+9WBlPe+c2EAiaJok9RB28QvrWvdWLZGeTT5aATDMg==
@@ -5173,6 +5226,11 @@ enhanced-resolve@^4.1.0:
memory-fs "^0.5.0"
tapable "^1.0.0"
+enquire.js@^2.1.6:
+ version "2.1.6"
+ resolved "https://registry.yarnpkg.com/enquire.js/-/enquire.js-2.1.6.tgz#3e8780c9b8b835084c3f60e166dbc3c2a3c89814"
+ integrity sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ=
+
entities@^1.1.1, entities@^1.1.2, entities@~1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
@@ -5254,7 +5312,7 @@ enzyme@^3.11.0:
rst-selector-parser "^2.2.3"
string.prototype.trim "^1.2.1"
-errno@^0.1.3, errno@~0.1.7:
+errno@^0.1.1, errno@^0.1.3, errno@~0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==
@@ -5982,6 +6040,13 @@ focus-lock@^0.6.7:
resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.6.8.tgz#61985fadfa92f02f2ee1d90bc738efaf7f3c9f46"
integrity sha512-vkHTluRCoq9FcsrldC0ulQHiyBYgVJB2CX53I8r0nTC6KnEij7Of0jpBspjt3/CuNb6fyoj3aOh9J2HgQUM0og==
+follow-redirects@1.5.10:
+ version "1.5.10"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
+ integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
+ dependencies:
+ debug "=3.1.0"
+
follow-redirects@^1.0.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.11.0.tgz#afa14f08ba12a52963140fe43212658897bc0ecb"
@@ -6773,6 +6838,11 @@ ignore@^4.0.6:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
+image-size@~0.5.0:
+ version "0.5.5"
+ resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c"
+ integrity sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=
+
immer@1.10.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d"
@@ -7919,6 +7989,13 @@ json-stringify-safe@~5.0.1:
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
+json2mq@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/json2mq/-/json2mq-0.2.0.tgz#b637bd3ba9eabe122c83e9720483aeb10d2c904a"
+ integrity sha1-tje9O6nqvhIsg+lyBIOusQ0skEo=
+ dependencies:
+ string-convert "^0.2.0"
+
json3@^3.3.2:
version "3.3.3"
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81"
@@ -8120,6 +8197,33 @@ lcov-parse@0.0.10:
resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3"
integrity sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=
+less-loader@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-6.1.0.tgz#59fd591df408ced89a40fce11a2aea449b005631"
+ integrity sha512-/jLzOwLyqJ7Kt3xg5sHHkXtOyShWwFj410K9Si9WO+/h8rmYxxkSR0A3/hFEntWudE20zZnWMtpMYnLzqTVdUA==
+ dependencies:
+ clone "^2.1.2"
+ less "^3.11.1"
+ loader-utils "^2.0.0"
+ schema-utils "^2.6.6"
+
+less@^3.11.1:
+ version "3.11.3"
+ resolved "https://registry.yarnpkg.com/less/-/less-3.11.3.tgz#2d853954fcfe0169a8af869620bcaa16563dcc1c"
+ integrity sha512-VkZiTDdtNEzXA3LgjQiC3D7/ejleBPFVvq+aRI9mIj+Zhmif5TvFPM244bT4rzkvOCvJ9q4zAztok1M7Nygagw==
+ dependencies:
+ clone "^2.1.2"
+ tslib "^1.10.0"
+ optionalDependencies:
+ errno "^0.1.1"
+ graceful-fs "^4.1.2"
+ image-size "~0.5.0"
+ make-dir "^2.1.0"
+ mime "^1.4.1"
+ promise "^7.1.1"
+ request "^2.83.0"
+ source-map "~0.6.0"
+
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
@@ -8316,7 +8420,7 @@ lru-cache@^5.1.1:
dependencies:
yallist "^3.0.2"
-make-dir@^2.0.0:
+make-dir@^2.0.0, make-dir@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
@@ -8528,7 +8632,7 @@ mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
dependencies:
mime-db "1.44.0"
-mime@1.6.0:
+mime@1.6.0, mime@^1.4.1:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
@@ -9809,6 +9913,13 @@ promise.prototype.finally@^3.1.0:
es-abstract "^1.17.0-next.0"
function-bind "^1.1.1"
+promise@^7.1.1:
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
+ integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
+ dependencies:
+ asap "~2.0.3"
+
prompts@^2.0.1:
version "2.3.2"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.2.tgz#480572d89ecf39566d2bd3fe2c9fccb7c4c0b068"
@@ -10152,6 +10263,14 @@ react-lifecycles-compat@^3.0.4:
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
+react-loader-spinner@^3.1.14:
+ version "3.1.14"
+ resolved "https://registry.yarnpkg.com/react-loader-spinner/-/react-loader-spinner-3.1.14.tgz#2a201f07379c492766175609903c0f2ced57c720"
+ integrity sha512-7V+upnW+RVA/O94LIB/EQLK2uaz/TpZBHG5uNXlOXgvxvALxlxVYeEDmus5Oex2C58fiwrsRvSyu/4VRmLbZ9Q==
+ dependencies:
+ babel-runtime "^6.26.0"
+ prop-types "^15.7.2"
+
react-popper-tooltip@^2.8.3:
version "2.11.1"
resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-2.11.1.tgz#3c4bdfd8bc10d1c2b9a162e859bab8958f5b2644"
@@ -10223,6 +10342,17 @@ react-sizeme@^2.6.7:
shallowequal "^1.1.0"
throttle-debounce "^2.1.0"
+react-slick@^0.26.1:
+ version "0.26.1"
+ resolved "https://registry.yarnpkg.com/react-slick/-/react-slick-0.26.1.tgz#42d6b9bfdf3a16e4e4609a6c6536957f8acde7d9"
+ integrity sha512-IQVRSkikG2w5bkz+m9Ing5zZIuM9cI+qJyXG2o6PXHKj8GFcsMCJoTBADwyLSsVT8dHcZ8MZ0dsxq0i0CKIq+Q==
+ dependencies:
+ classnames "^2.2.5"
+ enquire.js "^2.1.6"
+ json2mq "^0.2.0"
+ lodash.debounce "^4.0.8"
+ resize-observer-polyfill "^1.5.0"
+
react-syntax-highlighter@^11.0.2:
version "11.0.2"
resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-11.0.2.tgz#4e3f376e752b20d2f54e4c55652fd663149e4029"
@@ -10562,7 +10692,7 @@ request-promise-native@^1.0.8:
stealthy-require "^1.1.1"
tough-cookie "^2.3.3"
-request@^2.87.0, request@^2.88.0, request@^2.88.2, request@~2.88.0:
+request@^2.83.0, request@^2.87.0, request@^2.88.0, request@^2.88.2, request@~2.88.0:
version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
@@ -10603,7 +10733,7 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
-resize-observer-polyfill@^1.5.1:
+resize-observer-polyfill@^1.5.0, resize-observer-polyfill@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
@@ -10655,7 +10785,7 @@ resolve-url@^0.2.1:
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
-resolve@^1.1.6, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.17.0, resolve@^1.3.2:
+resolve@^1.1.6, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.8.1:
version "1.17.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444"
integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==
@@ -10890,7 +11020,7 @@ selfsigned@^1.10.7:
dependencies:
node-forge "0.9.0"
-"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1:
+"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
@@ -11145,6 +11275,11 @@ slice-ansi@^2.1.0:
astral-regex "^1.0.0"
is-fullwidth-code-point "^2.0.0"
+slick-carousel@^1.8.1:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/slick-carousel/-/slick-carousel-1.8.1.tgz#a4bfb29014887bb66ce528b90bd0cda262cc8f8d"
+ integrity sha512-XB9Ftrf2EEKfzoQXt3Nitrt/IPbT+f1fgqBdoxO3W/+JYvtEOW6EgxnWfr9GH6nmULv7Y2tPmEX3koxThVmebA==
+
snapdragon-node@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
@@ -11429,6 +11564,11 @@ strict-uri-encode@^1.0.0:
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
+string-convert@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97"
+ integrity sha1-aYLMMEn7tM2F+LJFaLnZvznu/5c=
+
string-length@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1"