Fix for loading

This commit is contained in:
Senad Uka
2019-07-25 06:53:32 +02:00
parent a691ab94c7
commit 2db47e95e1
26 changed files with 838 additions and 400 deletions

View File

@@ -0,0 +1,53 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Button, Modal } from 'semantic-ui-react';
import { addFeesToOrd } from '../../store/actions';
class GenerateFeesInORDButton extends Component {
state = { open: false };
show = size => () => this.setState({ size, open: true });
close = () => this.setState({ open: false });
confirm = () => {
const { addFeesToOrd, dateRange, memberIds } = this.props;
if (dateRange){
addFeesToOrd(dateRange, memberIds);
}
this.close();
};
render() {
const { open, size } = this.state;
const { singleMember, disabled } = this.props;
const modalContent = singleMember ?
'This will remove all existing fees in ORD for selected member in selected date range and generate new fees based on shown incident tables. Do you want to continue ?':
'This will remove all existing fees in ORD for all members in selected date range and generate new fees based on shown incident tables. Do you want to continue ?';
return (
<div>
<Button disabled={disabled} onClick={this.show('tiny')}>Generate fees in ORD</Button>
<Modal size={size} open={open} onClose={this.close}>
<Modal.Header>Add fees to the ORD</Modal.Header>
<Modal.Content>
<p>{modalContent}</p>
</Modal.Content>
<Modal.Actions>
<Button negative onClick={this.close}>No</Button>
<Button positive icon='checkmark' onClick={this.confirm} labelPosition='right' content='Yes' />
</Modal.Actions>
</Modal>
</div>
);
}
}
const mapDispatchToProps = (dispatch) => ({
addFeesToOrd: (dateRange, memberIds) => addFeesToOrd(dispatch, dateRange, memberIds),
});
export default connect(null, mapDispatchToProps)(GenerateFeesInORDButton);

View File

@@ -1,111 +0,0 @@
import React from 'react';
import { Loader } from 'semantic-ui-react';
import ReactTable from 'react-table';
import 'react-table/react-table.css';
import { NavLink } from 'react-router-dom';
import {incidentsReportHeaderTitles} from '../../constants/menuItems';
import {
incidentDescriptions,
incidentLevelDescriptions,
UNLOCKED_INCIDENT,
UNSCHEDULED_INCIDENT
} from '../../constants/enums';
const MemberIncidentsTable = props => {
const { loading, title, openMemberSummaryOnMemberClick } = props;
const incidents = props.incidents ? props.incidents : [];
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 = '';
let urlValue = undefined;
switch (props.column.id) {
case 'memberName':
const memberId = props.row['_original'].memberId;
urlValue = `/practice-summary-report/${memberId}`;
cellValue = props.value;
break;
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;
default:
cellValue = '';
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;
}
if (openMemberSummaryOnMemberClick && urlValue){
return <NavLink to={urlValue}>{cellValue}</NavLink>
}else{
return <div style={{ textAlign: columnContentsAlignment }}>{cellValue}</div>
}
// return <NavLink to={urlValue}>
// <div>{cellValue}</div>
// </NavLink>
// return <div style={{ textAlign: columnContentsAlignment }}><a href={'www.gogole.com'} >{cellValue}</a></div>
}
});
}
});
}
return (
<div>
<h4>{title}</h4>
<Loader active={loading} />
{
!loading && incidents &&
<ReactTable
data={incidents}
multiSort={false}
columns={columns}
/>
}
</div>
);
};
export default MemberIncidentsTable;

View File

