diff --git a/app/components/ClinicUserEdit.js b/app/components/ClinicUserEdit.js index e1145d488..276ffb3d1 100644 --- a/app/components/ClinicUserEdit.js +++ b/app/components/ClinicUserEdit.js @@ -52,6 +52,36 @@ function validateForm(values, props){ if(mrnRequired && !values.mrn){ errors.mrn = i18n.t('Patient\'s MRN is required'); } + // mrn needs to be uppercase alphanumeric between 6 and 25 characters + if(values.mrn && !/^[A-Z0-9]{6,25}$/.test(values.mrn)){ + errors.mrn = ( +
+ {i18n.t('Patient’s MRN is invalid. MRN must meet the following criteria:')} + +
+ ); + } + // mrn needs to be unique + if (values.mrn && props.selectedClinicId) { + var { targetId } = props; + var patients = _.get( + props.clinics, + [props.selectedClinicId, 'patients'], + {} + ); + var filteredPatients = _.reject(patients, { id: targetId }); + var mrnExists = _.find(filteredPatients, { mrn: values.mrn }); + if (mrnExists) { + errors.mrn = i18n.t( + 'This MRN is already in use. Please enter a valid MRN.' + ); + } + } return errors; } @@ -119,6 +149,57 @@ class ClinicUserEdit extends React.Component { clinics: PropTypes.object.isRequired, }; + static defaultProps = { + searchDebounceMs: 1000, + }; + + constructor(props) { + super(props); + const { targetId, memberships, selectedClinicId, clinics } = props; + this.state = { + searchText: '', + updateTrigger: false, + isCustodialAccount: this.isCustodialAccount(memberships, targetId, selectedClinicId, clinics) + }; + }; + + isCustodialAccount = (memberships, targetId, selectedClinicId, clinics) => { + return ( + _.has(_.get(memberships, [targetId, 'permissions']), 'custodian') || + (selectedClinicId && + _.has( + _.get(clinics, [ + selectedClinicId, + 'patients', + targetId, + 'permissions', + ]), + 'custodian' + )) + ); + }; + + componentDidUpdate(prevProps) { + const { targetId, memberships, selectedClinicId, clinics } = this.props; + if ( + this.props.working.fetchingPatientsForClinic.inProgress === false && + prevProps.working.fetchingPatientsForClinic.inProgress === true + ) { + this.props.change('_forceValidation', Date.now()); + } + + if (this.props.targetId !== prevProps.targetId) { + this.setState({ + isCustodialAccount: this.isCustodialAccount( + memberships, + targetId, + selectedClinicId, + clinics + ) + }); + } + }; + handleCancel = () => { if(this.props.working.creatingClinicCustodialAccount.notification) { this.props.acknowledgeNotification(); @@ -174,6 +255,22 @@ class ClinicUserEdit extends React.Component { } }; + handleSearchChange = () => _.debounce((e) => { + let searchText = e.target.value; + const {fetchPatientsForClinic, selectedClinicId, targetId} = this.props; + if(searchText !== this.state.searchText){ + if(_.isEmpty(searchText)){ + if(!targetId){ + this.setState({searchText}); + fetchPatientsForClinic(selectedClinicId); + } + } else { + this.setState({searchText}); + fetchPatientsForClinic(selectedClinicId, {search: searchText}); + } + } + }, this.props.searchDebounceMs); + renderCreateError = () => { if ( this.props.createCustodialAccountErrorDismissed || @@ -286,23 +383,12 @@ class ClinicUserEdit extends React.Component { }; render() { - const { handleSubmit, targetId, memberships, clinics, selectedClinicId } = this.props; - const isCustodialAccount = - _.has(_.get(memberships, [targetId, 'permissions']), 'custodian') || - (selectedClinicId && - _.has( - _.get(clinics, [ - selectedClinicId, - 'patients', - targetId, - 'permissions', - ]), - 'custodian' - )); + const { handleSubmit, targetId, clinics, selectedClinicId } = this.props; + const titleText = targetId ? i18n.t('Edit patient account') : i18n.t('Create a new patient account'); - const editable = targetId ? isCustodialAccount : true; + const editable = targetId ? this.state.isCustodialAccount : true; const mrnRequired = _.get( clinics, [selectedClinicId, 'mrnSettings', 'required'], @@ -346,6 +432,7 @@ class ClinicUserEdit extends React.Component { name="mrn" component={renderInput} props={{ disabled: !editable }} + onChange={this.handleSearchChange()} />
diff --git a/app/containers/ClinicUserEditPage.js b/app/containers/ClinicUserEditPage.js index 6d50d7666..8d66cfc39 100644 --- a/app/containers/ClinicUserEditPage.js +++ b/app/containers/ClinicUserEditPage.js @@ -36,30 +36,46 @@ export class ClinicUserEditPage extends Component { }; render() { - const { allUsers, uploadTargetUser, memberships } = this.props; + const { + allUsers, + uploadTargetUser, + memberships, + loggedInUser, + createCustodialAccountErrorMessage, + createCustodialAccountErrorDismissed, + updateProfileErrorMessage, + updateProfileErrorDismissed, + selectedClinicId, + clinics, + working, + async, + sync + } = this.props; + return (
+ createCustodialAccountErrorMessage={createCustodialAccountErrorMessage} + createCustodialAccountErrorDismissed={createCustodialAccountErrorDismissed} + updateProfileErrorMessage={updateProfileErrorMessage} + updateProfileErrorDismissed={updateProfileErrorDismissed} + dismissCreateCustodialAccountError={sync.dismissCreateCustodialAccountError} + dismissUpdateProfileError={sync.dismissUpdateProfileError} + onSubmitFail={sync.clinicInvalidDate} + selectedClinicId={selectedClinicId} + clinics={clinics} + working={working} + acknowledgeNotification={sync.acknowledgeNotification} + fetchPatientsForClinic={async.fetchPatientsForClinic} />
); } diff --git a/app/package.json b/app/package.json index 53e21a984..e6a354a56 100644 --- a/app/package.json +++ b/app/package.json @@ -1,7 +1,7 @@ { "name": "tidepool-uploader", "productName": "tidepool-uploader", - "version": "2.55.1-tandem-compatibility.updates.1", + "version": "2.55.1-mrn-validation.2", "description": "Tidepool Project Universal Uploader", "main": "./main.prod.js", "author": { diff --git a/package.json b/package.json index f85201ed2..b4a35e18c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tidepool-uploader", - "version": "2.55.1-tandem-compatibility.updates.1", + "version": "2.55.1-mrn-validation.2", "description": "Tidepool Project Universal Uploader", "private": true, "main": "main.prod.js", diff --git a/styles/components/ClinicUserEdit.module.less b/styles/components/ClinicUserEdit.module.less index f9fbd64a5..fdeefaecc 100644 --- a/styles/components/ClinicUserEdit.module.less +++ b/styles/components/ClinicUserEdit.module.less @@ -126,6 +126,11 @@ .validationError { color: @red-error; margin-top: 10px; + + ul { + padding-left: 20px; + margin-top: 0px; + } } .iconClose {