diff --git a/app/locales/en/translations.js b/app/locales/en/translations.js index 9cc85065fb..192dd9c310 100644 --- a/app/locales/en/translations.js +++ b/app/locales/en/translations.js @@ -901,7 +901,8 @@ export default { totalPatientDays: 'Total Patient Days', totalPatientDaysDetailed: 'Total Patient Days (Detailed)', visit: 'Visit', - deletePatientRecord: 'Delete Patient Record' + deletePatientRecord: 'Delete Patient Record', + outpatientsForDate: 'Outpatients for {{visitDate}}' }, messages: { areYouSureDelete: 'Are you sure you want to delete this {{object}}?', diff --git a/app/mixins/filter-list.js b/app/mixins/filter-list.js index 9aa62916fe..42d19b54de 100644 --- a/app/mixins/filter-list.js +++ b/app/mixins/filter-list.js @@ -1,23 +1,33 @@ import Ember from 'ember'; + +const { + isEmpty, + String: { + isHTMLSafe + } +} = Ember; + export default Ember.Mixin.create({ filteredBy: new Ember.Map(), filterList(list, filterBy, filterValue) { - if (Ember.isEmpty(filterBy)) { + let filteredBy = this.get('filteredBy'); + if (isEmpty(filterBy) && isEmpty(filteredBy)) { return list; } - let filteredBy = this.get('filteredBy'); - filteredBy.set(filterBy, filterValue); + if (!isEmpty(filterBy)) { + filteredBy.set(filterBy, filterValue); + } this.set('filteredBy', filteredBy); let filteredList = list.filter((order) => { let includeRecord = true; filteredBy.forEach((filterValue, filterBy) => { let orderValue = order.get(filterBy); - if (!Ember.isEmpty(filterValue)) { - if (Ember.String.isHTMLSafe(filterValue)) { + if (!isEmpty(filterValue)) { + if (isHTMLSafe(filterValue)) { filterValue = filterValue.toString(); } - if (Ember.String.isHTMLSafe(orderValue)) { + if (isHTMLSafe(orderValue)) { orderValue = orderValue.toString(); } if (orderValue !== filterValue) { diff --git a/app/patients/outpatient/controller.js b/app/patients/outpatient/controller.js index 52135cae4d..4723be383e 100644 --- a/app/patients/outpatient/controller.js +++ b/app/patients/outpatient/controller.js @@ -2,18 +2,25 @@ import Ember from 'ember'; import FilterList from 'hospitalrun/mixins/filter-list'; import ModalHelper from 'hospitalrun/mixins/modal-helper'; import PatientVisits from 'hospitalrun/mixins/patient-visits'; +import SelectValues from 'hospitalrun/utils/select-values'; import UserSession from 'hospitalrun/mixins/user-session'; import VisitTypes from 'hospitalrun/mixins/visit-types'; -const { computed } = Ember; +const { + computed, + isEmpty +} = Ember; -export default Ember.Controller.extend(FilterList, ModalHelper, PatientVisits, UserSession, VisitTypes, { +export default Ember.Controller.extend(FilterList, ModalHelper, PatientVisits, SelectValues, UserSession, VisitTypes, { addPermission: 'add_patient', deletePermission: 'delete_patient', filterValue: null, filterBy: null, + queryParams: ['visitDate', 'visitLocation'], sortByDesc: null, sortByKey: null, + visitLocation: null, + visitDate: null, canAddVisit: computed(function() { return this.currentUserCan('add_visit'); }), @@ -31,6 +38,7 @@ export default Ember.Controller.extend(FilterList, ModalHelper, PatientVisits, i18n.t('visits.labels.haveDoneOrders') ]; }), + locationList: Ember.computed.map('patientController.locationList.value', SelectValues.selectValuesMap), patientNames: computed.map('model', function(visit) { return visit.get('patient.shortDisplayName'); }), @@ -42,13 +50,20 @@ export default Ember.Controller.extend(FilterList, ModalHelper, PatientVisits, }), checkedInVisits: computed.filter('model.@each.status', function(visit) { - return visit.get('status') !== 'checkedOut'; + return visit.get('visitType') !== 'Admission' && visit.get('status') !== 'checkedOut'; }), - filteredVisits: computed('checkedInVisits', 'filterBy', 'filterValue', function() { + filteredVisits: computed('checkedInVisits', 'filterBy', 'filterValue', 'visitLocation', function() { let filterBy = this.get('filterBy'); let filterValue = this.get('filterValue'); + let filteredBy = this.get('filteredBy'); + let visitLocation = this.get('visitLocation'); let visits = this.get('checkedInVisits'); + if (isEmpty(visitLocation)) { + filteredBy.delete('location'); + } else { + filteredBy.set('location', visitLocation); + } return this.filterList(visits, filterBy, filterValue); }), @@ -107,6 +122,20 @@ export default Ember.Controller.extend(FilterList, ModalHelper, PatientVisits, }); }, + search() { + let visitDate = this.get('model.selectedVisitDate'); + let visitLocation = this.get('model.selectedLocation'); + if (!isEmpty(visitDate)) { + this.set('visitDate', visitDate.getTime()); + } + if (isEmpty(visitLocation)) { + this.set('visitLocation', null); + } else { + this.set('visitLocation', visitLocation); + } + + }, + sortByKey(sortKey, sortDesc) { this.setProperties({ sortByDesc: sortDesc, diff --git a/app/patients/outpatient/route.js b/app/patients/outpatient/route.js index f1d0f91f07..1dab85bfc4 100644 --- a/app/patients/outpatient/route.js +++ b/app/patients/outpatient/route.js @@ -1,29 +1,82 @@ import AbstractIndexRoute from 'hospitalrun/routes/abstract-index-route'; +import DateFormat from 'hospitalrun/mixins/date-format'; +import Ember from 'ember'; import { translationMacro as t } from 'ember-i18n'; -export default AbstractIndexRoute.extend({ +const { + computed, + isEmpty +} = Ember; + +export default AbstractIndexRoute.extend(DateFormat, { + database: Ember.inject.service(), modelName: 'visit', newButtonAction: 'patientCheckIn', newButtonText: t('patients.buttons.patientCheckIn'), - pageTitle: t('patients.titles.todaysOutpatients'), + selectedVisitDate: null, + showingTodaysPatients: true, + pageTitle: computed('showingTodaysPatients', 'selectedVisitDate', function() { + let i18n = this.get('i18n'); + let showingTodaysPatients = this.get('showingTodaysPatients'); + if (showingTodaysPatients) { + return i18n.t('patients.titles.todaysOutpatients'); + } else { + let selectedVisitDate = this._dateFormat(this.get('selectedVisitDate')); + return i18n.t('patients.titles.outpatientsForDate', { visitDate: selectedVisitDate }); + } + }), + + queryParams: { + visitDate: { refreshModel: true }, + visitLocation: { refreshModel: false } + }, _getStartKeyFromItem(item) { let displayPatientId = item.get('displayPatientId'); return [displayPatientId, `patient_${item.get('id')}`]; }, - _modelQueryParams() { - let endOfDay = moment().endOf('day').valueOf(); - let startOfDay = moment().startOf('day').valueOf(); + _modelQueryParams(params) { + let database = this.get('database'); + let maxId = database.getMaxPouchId('visit'); + let minId = database.getMaxPouchId('visit'); + let { visitDate } = params; + if (isEmpty(visitDate)) { + visitDate = moment(); + } else { + visitDate = moment(parseInt(visitDate)); + } + if (visitDate.isSame(moment(), 'day')) { + this.set('showingTodaysPatients', true); + } else { + this.set('showingTodaysPatients', false); + this.set('selectedVisitDate', visitDate.toDate()); + } + let endOfDay = visitDate.endOf('day').valueOf(); + let startOfDay = visitDate.startOf('day').valueOf(); + return { mapReduce: 'visit_by_date', options: { - endkey: [endOfDay, endOfDay, this._getMaxPouchId()], - startkey: [startOfDay, null, this._getMinPouchId()] + endkey: [endOfDay, endOfDay, maxId], + startkey: [startOfDay, null, minId] } }; }, + model(params) { + return this._super(params).then((model) => { + let visitDate = new Date(); + if (!isEmpty(params.visitDate)) { + visitDate.setTime(params.visitDate); + } + model.set('selectedVisitDate', visitDate); + model.set('display_selectedVisitDate', this._dateFormat(visitDate)); + model.set('selectedLocation', params.visitLocation); + return model; + }); + }, + actions: { finishCheckOut(visit) { this.controller.send('finishCheckOut', visit); diff --git a/app/patients/outpatient/template.hbs b/app/patients/outpatient/template.hbs index 30c3bae71c..6a1d72fedc 100644 --- a/app/patients/outpatient/template.hbs +++ b/app/patients/outpatient/template.hbs @@ -1,4 +1,19 @@ {{#item-listing paginationProps=paginationProps }} +
+
+ {{#em-form model=model submitButton=false }} +
+ {{date-picker property="selectedVisitDate" label=(t "visits.labels.visitDate")class="col-sm-3"}} + {{em-select class="col-sm-3 form-input-group" property="selectedLocation" + label=(t "labels.location") content=locationList prompt=" " + }} +
+ {{/em-form}} +
+ +