diff --git a/client/package.json b/client/package.json
index 26300b5..4aa04dc 100644
--- a/client/package.json
+++ b/client/package.json
@@ -5,6 +5,7 @@
"dependencies": {
"axios": "^0.18.0",
"fuse.js": "^3.4.5",
+ "moment": "^2.24.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-redux": "^7.0.3",
diff --git a/client/src/components/DateRangePicker/index.js b/client/src/components/DateRangePicker/index.js
new file mode 100644
index 0000000..442a700
--- /dev/null
+++ b/client/src/components/DateRangePicker/index.js
@@ -0,0 +1,114 @@
+import React, { Component } from 'react';
+import moment from 'moment';
+
+import { Form, Message } from 'semantic-ui-react';
+
+import { defaultDateFormat } from '../../constants/constants';
+
+class DateRangePicker extends Component {
+ constructor(props) {
+ super(props);
+
+ const initialStartDate = props.startDate ? moment(props.startDate, defaultDateFormat) : moment().startOf('month');
+ let initialEndDate = props.endDate ? moment(props.endDate, defaultDateFormat) : moment();
+
+ if (initialStartDate > initialEndDate){
+ initialEndDate = initialStartDate.add(1, 'day');
+ }
+
+ this.state = {
+ startDate: initialStartDate,
+ endDate: initialEndDate,
+ error: null,
+ startDateLabel: props.startDateLabel || 'Start date',
+ endDateLabel: props.endDateLabel || 'End date',
+ };
+ }
+
+ onStartDateChange(event) {
+ const { endDate, startDateLabel, endDateLabel } = this.state;
+
+ const newStartDate = moment(event.target.value, defaultDateFormat);
+ if (newStartDate > endDate){
+ this.setState({
+ error: `${startDateLabel} cannot be after ${endDateLabel}`
+ });
+ return;
+ }
+ this.setState({startDate: newStartDate, error: null});
+ }
+
+ onEndDateChange(event) {
+ const { startDate, startDateLabel, endDateLabel } = this.state;
+
+ const newEndDate = moment(event.target.value, defaultDateFormat);
+ if (newEndDate < startDate){
+ this.setState({
+ error: `${startDateLabel} cannot be after ${endDateLabel}`
+ });
+ return;
+ }
+ this.setState({endDate: newEndDate, error: null});
+ }
+
+ onDismiss() {
+ this.setState({error: null});
+ }
+
+ onButtonClick() {
+ const { onDatesUpdate } = this.props;
+ const { startDate, endDate } = this.state;
+
+ if (onDatesUpdate){
+ onDatesUpdate({
+ startDate: startDate.format(defaultDateFormat),
+ endDate: endDate.format(defaultDateFormat),
+ });
+ }
+ }
+
+ componentDidMount() {
+ this.onButtonClick();
+ }
+
+ render() {
+ const { startDate, endDate, error, startDateLabel, endDateLabel } = this.state;
+
+ const buttonLabel = this.props.buttonLabel || 'Save';
+
+ const startDateValue = startDate.format(defaultDateFormat);
+ const endDateValue = endDate.format(defaultDateFormat);
+
+ return (
+
+
+
+
+ { error &&
+
+ Wrong date
+ {startDateLabel} has to be before {endDateLabel}
+
+ }
+ {buttonLabel}
+
+ );
+ }
+}
+
+export default DateRangePicker;
diff --git a/client/src/constants/constants.js b/client/src/constants/constants.js
new file mode 100644
index 0000000..ed5633b
--- /dev/null
+++ b/client/src/constants/constants.js
@@ -0,0 +1 @@
+export const defaultDateFormat = 'YYYY-MM-DD';
diff --git a/client/src/scenes/IncidentsReport/index.js b/client/src/scenes/IncidentsReport/index.js
index 09a76cb..d12cd01 100644
--- a/client/src/scenes/IncidentsReport/index.js
+++ b/client/src/scenes/IncidentsReport/index.js
@@ -1,19 +1,20 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
-import { Container, Loader } from 'semantic-ui-react';
+import {Container, Loader} from 'semantic-ui-react';
import ReactTable from 'react-table';
import 'react-table/react-table.css';
import MainMenu from '../../components/MainMenu';
+import DateRangePicker from '../../components/DateRangePicker';
+
import { fetchIncidents } from '../../store/actions';
import { incidentsReportHeaderTitles } from '../../constants/menuItems';
import { incidentDescriptions, incidentLevelDescriptions, UNSCHEDULED_INCIDENT, UNLOCKED_INCIDENT } from '../../constants/enums';
class IncidentsReport extends Component {
-
- componentDidMount() {
+ onDatesUpdate(dateRange) {
const { fetchIncidents } = this.props;
- fetchIncidents();
+ fetchIncidents(dateRange);
}
render () {
@@ -56,6 +57,9 @@ class IncidentsReport extends Component {
case UNSCHEDULED_INCIDENT:
cellValue = `${timeIntervalsToCharge} x 5 min`;
break;
+ default:
+ cellValue = '';
+ break;
}
break;
@@ -82,6 +86,8 @@ class IncidentsReport extends Component {
Incidents Report
+
+
{
!pendingIncidents && incidents &&
diff --git a/client/src/store/actions/integrationActions.js b/client/src/store/actions/integrationActions.js
index 599573f..395186f 100644
--- a/client/src/store/actions/integrationActions.js
+++ b/client/src/store/actions/integrationActions.js
@@ -36,9 +36,11 @@ export const addNewMapping = (dispatch, mapping) => {
});
};
-export const fetchIncidents = (dispatch) => {
+export const fetchIncidents = (dispatch, dateRange) => {
dispatch({type: FETCH_INCIDENTS_PENDING});
- API.get('integration/report/allIncidents')
+ API.get('integration/report/allIncidents', {
+ dateRange
+ })
.then(response => {
dispatch({type: FETCH_INCIDENTS_SUCCESS, payload: response.data});
})
diff --git a/client/yarn.lock b/client/yarn.lock
index dd8a44d..caa1ce2 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -5478,6 +5478,10 @@ mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@
dependencies:
minimist "0.0.8"
+moment@^2.24.0:
+ version "2.24.0"
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
+
move-concurrently@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"