Show incident report (without filtering for now)

This commit is contained in:
Senad Uka
2019-06-17 13:24:34 +02:00
parent 393e9b8aec
commit 9a8d95dd19
27 changed files with 400 additions and 51 deletions

View File

@@ -10,6 +10,7 @@
"react-redux": "^7.0.3",
"react-router-dom": "^5.0.0",
"react-scripts": "3.0.1",
"react-table": "^6.10.0",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"semantic-ui-css": "^2.4.1",

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { NavLink } from 'react-router-dom';
import { Menu } from 'semantic-ui-react';
import { mainMenuItems } from "../../constants/menuItems";
import { mainMenuItems } from '../../constants/menuItems';
const MainMenu = () =>
(<Menu>

View File

@@ -0,0 +1,17 @@
export const UNLOCKED_INCIDENT = 2;
export const UNSCHEDULED_INCIDENT = 3;
export const incidentDescriptions = {};
incidentDescriptions[UNLOCKED_INCIDENT] = 'User left door unlocked';
incidentDescriptions[UNSCHEDULED_INCIDENT] = 'Unscheduled use';
export const incidentLevelDescriptions = {
UNLOCKED_0: 'First month',
UNLOCKED_1: 'Second month',
UNLOCKED_2: 'Third month',
UNLOCKED_3: 'Fourth month',
UNLOCKED_4: 'Fifth month',
UNLOCKED_5: 'Sixth month',
};

View File

@@ -1,5 +1,6 @@
import UploadDLockData from "../scenes/UploadDLockData";
import Home from "../scenes/Home";
import UploadDLockData from '../scenes/UploadDLockData';
import Home from '../scenes/Home';
import IncidentsReport from '../scenes/IncidentsReport';
export const mainMenuItems = [
{
@@ -8,6 +9,12 @@ export const mainMenuItems = [
url: '/',
component: Home,
},
{
id: 'report',
title: 'Incidents Report',
url: '/incidents-report',
component: IncidentsReport,
},
{
id: 'uploadDLockData',
title: 'DLock',
@@ -15,3 +22,14 @@ export const mainMenuItems = [
component: UploadDLockData,
},
];
export const incidentsReportHeaderTitles = {
officeName: 'Office',
resourceName: 'Room',
bookingStart: 'Reservation Start',
bookingEnd: 'Reservation End',
memberName: 'Member Name',
incidentType: 'Incident Type',
feeDescription: 'Fee description',
totalChargeFee: 'Total Fee',
};

View File

@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import { Container, Form } from "semantic-ui-react";
import { Container, Form } from 'semantic-ui-react';
import MainMenu from '../../components/MainMenu';

View File

@@ -0,0 +1,108 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Container, Loader } from 'semantic-ui-react';
import ReactTable from 'react-table';
import 'react-table/react-table.css';
import MainMenu from '../../components/MainMenu';
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() {
const { fetchIncidents } = this.props;
fetchIncidents();
}
render () {
const { pendingIncidents, incidents } = this.props;
const columns = [];
if (incidents && incidents.length > 0){
const incidentHeaders = Object.keys(incidentsReportHeaderTitles);
incidentHeaders.forEach((header) => {
const columnTitle = incidentsReportHeaderTitles[header];
if (columnTitle){
const columnAlignments = {
left: 'left',
right: 'right',
};
let columnContentsAlignment = columnAlignments.left;
columns.push({
Header: incidentsReportHeaderTitles[header],
accessor: header,
Cell: props => {
let cellValue;
switch (props.column.id) {
case 'incidentType':
cellValue = incidentDescriptions[props.value];
break;
case 'incidentLevel':
cellValue = incidentLevelDescriptions[props.value];
break;
case 'feeDescription':
const { incidentType, incidentLevel, timeIntervalsToCharge } = props.row['_original'];
switch (incidentType) {
case UNLOCKED_INCIDENT:
cellValue = `${incidentLevelDescriptions[incidentLevel]}`;
break;
case UNSCHEDULED_INCIDENT:
cellValue = `${timeIntervalsToCharge} x 5 min`;
break;
}
break;
case 'totalChargeFee':
const totalFee = props.value ? props.value : props.row['_original'].incidentPrice;
const totalFeeFormatted = parseFloat(totalFee).toFixed(2);
cellValue = `$ ${totalFeeFormatted}`;
columnContentsAlignment = columnAlignments.right;
break;
default:
cellValue = props.value;
}
return <div style={{ textAlign: columnContentsAlignment }}>{cellValue}</div>
}
});
}
});
}
return (
<Container>
<MainMenu/>
<h3>Incidents Report</h3>
<hr/>
<Loader active={pendingIncidents} />
{
!pendingIncidents && incidents &&
<ReactTable
data={incidents}
multiSort={false}
columns={columns}
/>
}
</Container>
);
}
}
const mapStateToProps = (state) => ({
pendingIncidents: state.incidentsReport.pending,
incidents: state.incidentsReport.result,
});
const mapDispatchToProps = (dispatch) => ({
fetchIncidents: () => fetchIncidents(dispatch),
});
export default connect(mapStateToProps, mapDispatchToProps)(IncidentsReport);

View File

@@ -1,5 +1,5 @@
import React from 'react';
import MainMenu from "../../components/MainMenu";
import MainMenu from '../../components/MainMenu';
export default function NotFound () {
return (

View File

@@ -1,10 +1,10 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Form } from "semantic-ui-react";
import { Form } from 'semantic-ui-react';
import UnknownMapping from './UnknownMapping';
import { uploadDoorLockData, fetchMappings } from "../../../store/actions";
import { uploadDoorLockData, fetchMappings } from '../../../store/actions';
class FileUpload extends Component {
constructor(props) {

View File

@@ -1,8 +1,8 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {Button, Dropdown, Message} from "semantic-ui-react";
import {Button, Dropdown, Message} from 'semantic-ui-react';
import Fuse from 'fuse.js';
import { addNewMapping } from "../../../store/actions";
import { addNewMapping } from '../../../store/actions';
class UnknownMapping extends Component {
constructor(props) {

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Container, Form } from "semantic-ui-react";
import { Container, Form } from 'semantic-ui-react';
import MainMenu from '../../components/MainMenu';
import FileUpload from './components/FileUpload';

View File

@@ -2,7 +2,7 @@ import {
UPLOAD_DOOR_LOCK_DATA_PENDING,
UPLOAD_DOOR_LOCK_DATA_SUCCESS,
UPLOAD_DOOR_LOCK_DATA_FAILED
} from "../constants";
} from '../constants';
import API from '../../utilities/api';

View File

@@ -5,7 +5,10 @@ import {
ADD_NEW_MAPPING_PENDING,
ADD_NEW_MAPPING_SUCCESS,
ADD_NEW_MAPPING_FAILED,
} from "../constants";
FETCH_INCIDENTS_PENDING,
FETCH_INCIDENTS_SUCCESS,
FETCH_INCIDENTS_FAILED,
} from '../constants';
import API from '../../utilities/api';
@@ -32,3 +35,14 @@ export const addNewMapping = (dispatch, mapping) => {
dispatch({type: ADD_NEW_MAPPING_FAILED, payload: error.response});
});
};
export const fetchIncidents = (dispatch) => {
dispatch({type: FETCH_INCIDENTS_PENDING});
API.get('integration/report/allIncidents')
.then(response => {
dispatch({type: FETCH_INCIDENTS_SUCCESS, payload: response.data});
})
.catch(error => {
dispatch({type: FETCH_INCIDENTS_FAILED, payload: error.response});
});
};

View File

@@ -9,3 +9,7 @@ export const FETCH_MAPPINGS_FAILED = 'FETCH_MAPPINGS_FAILED';
export const ADD_NEW_MAPPING_PENDING = 'ADD_NEW_MAPPING_PENDING';
export const ADD_NEW_MAPPING_SUCCESS = 'ADD_NEW_MAPPING_SUCCESS';
export const ADD_NEW_MAPPING_FAILED = 'ADD_NEW_MAPPING_FAILED';
export const FETCH_INCIDENTS_PENDING = 'FETCH_INCIDENTS_PENDING';
export const FETCH_INCIDENTS_SUCCESS = 'FETCH_INCIDENTS_SUCCESS';
export const FETCH_INCIDENTS_FAILED = 'FETCH_INCIDENTS_FAILED';

View File

@@ -2,7 +2,7 @@ import {
ADD_NEW_MAPPING_PENDING,
ADD_NEW_MAPPING_SUCCESS,
ADD_NEW_MAPPING_FAILED,
} from "../constants";
} from '../constants';
const initialState = {
pending: false,

View File

@@ -2,7 +2,7 @@ import {
UPLOAD_DOOR_LOCK_DATA_PENDING,
UPLOAD_DOOR_LOCK_DATA_SUCCESS,
UPLOAD_DOOR_LOCK_DATA_FAILED
} from "../constants";
} from '../constants';
const initialState = {
pending: false,

View File

@@ -0,0 +1,38 @@
import {
FETCH_INCIDENTS_PENDING,
FETCH_INCIDENTS_SUCCESS,
FETCH_INCIDENTS_FAILED,
} from '../constants';
const initialState = {
pending: false,
result: null,
error: null,
};
export const incidentsReport = (state, action) => {
state = state || initialState;
action = action || {};
switch(action.type){
case FETCH_INCIDENTS_PENDING:
return Object.assign({}, state, {
pending: true,
error: null,
});
case FETCH_INCIDENTS_SUCCESS:
return Object.assign({}, state, {
pending: false,
result: action.payload,
error: null,
});
case FETCH_INCIDENTS_FAILED:
return Object.assign({}, state, {
pending: false,
result: {},
error: action.payload,
});
default:
return state;
}
};

View File

@@ -1,12 +1,14 @@
import { combineReducers } from "redux";
import { combineReducers } from 'redux';
import { doorLockData} from "./doorLockReducers";
import { mappingsData } from "./mappingsReducer";
import { doorLockData} from './doorLockReducers';
import { mappingsData } from './mappingsReducer';
import { addMapping } from './addMappingReducer';
import { incidentsReport } from './incidentsReportReducer';
export const rootReducer = combineReducers({
doorLockData,
mappingsData,
addMapping,
incidentsReport,
});

View File

@@ -2,7 +2,7 @@ import {
FETCH_MAPPINGS_PENDING,
FETCH_MAPPINGS_SUCCESS,
FETCH_MAPPINGS_FAILED,
} from "../constants";
} from '../constants';
const initialState = {
pending: false,

View File

@@ -2140,7 +2140,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
classnames@^2.2.6:
classnames@^2.2.5, classnames@^2.2.6:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
@@ -7095,6 +7095,12 @@ react-scripts@3.0.1:
optionalDependencies:
fsevents "2.0.6"
react-table@^6.10.0:
version "6.10.0"
resolved "https://registry.yarnpkg.com/react-table/-/react-table-6.10.0.tgz#20444b19d8ca3c1a08e7544e5c3a93e4ba56690e"
dependencies:
classnames "^2.2.5"
react@^16.8.6:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"