packages/optimise-ui/src/components/medicalData/visitDataPage.jsx
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import { alterDataCall } from '../../redux/actions/addOrUpdateData';
import { createLevelObj, mappingFields, BackButton, checkIfObjIsEmpty } from './utils';
import Icon from '../icon';
import _scaffold_style from '../createMedicalElements/medicalEvent.module.css';
import style from './dataPage.module.css';
import store from '../../redux/store';
function mapStateToProps(state) {
return {
fields: state.availableFields,
patientProfile: state.patientProfile
};
}
/**
* @class DataTemplate
* @description Renders the data page for test / visit / treatment / event data
* @prop {String} this.props.elementType - 'test', 'visit', 'treatment', 'clinicalEvent'
* @prop {Object} this.props.match - from router
* @prop {Object} this.props.fields - from store
* @prop {Object} this.props.patientProfile - from store
* @prop {Function} this.props.submitData - from connect
*/
/* this component serves as a sieve for the data and pass the relevant one to the form as props*/
@withRouter
@connect(mapStateToProps)
class VisitData extends Component {
constructor(props) {
super();
const { childRef } = props;
if (childRef) {
childRef(this);
}
this.state = {
saved: false
};
this.references = null;
this.originalValues = {};
this._handleSubmit = this._handleSubmit.bind(this);
}
static getDerivedStateFromProps(props, state) {
if (props.match.url === state.vdPath)
return state;
return {
...state,
vdPath: props.match.url,
refreshReferences: true
};
}
componentDidUpdate() {
if (this.state.refreshReferences === true) {
this.references = null;
this.setState({
refreshReferences: false
});
}
}
_handleSubmit(ev) {
ev.preventDefault();
if (this.state.lastSubmit && (new Date()).getTime() - this.state.lastSubmit < 500 ? true : false)
return;
const { references, originalValues } = this;
if (references === null)
return;
const update = {};
const add = {};
Object.entries(references).forEach(el => {
const fieldId = el[0];
const reference = el[1].ref;
const type = el[1].type;
if (type === 'C' && (originalValues[fieldId] !== undefined || reference.current.value !== 'unselected')) {
if (originalValues[fieldId] !== undefined) {
if (originalValues[fieldId] !== reference.current.value)
update[fieldId] = reference.current.value;
} else if (reference.current.value !== 'unselected') {
add[fieldId] = reference.current.value;
}
}
if (['I', 'F', 'T'].includes(type) && (originalValues[fieldId] !== undefined || reference.current.value !== '' || reference.current.value !== undefined)) {
if (originalValues[fieldId] !== undefined) {
if (originalValues[fieldId] !== reference.current.value)
update[fieldId] = reference.current.value;
} else if (reference.current.value !== '') {
add[fieldId] = reference.current.value;
}
}
if (type === 'B') {
const bool = reference.current.checked ? '1' : '0';
if (originalValues[fieldId] !== undefined) {
if (originalValues[fieldId] !== bool)
update[fieldId] = bool;
} else if (bool !== '0') {
add[fieldId] = bool;
}
}
});
const { params } = this.props.match;
if (checkIfObjIsEmpty(update, add)) {
this.setState({ saved: true });
return;
}
const body = { data: { visitId: params.visitId, update, add }, type: 'visit', patientId: params.patientId };
this.setState({
lastSubmit: (new Date()).getTime()
}, () => {
store.dispatch(alterDataCall(body, () => {
this.originalValues = Object.assign({}, this.originalValues, add);
this.setState({ saved: true });
}));
});
}
render() {
let scaffold_style = _scaffold_style;
if (this.props.override_style) {
scaffold_style = { ..._scaffold_style, ...this.props.override_style };
}
const { patientProfile, match } = this.props;
const { params } = match;
if (!patientProfile.fetching) {
const visitsMatched = patientProfile.data.visits.filter(visit => visit.id === parseInt(params.visitId, 10));
if (visitsMatched.length !== 1) {
return <>
<div className={scaffold_style.ariane}>
<h2>Edit {this.props.category.toUpperCase()}</h2>
<BackButton to={`/patientProfile/${match.params.patientId}`} />
</div>
<div className={scaffold_style.panel}>
<i>We could not find the visit that you are looking for.</i>
</div>
</>;
}
const { fields } = this.props;
const category = this.props.category === 'symptoms' ? 2 : this.props.category === 'signs' ? 3 : 1;
let relevantFields = fields.visitFields.filter(el => (el.referenceType === visitsMatched[0].type && el.section === category));
let academicConcernField = relevantFields.filter(el => el.idname === 'Special Educational Needs:yes_or_no');
let academicConcernCommentField = relevantFields.filter(el => el.idname === 'Special Educational Needs:comment');
relevantFields = relevantFields.filter(el => el.idname !== 'Special Educational Needs:yes_or_no' && el.idname !== 'Special Educational Needs:comment');
if (new Date().getTime() - parseInt(patientProfile.data.demographicData.DOB) < 568025136000) {
relevantFields = [...relevantFields, ...academicConcernField, ...academicConcernCommentField];
}
const fieldTree = createLevelObj(relevantFields);
const inputTypeHash = fields.inputTypes.reduce((a, el) => { a[el.id] = el.value; return a; }, {});
this.originalValues = visitsMatched[0].data.reduce((a, el) => { a[el.field] = el.value; return a; }, {});
if (this.references !== null && this.state.refreshReferences === true)
return null;
if (this.references === null)
this.references = relevantFields.reduce((a, el) => { a[el.id] = { ref: React.createRef(), type: inputTypeHash[el.type] }; return a; }, {});
return (
<>
<div className={scaffold_style.ariane}>
<h2>Edit {this.props.category.toUpperCase()}</h2>
<BackButton to={`/patientProfile/${match.params.patientId}`} />
</div>
<div className={`${scaffold_style.panel} ${style.topLevelPanel}`}>
<form className={style.form}>
<div className={style.levelBody}>
{Object.entries(fieldTree).map(mappingFields(inputTypeHash, this.references, this.originalValues))}
</div>
{ this.state.saved ? <><button disabled style={{ cursor: 'default', backgroundColor: 'green' }}>Successfully saved!</button><br/></> : null }
{
this.props.renderedInFrontPage
?
null
:
<button onClick={this._handleSubmit} type='submit'>Save</button>
}
</form>
</div>
</>
);
} else {
return <div><Icon symbol='loading' /></div>;
}
}
}
export {VisitData};