@@ -5,26 +5,50 @@ import { Container } from 'semantic-ui-react';
import MainMenu from '../../components/MainMenu';
import DateRangePicker from '../../components/DateRangePicker';
import MemberIncidentsTables from '../../components/MemberIncidentsTables';
import GenerateFeesInORDButton from '../../components/GenerateFeesInORDButton';
import { fetchIncidents } from '../../store/actions';
import { fetchIncidents, addFeesToOrd } from '../../store/actions';
class IncidentsReport extends Component {
onDatesUpdate(dateRange) {
state = {dateRange: null};
onDatesUpdate = (dateRange) => {
const { fetchIncidents } = this.props;
this.setState({dateRange});
fetchIncidents(dateRange);
}
};
render () {
const { pendingIncidents, incidents } = this.props;
const { pendingIncidents, incidents, pendingAddFeesStatus } = this.props;
const { dateRange } = this.state;
const loading = pendingIncidents || pendingAddFeesStatus;
const membersMap = {};
if (incidents && Array.isArray(incidents)) {
incidents.forEach((incident) => {
membersMap[incident.memberId] = true;
});
}
const memberIds = Object.keys(membersMap) || [];
return (
<Container>
<MainMenu/>
<h3>Incidents Report</h3>
<hr/>
<DateRangePicker buttonLabel="Show report" onDatesUpdate={this.onDatesUpdate.bind(this)} />
<DateRangePicker buttonLabel="Show report" onDatesUpdate={this.onDatesUpdate} inlineButton />
<br/>
<MemberIncidentsTables pendingIncidents={pendingIncidents} incidents={incidents} />
<GenerateFeesInORDButton
memberIds={memberIds}
disabled={loading}
dateRange={dateRange}
/>
<br/><br/>
<hr/>
<br/>
<MemberIncidentsTables pendingIncidents={loading} incidents={incidents} />
</Container>
);
}
@@ -33,10 +57,12 @@ class IncidentsReport extends Component {
const mapStateToProps = (state) => ({
pendingIncidents: state.incidentsReport.pending,
incidents: state.incidentsReport.result,
pendingAddFeesStatus: state.addFeesStatus.pending,
});
const mapDispatchToProps = (dispatch) => ({
fetchIncidents: (dateRange) => fetchIncidents(dispatch, dateRange),
addFeesToOrd: (dateRange, memberIds) => addFeesToOrd(dispatch, dateRange, memberIds),
});
export default connect(mapStateToProps, mapDispatchToProps)(IncidentsReport);

View File

@@ -1,12 +1,13 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {Container, Grid} from 'semantic-ui-react';
import { Container, Grid } from 'semantic-ui-react';
import MainMenu from '../../components/MainMenu';
import DateRangePicker from '../../components/DateRangePicker';
import MemberSelector from './components/MemberSelector';
import MemberSummary from './components/MemberSummary';
import MemberIncidentsTables from '../../components/MemberIncidentsTables';
import GenerateFeesInORDButton from '../../components/GenerateFeesInORDButton';
import { fetchMemberIncidents } from '../../store/actions';
@@ -39,8 +40,12 @@ class PracticeSummaryReport extends Component {
}
render () {
const { memberIncidents, loading } = this.props;
const { memberId } = this.state;
const { memberIncidents, loadingMemberIncidents, loadingAddFeesStatus } = this.props;
const { memberId, dateRange } = this.state;
const loading = loadingAddFeesStatus || loadingMemberIncidents;
const addFeesButtonDisabled = !memberId || !dateRange || loading;
return (
<Container>
@@ -64,6 +69,16 @@ class PracticeSummaryReport extends Component {
/>
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Grid.Column>
<GenerateFeesInORDButton
singleMember
disabled={addFeesButtonDisabled}
dateRange={dateRange}
memberIds={[memberId]}
/>
</Grid.Column>
</Grid.Row>
<Grid.Row/>
<Grid.Row>
<Grid.Column>
@@ -78,7 +93,8 @@ class PracticeSummaryReport extends Component {
const mapStateToProps = (state) => ({
memberIncidents: state.memberIncidents.result,
loading: state.memberIncidents.pending,
loadingMemberIncidents: state.memberIncidents.pending,
loadingAddFeesStatus: state.addFeesStatus.pending,
});
const mapDispatchToProps = (dispatch) => ({

View File

@@ -14,6 +14,9 @@ import {
FETCH_MEMBER_INCIDENTS_PENDING,
FETCH_MEMBER_INCIDENTS_SUCCESS,
FETCH_MEMBER_INCIDENTS_FAILED,
ADD_FEES_TO_ORD_PENDING,
ADD_FEES_TO_ORD_SUCCESS,
ADD_FEES_TO_ORD_FAILED,
} from '../constants';
import API from '../../utilities/api';
@@ -78,3 +81,17 @@ export const fetchMemberIncidents = (dispatch, memberId, dateRange) => {
dispatch({type: FETCH_MEMBER_INCIDENTS_FAILED, payload: error.response});
});
};
export const addFeesToOrd = (dispatch, dateRange, memberIds) => {
dispatch({type: ADD_FEES_TO_ORD_PENDING});
API.post(`integration/addFees`, {
dateRange,
memberIds: memberIds || [],
})
.then(response => {
dispatch({type: ADD_FEES_TO_ORD_SUCCESS, payload: response.data});
})
.catch(error => {
dispatch({type: ADD_FEES_TO_ORD_FAILED, payload: error.response});
});
};

View File

@@ -21,3 +21,7 @@ export const FETCH_MEMBERS_FAILED = 'FETCH_MEMBERS_FAILED';
export const FETCH_MEMBER_INCIDENTS_PENDING = 'FETCH_MEMBER_INCIDENTS_PENDING';
export const FETCH_MEMBER_INCIDENTS_SUCCESS = 'FETCH_MEMBER_INCIDENTS_SUCCESS';
export const FETCH_MEMBER_INCIDENTS_FAILED = 'FETCH_MEMBER_INCIDENTS_FAILED';
export const ADD_FEES_TO_ORD_PENDING = 'ADD_FEES_TO_ORD_PENDING';
export const ADD_FEES_TO_ORD_SUCCESS = 'ADD_FEES_TO_ORD_SUCCESS';
export const ADD_FEES_TO_ORD_FAILED = 'ADD_FEES_TO_ORD_FAILED';

View File

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

View File

@@ -6,6 +6,7 @@ import { addMapping } from './addMappingReducer';
import { incidentsReport } from './incidentsReportReducer';
import { membersList } from './membersListReducer';
import { memberIncidents} from './memberIncidentsReducer';
import { addFeesStatus } from './addFeesToOrdReducer';
export const rootReducer = combineReducers({
doorLockData,
@@ -14,5 +15,6 @@ export const rootReducer = combineReducers({
incidentsReport,
membersList,
memberIncidents,
addFeesStatus,
});