Эх сурвалжийг харах

Merge branch 'master' of rav.triplestart.com:jmudaka/stagfe2

root 3 жил өмнө
parent
commit
5cbfd4fa10
26 өөрчлөгдсөн 772 нэмэгдсэн , 744 устгасан
  1. 15 0
      app/Helpers/helpers.php
  2. 85 2
      app/Http/Controllers/HomeController.php
  3. 12 0
      app/Models/ClientBDTDevice.php
  4. 5 0
      app/Models/Measurement.php
  5. 4 1
      app/Models/Pro.php
  6. 1 1
      config/app.php
  7. 24 2
      public/js/mc-init.js
  8. 47 23
      public/js/mc.js
  9. 11 4
      public/js/stag-popup.js
  10. 0 0
      public/js/yemi.js
  11. 84 346
      resources/views/app/dashboard-mcp.blade.php
  12. 0 17
      resources/views/app/mcp/dashboard/appointment-change-status.blade.php
  13. 96 0
      resources/views/app/mcp/dashboard/appointments-list.blade.php
  14. 45 30
      resources/views/app/mcp/dashboard/measurements-pending-stamping.blade.php
  15. 4 0
      resources/views/app/patient/dashboard.blade.php
  16. 23 3
      resources/views/app/patient/devices.blade.php
  17. 95 71
      resources/views/app/patient/partials/appointments.blade.php
  18. 2 48
      resources/views/app/patient/partials/measurements.blade.php
  19. 87 0
      resources/views/app/patient/segment-templates/_custom_items/edit.blade.php
  20. 2 1
      resources/views/app/patient/segment-templates/history_family/edit.blade.php
  21. 30 59
      resources/views/app/patient/segment-templates/history_social/edit.blade.php
  22. 33 60
      resources/views/app/patient/segment-templates/history_surgical/edit.blade.php
  23. 30 59
      resources/views/app/patient/segment-templates/past_medical_history/edit.blade.php
  24. 5 3
      resources/views/layouts/patient.blade.php
  25. 1 0
      routes/web.php
  26. 31 14
      yemi.js

+ 15 - 0
app/Helpers/helpers.php

@@ -665,4 +665,19 @@ if(!function_exists('noteMethodDisplay')) {
         $method = str_replace('_', ' ', $method);
         return ucwords(strtolower($method));
     }
+}
+
+if(!function_exists('friendly_timezone')) {
+    function friendly_timezone($tz) {
+        $map = [
+            'EASTERN' => 'EST',
+            'CENTRAL' => 'CST',
+            'MOUNTAIN' => 'MST',
+            'PACIFIC' => 'PST',
+            'ALASKA' => 'AST',
+            'HAWAII' => 'HST',
+            'PUERTO_RICO' => 'PR'
+        ];
+        return $map[$tz] ?? str_replace("_", " ", $tz);
+    }
 }

+ 85 - 2
app/Http/Controllers/HomeController.php

@@ -541,10 +541,25 @@ WHERE cl.shadow_pro_id IS NULL
             ORDER BY created_at DESC
         ", ['mcp_pro_id' => $performer->pro->id]);
 
-        $measurementsPendingStamping = CareMonth::where('mcp_pro_id', $this->performer->pro->id)
+        $careMonthsWithMeasurementsPendingStamping = CareMonth::select('id')
+            ->where('mcp_pro_id', $this->performer->pro->id)
             ->where('rm_num_measurements_not_stamped_by_mcp', '>', 0)
             ->whereNotNull('rm_num_measurements_not_stamped_by_mcp')
             ->orderBy('created_at', 'DESC')
+            ->get()
+            ->map(function($_x) {
+                return $_x->id;
+            })
+            ->toArray();
+
+        $measurementsPendingStamping = Measurement::whereIn('care_month_id', $careMonthsWithMeasurementsPendingStamping)
+            ->orderBy('created_at', 'DESC')
+            ->whereNotNull('ts')
+            ->whereNotIn('label', ['SBP', 'DBP'])
+            ->where('is_cellular_zero', '<>', true)
+            ->where('is_removed', false)
+            ->where('has_been_stamped_by_mcp', false)
+            ->whereNotNull('client_bdt_measurement_id')
             ->paginate(15);
 
         return view('app/dashboard-mcp', compact('keyNumbers', 'reimbursement', 'milliseconds',
@@ -552,7 +567,7 @@ WHERE cl.shadow_pro_id IS NULL
             'incomingReports', 'tickets', 'supplyOrders',
             'numERx', 'numLabs', 'numImaging', 'numSupplyOrders',
             'newMCPAssociations', 'newNAAssociations',
-            'measurementsPendingStamping',
+            'measurementsPendingStamping', 'careMonthsWithMeasurementsPendingStamping',
             'mcpClientMemos', 'mcpClientMemosCount', 'naClientMemos', 'incomingSmsMessagesPendingReply'));
     }
 
@@ -1445,6 +1460,74 @@ WHERE measurement.label NOT IN ('SBP', 'DBP')
         return json_encode($appointments);
     }
 
+    public function dashboardAppointmentsDisplay(Request $request, $from, $to) {
+        $performer = $this->performer();
+        $performerProID = $performer->pro->id;
+        $isAdmin = ($performer->pro->pro_type === 'ADMIN');
+
+        // $appointments = Appointment::where("start_time", '>=', $from)->where("start_time", '<=', $to.' 23:59:00+00');
+        $appointments = Appointment::where("raw_date", '=', $from);
+
+        if(!$isAdmin) {
+            $appointments = $appointments->where("pro_id", $performerProID);
+        }
+
+        $appointments = $appointments
+            ->orderBy('start_time', 'asc')
+            ->orderBy('end_time', 'asc')
+            ->get();
+
+        foreach ($appointments as $appointment) {
+            $date = explode(" ", $appointment->start_time)[0];
+            $appointment->milliseconds = strtotime($date) . '000';
+            $appointment->newStatus = $appointment->status;
+
+            $appointment->dateYMD = date('Y-m-d', strtotime($appointment->raw_date));
+            $appointment->clientName = $appointment->client->displayName();
+            $appointment->clientInitials = substr($appointment->client->name_first, 0, 1) . substr($appointment->client->name_last, 0, 1);
+            $appointment->isClientShadowOfPro = $appointment->client->shadow_pro_id ? true : false;
+            $appointment->proInitials = substr($appointment->pro->name_first, 0, 1) . substr($appointment->pro->name_last, 0, 1);
+            $appointment->friendlyStartTime = friendly_time($appointment->raw_start_time);
+            $appointment->friendlyEndTime = friendly_time($appointment->raw_end_time);
+            $appointment->clientSummary = friendly_date_time($appointment->client->dob, false) . ' (' .
+                $appointment->client->age_in_years . ' y.o' .
+                ($appointment->client->sex ? ' ' . $appointment->client->sex : '') .
+                ')';
+            $appointment->clientAge = $appointment->client->age_in_years;
+            $appointment->clientSex = $appointment->client->sex;
+
+            $appointment->started = false;
+            $appointment->inHowManyHours = date_diff(date_create('now'), date_create($appointment->start_time), false)
+                ->format('%R%h h, %i m');
+            if ($appointment->inHowManyHours[0] === '-') {
+                $appointment->inHowManyHours = substr($appointment->inHowManyHours, 1) . ' ago';
+                $appointment->started = true;
+            } else {
+                $appointment->inHowManyHours = 'Appt. in ' . substr($appointment->inHowManyHours, 1);
+            }
+            $appointment->clientUid = $appointment->client->uid;
+            $appointment->proUid = $appointment->pro->uid;
+            $appointment->proName = $appointment->pro->displayName();
+
+            // insurance information
+            $appointment->coverage = $appointment->client->getPrimaryCoverageStatus();
+
+            // bg color
+            $appointment->bgColor = 'bg-white';
+            if($appointment->status === 'COMPLETED') {
+                $appointment->bgColor = 'event-bg-green';
+            }
+            else if($appointment->status === 'CANCELLED') {
+                $appointment->bgColor = 'event-bg-gray';
+            }
+
+            unset($appointment->client);
+            unset($appointment->pro);
+            unset($appointment->detail_json);
+        }
+        return view('app.mcp.dashboard.appointments-list', compact('appointments', 'from', 'to'));
+    }
+
     public function dashboardMeasurements(Request $request, $filter) {
         $measurements = $this->performer()->pro->getMeasurements($filter === 'NEED_ACK');
         return json_encode($measurements);

+ 12 - 0
app/Models/ClientBDTDevice.php

@@ -14,4 +14,16 @@ class ClientBDTDevice extends Model
         return $this->hasOne(Client::class, 'id', 'client_id');
     }
 
+    public function lastDeviceMeasurement() {
+        return BDTMeasurement::select('bdt_measurement.created_at', 'measurement.label', 'measurement.sbp_mm_hg', 'measurement.dbp_mm_hg', 'measurement.numeric_value')
+            ->join('client_bdt_measurement', 'client_bdt_measurement.bdt_measurement_id', '=', 'bdt_measurement.id')
+            ->join('measurement', 'measurement.client_bdt_measurement_id', '=', 'client_bdt_measurement.id')
+            ->where('bdt_measurement.is_cellular_zero', '<>', true)
+            ->whereNotNull('bdt_measurement.ts')
+            ->where('client_bdt_measurement.client_id', $this->client_id)
+            ->where('bdt_measurement.imei', $this->device->imei)
+            ->orderBy('bdt_measurement.created_at', 'DESC')
+            ->first();
+    }
+
 }

+ 5 - 0
app/Models/Measurement.php

@@ -13,6 +13,11 @@ class Measurement extends Model
         return $this->hasOne(Client::class, 'id', 'client_id');
     }
 
+    public function careMonth()
+    {
+        return $this->hasOne(CareMonth::class, 'id', 'care_month_id');
+    }
+
     public function clientBDTMeasurement()
     {
         return $this->hasOne(ClientBDTMeasurement::class, 'id', 'client_bdt_measurement_id');

+ 4 - 1
app/Models/Pro.php

@@ -151,7 +151,10 @@ class Pro extends Model
     }
 
     public function canvasCustomItems($_key) {
-        return ClientCanvasDataCustomItem::where('key', $_key)->get();
+        return ClientCanvasDataCustomItem::where('key', $_key)
+            ->where('pro_id', $this->id)
+            ->orderBy('label')
+            ->get();
     }
 
 

+ 1 - 1
config/app.php

@@ -65,7 +65,7 @@ return [
 
     'hrm2_url' => env('HRM2_URL'),
 
-    'asset_version' => 23,
+    'asset_version' => 24,
 
     'temp_dir' => env('TEMP_DIR'),
 

+ 24 - 2
public/js/mc-init.js

@@ -9,7 +9,7 @@ window.addMCInitializer = function(_name, _func, _container) {
         container: _container
     };
 };
-window.runMCInitializers = function() {
+window.runMCInitializers = function(_target = null) {
     if(!!mcInitializers) {
         // console.log('ALIX -----------------');
         for(let initer in mcInitializers) {
@@ -18,7 +18,7 @@ window.runMCInitializers = function() {
                     let initerObj = mcInitializers[initer];
                     if(!initerObj.container || $(initerObj.container).length) {
                         // console.log("ALIX running MC initer", initer);
-                        initerObj.func();
+                        initerObj.func(_target);
                     }
                     else {
                         // console.warn("ALIX MC initer not in context. Removing ", initer);
@@ -54,3 +54,25 @@ window.runMCInitializer = function(_initer) {
         }
     }
 };
+window.mcHooks = {};
+window.addMCHook = function(_name, _func) {
+    if(!!window.mcHooks[_name]) {
+        // console.warn('ALIX initializer ' + _name + ' exists. Will overwrite.');
+        delete window.mcHooks[_name];
+    }
+    window.mcHooks[_name] = {
+        func: _func
+    };
+};
+window.runMCHook = function(_initer) {
+    if(!!mcHooks && !!mcHooks[_initer]) {
+        try {
+            let initerObj = mcHooks[_initer];
+            initerObj.func();
+        }
+        catch(e) {
+            console.warn('MC hook error: ', e);
+            console.warn('Hook: ', _initer);
+        }
+    }
+};

+ 47 - 23
public/js/mc.js

@@ -156,41 +156,54 @@ function initFastLoad(_parent = false) {
 
 }
 
-function onFastLoaded(_data, _href, _history) {
-    var targetParent = $('.stag-content');
+function onFastLoaded(_data, _href, _history, _target = null) {
+
     if (!Number.isInteger(_data)) {
         _data = '<div>' + _data + '</div>';
-        var content = $(_data).find('.stag-content');
-        if (content && content.length) {
-            targetParent.html(content.html());
+
+        // do for each element in _target
+        let responseError = false;
+        let originalTarget = _target;
+        _target = _target ? _target : '.stag-content';
+        _target = _target.split(',').map(_x => $.trim(_x));
+        for (let i = 0; i < _target.length; i++) {
+            let t = _target[i];
+            let targetElement = $(t).first();
+            if(targetElement.length) {
+                let sourceElement = $(_data).find(t).first();
+                if (sourceElement && sourceElement.length) {
+                    targetElement.html(sourceElement.html());
+                    initFastLoad(targetElement);
+                    console.log('ALIX loaded element: ' + t);
+                }
+                else {
+                    responseError = true;
+                }
+            }
+            else {
+                responseError = true;
+            }
+        }
+
+        if (!responseError) {
             hideMask();
             hideMoeFormMask();
-            targetParent.append('<script src="/js/yemi.js?_=7"></script>');
             window.setTimeout(function () {
                 initCreateNote();
                 initQuillEdit();
-                initFastLoad(targetParent);
                 initPrimaryForm();
                 initPatientPresenceIndicator();
-                runMCInitializers();
                 initFileInputs();
+                initMoes();
+                runMCInitializers(originalTarget);
                 if (window.top.currentMcUrl.split('?')[0] !== window.top.location.href.split('?')[0]) {
                     $(window).scrollTop(0);
                 }
                 window.top.currentMcUrl = window.top.location.href;
-
-                /*let activeLeftNavLink = $('#sidebarMenu .nav-item>.nav-link.active').first();
-                if(activeLeftNavLink.length) {
-                    activeLeftNavLink[0].scrollIntoView({
-                        behavior: "smooth",
-                        block: "nearest",
-                        inline: "nearest"
-                    });
-                }*/
             }, 0);
         }
         else {
-            targetParent.html('<p class="text-danger p-3 small">Error on page: <b>' + _href + '</b></p>');
+            $('.stag-content').first().html('<p class="text-danger p-3 small">Error on page: <b>' + _href + '</b></p>');
             hideMask();
             hideMoeFormMask();
         }
@@ -212,13 +225,24 @@ function onFastLoaded(_data, _href, _history) {
                 break;
         }
         console.warn('MC: Target page failed: ' + _href);
-        targetParent.html('<p class="text-danger p-3 small"><b>' + _data + '</b> - ' + msg + '<b>' + _href + '</b></p>');
+        $('.stag-content').first().html('<p class="text-danger p-3 small"><b>' + _data + '</b> - ' + msg + '<b>' + _href + '</b></p>');
         hideMask();
         hideMoeFormMask();
     }
     $('html, body').removeClass('no-scroll');
 }
-function fastLoad(_href, _history = true, _useCache = true, _replaceState = false) {
+
+var fastReload = function(_target = null) {
+    var targetLocation = window.top.location.pathname + window.top.location.search;
+    if(targetLocation.indexOf('/mc') === 0) {
+        targetLocation = targetLocation.substr(3);
+    }
+    if(targetLocation === '' || targetLocation[0] !== '/') targetLocation = '/' + targetLocation;
+    fastLoad(targetLocation, false, false, false, _target);
+    return false;
+}
+
+function fastLoad(_href, _history = true, _useCache = true, _replaceState = false, _target = null) {
 
     let domPro = $(window.top.document.body).attr('data-pro-uid'),
         lsPro = window.top.localStorage.currentProUid;
@@ -256,7 +280,7 @@ function fastLoad(_href, _history = true, _useCache = true, _replaceState = fals
     }
 
     if (_useCache && !!fastCache[_href]) {
-        onFastLoaded(fastCache[_href], _href, _history);
+        onFastLoaded(fastCache[_href], _href, _history, _target);
     } else {
 
         let cleanedHREF = _href;
@@ -270,9 +294,9 @@ function fastLoad(_href, _history = true, _useCache = true, _replaceState = fals
         if(cleanedHREF.length > 0 && cleanedHREF[0] === '?') cleanedHREF = '/' + cleanedHREF;
 
         $.get(cleanedHREF, function (_data) {
-            onFastLoaded(_data, _href, _history);
+            onFastLoaded(_data, _href, _history, _target);
         }).fail(function (_jqXhr) {
-            onFastLoaded(_jqXhr.status, _href, _history);
+            onFastLoaded(_jqXhr.status, _href, _history, _target);
         });
     }
 }

+ 11 - 4
public/js/stag-popup.js

@@ -50,7 +50,7 @@ function closeStagPopup(_noEvent = false) {
                 refreshDynamicStagPopup();
             }
             else {
-                fastReload();
+                fastReload(popup.is('[update-target]') ? popup.attr('update-target') : '');
                 return;
             }
         }
@@ -81,7 +81,7 @@ function convertContentLinksForInPopupNavigation(popup) {
         }
     });
 }
-function openDynamicStagPopup(_url, initer, title, updateParent, style = '', replace = false) {
+function openDynamicStagPopup(_url, initer, title, updateParent, style = '', replace = false, updateTarget = null) {
     let url = _url;
     if(url.indexOf('popupmode') === -1) {
         url += (url.indexOf('?') !== -1 ? '&' : '?') + 'popupmode=1';
@@ -134,6 +134,10 @@ function openDynamicStagPopup(_url, initer, title, updateParent, style = '', rep
                 popup.removeAttr('update-parent');
             }
             showStagPopup(url, true);
+
+            if(updateTarget) {
+                popup.attr('update-target', updateTarget);
+            }
         }
 
         if(initer) runMCInitializer(initer);
@@ -218,7 +222,9 @@ function hasResponseError(_data) {
                     trig.attr('mc-initer'),
                     trig.attr('title'),
                     trig.is('[update-parent]'),
-                    trig.attr('popup-style')
+                    trig.attr('popup-style'),
+                    false,
+                    trig.is('[update-target]') ? trig.attr('update-target') : null
                 );
                 return false;
             });
@@ -233,7 +239,8 @@ function hasResponseError(_data) {
                     trig.attr('title'),
                     null, // will be inherited when replacing
                     null, // will be inherited when replacing
-                    true
+                    true,
+                    null
                 );
                 return false;
             });

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
public/js/yemi.js


+ 84 - 346
resources/views/app/dashboard-mcp.blade.php

@@ -19,7 +19,7 @@
     <div id="dashboard-mcp">
     <div class="p-3">
         <div class="">
-            <div class="row mcp-theme-1" id="pro-dashboard-container" v-cloak>
+            <div class="row mcp-theme-1" id="pro-dashboard-container">
                 <div class="col-md-3 mcp-theme-1">
                     <div class="mb-4">
                         <div class="pro-dashboard-inline-calendar"></div>
@@ -284,17 +284,10 @@
                     </div>
                 </div>
                 <div class="col-md-9">
-                    <div class="row mcp-theme-1" id="pro-dashboard-container" v-cloak>
+                    <div class="row mcp-theme-1">
                         <div class="col-md-6 mcp-theme-1">
-                            <div class="card mb-4">
-                                <div class="card-header pl-2">
-                                    <strong>
-                                        Appointments @{{ formatSelectedDate(selectedDate) }}
-                                    </strong>
-                                </div>
-                                <div class="card-body p-0 max-height-200px overflow-auto">
-                                    @include('app.mcp.dashboard.appointments')
-                                </div>
+                            <div id="mcp-dashboard-appointments" class="mb-4">
+
                             </div>
                             <div class="card mb-4">
                                 <div class="card-header pl-2">
@@ -350,350 +343,91 @@
 
     <script>
         (function () {
-            function init() {
-                window.apapp = new Vue({
-                    el: '#pro-dashboard-container',
-                    delimiters: ['@{{', '}}'],
-                    data: {
-                        tab: '{{ request()->input('tab') ? request()->input('tab') : 'measurements' }}',
-                        datesWithEvents: [],
-                        selectedDate: '{{ date('Y-m-d') }}',
-                        selectedStatus: 'PENDING',
-                        events: [],
-                        numEventsForDate: 0,
-                        filterStatus: '',
-                        calendarElem: null,
-                        currentMonth: null,
-                        currentYear: null,
-                        measurementFilterStatus: 'ALL',
-                        measurements: {!! $pro->pro_type === 'ADMIN' ? '[]' : json_encode($pro->getMeasurements()) !!},
-                        appointmentsLoaded: false,
-                    },
-                    methods: {
-                        formatDate: function (date) {
-                            let d = new Date(date),
-                                month = '' + (d.getMonth() + 1),
-                                day = '' + d.getDate(),
-                                year = d.getFullYear();
-
-                            if (month.length < 2)
-                                month = '0' + month;
-                            if (day.length < 2)
-                                day = '0' + day;
 
-                            return [year, month, day].join('-');
-                        },
-                        onDateChange: function (_newDate) {
-                            let self = this;
-                            window.setTimeout(() => {
-                                // let dayValue = $('.pro-dashboard-inline-calendar td.day.active').first().text();
-                                // if(dayValue.length === 1) dayValue = '0' + dayValue;
-                                // self.selectedDate = _newDate.substr(0, 8) + dayValue;
-                                self.selectedDate = _newDate;
-                                showMask();
-                                self.loadEvents(self.selectedDate, function () {
-                                    hideMask();
-                                    Vue.nextTick(() => {
-                                        // self.highlightDatesWithEvents(self.datesWithEvents);
-                                        initFastLoad($('.appointments-tab'));
-                                        initFastLoad($('#pro-dashboard-container'));
-                                        $('#pro-dashboard-container').find('[moe][initialized]').removeAttr('initialized');
-                                        initMoes();
-                                    });
-                                });
-                            }, 25);
-                        },
-                        selectToday: function () {
-                            $('.pro-dashboard-inline-calendar table td[data-date]').removeClass('active');
-                            $('.pro-dashboard-inline-calendar table td[data-date="{{ $milliseconds }}"]')
-                                .addClass('active');
-                            // this.onDateChange('{{ date('Y-m-d') }}');
-                        },
-                        highlightDatesWithEvents: function (_dates) {
-                            $('.pro-dashboard-inline-calendar table td[data-date]').removeAttr('has-events');
-                            for (let i = 0; i < _dates.length; i++) {
-                                $('.pro-dashboard-inline-calendar table td[data-date="' + _dates[i] + '"]')
-                                    .attr('has-events', 1);
-                            }
-                        },
-                        updateStatus: function (_event) {
-                            $.post('/api/appointment/updateStatus', {
-                                uid: _event.uid,
-                                status: _event.newStatus
-                            }, function (_data) {
-                                if (!_data) {
-                                    toastr.error('Unable to update appointment status!');
-                                } else {
-                                    if (!_data.success) {
-                                        toastr.error(_data.message);
-                                    } else {
-                                        _event.status = _event.newStatus;
-                                        toastr.success('The appointment has been updated');
-                                    }
-                                }
-                            }, 'json')
-                        },
-                        showEditForm: function (_trigger) {
-                            let form = $(_trigger).closest('[moe]').find('form').first();
-                            showMoeFormMask();
-                            form.show();
-                            setTimeout(function () {
-                                initPrimaryForm(form);
-                            }, 0);
-                        },
-                        submitEditForm: function (_trigger) {
-                            let form = $(_trigger).closest('[moe]').find('form').first();
-                            if (!form[0].checkValidity()) {
-                                form[0].reportValidity();
-                                return;
-                            }
-                            $.post(form.attr('url'), form.serialize(), function (_data) {
-                                if (_data && _data.success) {
-                                    fastReload();
-                                } else {
-                                    if (_data.message) {
-                                        toastr.error(_data.message);
-                                    } else {
-                                        toastr.error('Unable to update the appointment');
-                                    }
-                                }
-                            });
-                        },
-                        cancelEditForm: function (_trigger) {
-                            let form = $(_trigger).closest('[moe]').find('form').first();
-                            hideMoeFormMask();
-                            form.hide();
-                        },
-                        loadEventDates: function (_refDate = false) {
-                            let today = new Date(_refDate ? _refDate : '{{date('Y-m-d')}}'),
-                                firstOfMonth = new Date(today.getFullYear(), today.getMonth(), 1),
-                                lastOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0);
-
-                            this.selectedDate = null;
-                            $('td.day.active').removeClass('active');
-
-                            $.get('/pro-dashboard-event-dates/' +
-                                this.formatDate(firstOfMonth) + '/' +
-                                this.formatDate(lastOfMonth), (_data) => {
-                                this.datesWithEvents = _data;
-                                console.log(this.datesWithEvents);
-                                this.calendarElem.datepicker('refresh');
-                                // this.highlightDatesWithEvents(this.datesWithEvents);
-
-                                this.currentMonth = firstOfMonth.getMonth();
-                                this.currentYear = firstOfMonth.getFullYear();
-
-                                if (!_refDate && $('td.day[data-date="{{$milliseconds}}"]:visible').length) {
-                                    $('td.day[data-date="{{$milliseconds}}"]:visible').first().click();
-                                }
-
-                                this.appointmentsLoaded = true;
-                            }, 'json');
-                        },
-                        loadEvents: function (_date, _callback) {
-                            let self = this;
-                            $.get('/pro-dashboard-events/' + _date + '/' + _date, function (_data) {
-                                self.events = _data;
-                                self.numEventsForDate = (_data && _data.length) ? 1 : 0;
-                                _callback.call(self);
-                            }, 'json');
-                        },
-                        updateMeasurements: function () {
-                            $.get('/pro-dashboard-measurements/' + this.measurementFilterStatus, (_data) => {
-                                this.measurements = _data;
-                                Vue.nextTick(() => {
-                                    // this.initCMRTE();
-                                    $('#pro-dashboard-container').find('[moe][initialized]').removeAttr('initialized');
-                                    initMoes();
-                                });
-                            }, 'json');
-                        },
-                        setMeasurementStatus: function (_uid, _status) {
-                            $.post('/api/measurement/updateStatus', {
-                                uid: _uid,
-                                status: _status
-                            }, (_data) => {
-                                this.updateMeasurements();
-                            }, 'json');
-                        },
-                        initCMRTE: function () {
-                            $('#pro-dashboard-container [cm-rte]').each(function () {
-
-                                $(this).wrap(
-                                    $('<div class="border-left border-right rte-holder"/>')
-                                        .attr('data-shortcuts', '')
-                                );
-
-                                // give a unique id to this editor instance
-                                var editorID = Math.ceil(Math.random() * 99999), fieldName = $(this).attr('data-name');
-
-                                var el = this;
-                                var existingContent = $(el).attr('data-content');
-                                var quill = new Quill(el, {
-                                    theme: 'snow',
-                                    modules: stagQuillConfig
-                                });
-
-                                var toolbar = $(quill.container).prev('.ql-toolbar');
-
-                                // add button for new shortcut
-                                var newSCButton = $('<button class="btn bg-white btn-sm btn-default text-primary w-auto px-2 border py-0 ' +
-                                    'text-sm add-shortcut" data-editor-id="' + editorID + '">+ Shortcut</button>');
-                                toolbar.append(newSCButton);
+            let datesWithEvents = [],
+                selectedDate = '{{ date('Y-m-d') }}',
+                calendarElem = null,
+                currentMonth = null,
+                currentYear = null,
+                appointmentsLoaded = false;
+
+            function formatDate(date) {
+                let d = new Date(date),
+                    month = '' + (d.getMonth() + 1),
+                    day = '' + d.getDate(),
+                    year = d.getFullYear();
+
+                if (month.length < 2)
+                    month = '0' + month;
+                if (day.length < 2)
+                    day = '0' + day;
+
+                return [year, month, day].join('-');
+            }
 
-                                quill.root.innerHTML = existingContent;
+            function onDateChange(_newDate) {
+                // ajax load appts list as markup directly from server
+                selectedDate = _newDate;
+                $.get('/pro-dashboard-events-display/' + selectedDate + '/' + selectedDate, function (_data) {
+                    let apptscontainer = $('#mcp-dashboard-appointments');
+                    apptscontainer.html(_data);
+                    initFastLoad(apptscontainer);
+                    initMoes();
+                });
+            }
 
-                                $('<input type="hidden" name="' + fieldName + '">').val(existingContent).insertAfter(el);
+            function loadEventDates(_refDate = false) {
+                let today = new Date(_refDate ? _refDate : '{{date('Y-m-d')}}'),
+                    firstOfMonth = new Date(today.getFullYear(), today.getMonth(), 1),
+                    lastOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0);
+                selectedDate = null;
+                $('td.day.active').removeClass('active');
+                $.get('/pro-dashboard-event-dates/' +
+                    formatDate(firstOfMonth) + '/' +
+                    formatDate(lastOfMonth), (_data) => {
+                    datesWithEvents = _data;
+                    calendarElem.datepicker('refresh');
+                    currentMonth = firstOfMonth.getMonth();
+                    currentYear = firstOfMonth.getFullYear();
+                    if (!_refDate && $('td.day[data-date="{{$milliseconds}}"]:visible').length) {
+                        $('td.day[data-date="{{$milliseconds}}"]:visible').first().click();
+                    }
+                    appointmentsLoaded = true;
+                }, 'json');
+            }
 
-                                quill.on('text-change', function (delta, oldDelta, source) {
-                                    $(el).next('[name="' + fieldName + '"]').val(quill.root.innerHTML);
-                                });
+            function getFormattedCurrentDate() {
+                let date = new Date();
+                let day = date.getDate();
+                day = day < 10 ? '0' + day : day;
+                return date.getFullYear() + '-' + parseInt(date.getMonth() + 1) + '-' + day;
+            }
 
-                                $(quill.container)
-                                    .find('.ql-editor[contenteditable]')
-                                    .attr('data-field', fieldName)
-                                    .attr('data-editor-id', editorID)
-                                    .attr('with-shortcuts', 1);
+            function init(_target = null) {
 
-                            })
-                        },
-                        initLoadAppointments: function () {
-                            if (this.appointmentsLoaded) return false;
-                            this.loadEventDates();
-                        },
-                        loadMeasurements: function () {
-                            $('#measurements-tab').load('/pro-dashboard-measurements-tab', () => {
-                                initMoes();
-                                initFastLoad($('#measurements-tab'));
-                            });
-                        },
-                        getFormattedCurrentDate: function () {
-                            let date = new Date();
-                            let day = date.getDate();
-                            day = day < 10 ? '0' + day : day;
+                if(_target && _target !== '.stag-content') return;
 
-                            return date.getFullYear() + '-' + parseInt(date.getMonth() + 1) + '-' + day;
-                        },
-                        formatSelectedDate: function (_date, _format) {
-                            _format = _format || 'MM/DD/YYYY';
-                            if (_date) {
-                                return moment(_date).format(_format);
-                            }
-                        },
-                        formatTimeZone: function (_tz) {
-                            switch (_tz) {
-                                case 'EASTERN':
-                                    return 'EST'
-                                    break;
-                                case 'CENTRAL':
-                                    return 'CST'
-                                    break;
-                                case 'MOUNTAIN':
-                                    return 'MST'
-                                    break;
-                                case 'PACIFIC':
-                                    return 'PST'
-                                    break;
-                                case 'ALASKA':
-                                    return 'Alaska'
-                                    break;
-                                case 'HAWAII':
-                                    return 'Hawaii'
-                                    break;
-                                case 'PUERTO_RICO':
-                                    return 'Puerto Rico'
-                                    break;
-                                default:
-                                    return 'N/A';
-                            }
-                        },
-                        getEventBgColor: function(status){
-                            if(status === 'COMPLETED') return 'event-bg-green';
-                            if(status === 'CANCELLED') return 'event-bg-gray';
-                            return '';
-                        },
+                calendarElem = $('.pro-dashboard-inline-calendar');
+                calendarElem.datepicker({
+                    dateFormat: 'yy-mm-dd',
+                    onSelect: function (_date) {
+                        onDateChange(_date);
                     },
-                    mounted: function () {
-                        let self = this;
-                        this.calendarElem = $('.pro-dashboard-inline-calendar');
-                        this.calendarElem.datepicker({
-                            dateFormat: 'yy-mm-dd',
-                            onSelect: function (_date) {
-                                self.onDateChange(_date);
-                            },
-                            onChangeMonthYear: function (_year, _month) {
-                                let date = _year + '-' + (_month < 10 ? '0' : '') + _month + '-05';
-                                self.loadEventDates(date);
-                            },
-                            beforeShowDay: function (d) {
-                                if (self.datesWithEvents && self.datesWithEvents.indexOf(self.formatDate(d)) !== -1) {
-                                    return [true, 'has-events'];
-                                }
-                                return [true, 'no-events'];
-                            },
-                            defaultDate: 0
-                        });
-                        // this.calendarElem
-                        //     .on('changeDate', function () {
-                        //         self.onDateChange(self.calendarElem.datepicker('getFormattedDate'));
-                        //     })
-                        //     .on('changeMonth', function () {
-                        //         window.setTimeout(function() {
-                        //             let ts = $('td.day[data-date]').first().closest('tr').find('td.day[data-date]').last().attr('data-date');
-                        //             if(ts) {
-                        //                 self.loadEventDates(ts);
-                        //             }
-                        //         }, 10);
-                        //     });
-
-
-                        $('#pro-dashboard-container').find('[moe][initialized]').removeAttr('initialized');
-                        initMoes();
-
-                        // init fast load
-                        initFastLoad($('#pro-dashboard-container'));
-
-                        $(document)
-                            .off('click', '.dashboard-measurements.pagination a.page-link')
-                            .on('click', '.dashboard-measurements.pagination a.page-link', function () {
-                                $('#measurements-tab').text('Loading...').load('/pro-dashboard-measurements-tab/' + $(this).attr('data-target-page'), () => {
-                                    initMoes();
-                                    initFastLoad($('#measurements-tab'));
-                                });
-                                return false;
-                            });
-
-                        this.loadMeasurements();
-                        this.initLoadAppointments();
-                        this.onDateChange(this.getFormattedCurrentDate());
-                        this.selectedDate = this.getFormattedCurrentDate();
-                    }
-                });
-                /*// refresh once ticket popup is closed
-                $('body').off('stag-popup-closed')
-                $('body').on('stag-popup-closed', function() {
-                    if($('#pro-dashboard-container').length) {
-                        let activeTab = $('.nav-link.active[data-tab]').attr('data-tab');
-                        if(activeTab) {
-                            fastLoad('/?tab=' + activeTab);
+                    onChangeMonthYear: function (_year, _month) {
+                        let date = _year + '-' + (_month < 10 ? '0' : '') + _month + '-05';
+                        loadEventDates(date);
+                    },
+                    beforeShowDay: function (d) {
+                        if (datesWithEvents && datesWithEvents.indexOf(formatDate(d)) !== -1) {
+                            return [true, 'has-events'];
                         }
-                    }
-                });*/
-                // ticket-popup
-                $(document)
-                    .off('click', '.ticket-popup-trigger')
-                    .on('click', '.ticket-popup-trigger', function () {
-                        showMask();
-                        window.noMc = true;
-                        $.get(this.href, (_data) => {
-                            $('.ticket-popup').html(_data);
-                            showStagPopup('ticket-popup');
-                            $('.ticket-popup .stag-popup.stag-slide').attr('close-all-with-self', 1);
-                            runMCInitializer('patient-tickets'); // run specific mc initer
-                            hideMask();
-                        });
-                        return false;
-                    });
+                        return [true, 'no-events'];
+                    },
+                    defaultDate: 0
+                });
+
+                onDateChange(getFormattedCurrentDate());
+                selectedDate = getFormattedCurrentDate();
 
                 $(document)
                     .off('click', '.ack-client-pro-change')
@@ -767,6 +501,10 @@
                         }, 'json');
                         return false;
                     });
+
+                addMCHook('refreshDashboardAppointments', function() {
+                    onDateChange(selectedDate);
+                });
             }
 
             addMCInitializer('pro-dashboard', init, '#pro-dashboard-container');

+ 0 - 17
resources/views/app/mcp/dashboard/appointment-change-status.blade.php

@@ -1,17 +0,0 @@
-<div class="ml-2" moe relative>
-    <a href="#" start show><i class="fa fa-edit"></i></a>
-    <form url="/api/appointment/updateStatus">
-        <input type="hidden" name="uid" :value="event.uid">
-        <p class="text-nowrap mb-2 font-weight-bold text-secondary">Change appointment status</p>
-        <select name="status" class="form-control form-control-sm input-sm bg-light mb-2">
-            <option value="PENDING" :selected="event.status === 'PENDING'">PENDING</option>
-            <option value="CONFIRMED" :selected="event.status === 'CONFIRMED'">CONFIRMED</option>
-            <option value="CANCELLED" :selected="event.status === 'CANCELLED'">CANCELLED</option>
-            <option value="COMPLETED" :selected="event.status === 'COMPLETED'">COMPLETED</option>
-        </select>
-        <div class="mb-0">
-            <button class="btn btn-primary btn-sm" submit>Submit</button>
-            <button class="btn btn-default border btn-sm" cancel>Cancel</button>
-        </div>
-    </form>
-</div>

+ 96 - 0
resources/views/app/mcp/dashboard/appointments-list.blade.php

@@ -0,0 +1,96 @@
+@if(@$appointments && count($appointments))
+    <table class="mb-0 table table-sm table-bordered appointments">
+        @foreach($appointments as $appointment)
+            <tr class="{{$appointment->bgColor}}">
+                <td>
+                    <a href="/patients/view/{{$appointment->clientUid}}" class="font-weight-bold d-block">
+                        {{$appointment->clientName }}
+                    </a>
+                    <div class="mt-1">
+                        {{ $appointment->friendlyStartTime }} - {{ $appointment->friendlyEndTime }}
+                        <span class="text-secondary">{{ friendly_timezone($appointment->timezone) }}</span>
+                    </div>
+                    <a href="'/patients/view/{{$appointment->clientUid}}/calendar/{{$appointment->uid}}"
+                       class="d-block mt-1">
+                        <i class="fa fa-edit"></i>
+                    </a>
+                    @if($appointment->title)
+                        <span class="d-inline-block mt-1 text-secondary text-sm">
+                            {{ $appointment->title }}
+                        </span>
+                    @endif
+                </td>
+                <td>
+                    <div class="d-flex flex-column">
+                        <div class="d-flex align-items-baseline flex-nowrap">
+                            @if($appointment->status === 'PENDING')
+                                <div class="text-warning-mellow font-weight-bold text-nowrap">
+                                    <i class="fa fa-exclamation-triangle"></i>
+                                    Pending
+                                </div>
+                            @elseif($appointment->status === 'CONFIRMED')
+                                <div class="text-success font-weight-bold text-nowrap">
+                                    <i class="fa fa-check"></i>
+                                    Confirmed
+                                </div>
+                            @elseif($appointment->status === 'CANCELLED')
+                                <div class="text-danger font-weight-bold text-nowrap">
+                                    <i class="fa fa-stop"></i>
+                                    Cancelled
+                                </div>
+                            @elseif($appointment->status === 'COMPLETED')
+                                <div class="text-success font-weight-bold text-nowrap">
+                                    <i class="far fa-calendar-check"></i>
+                                    Completed
+                                </div>
+                            @endif
+                            <div class="ml-2" moe relative>
+                                <a href="#" start show><i class="fa fa-edit"></i></a>
+                                <form url="/api/appointment/updateStatus" hook="refreshDashboardAppointments">
+                                    <input type="hidden" name="uid" value="{{$appointment->uid}}">
+                                    <p class="text-nowrap mb-2 font-weight-bold text-secondary">Change appointment status</p>
+                                    <select name="status" class="form-control form-control-sm input-sm bg-light mb-2">
+                                        <option value="PENDING" {{$appointment->status === 'PENDING' ? 'selected' : ''}}>PENDING</option>
+                                        <option value="CONFIRMED" {{$appointment->status === 'CONFIRMED' ? 'selected' : ''}}>CONFIRMED</option>
+                                        <option value="CANCELLED" {{$appointment->status === 'CANCELLED' ? 'selected' : ''}}>CANCELLED</option>
+                                        <option value="COMPLETED" {{$appointment->status === 'COMPLETED' ? 'selected' : ''}}>COMPLETED</option>
+                                    </select>
+                                    <div class="mb-0">
+                                        <button class="btn btn-primary btn-sm" submit>Submit</button>
+                                        <button class="btn btn-default border btn-sm" cancel>Cancel</button>
+                                    </div>
+                                </form>
+                            </div>
+                        </div>
+                        @if($from === date('Y-m-d'))
+                            <div class="{{$appointment->started ? 'text-danger': 'text-secondary'}}">
+                                {{ $appointment->inHowManyHours }}
+                            </div>
+                        @endif
+                    </div>
+                </td>
+                <td>
+                    <div>
+                        @if($appointment->coverage === 'YES')
+                            <b class="text-success">Covered</b>
+                        @elseif($appointment->coverage === 'NO')
+                            <b class="text-danger">Not Covered</b>
+                        @else
+                            <b v-else class="text-warning-mellow">Pending</b>
+                        @endif
+                    </div>
+                </td>
+            </tr>
+        @endforeach
+    </table>
+@else
+    @if(@$from)
+        <div class="bg-light p-3 text-secondary border bounded">
+            <span>You have no appointments on <b>{{ $from }}</b></span>
+        </div>
+    @else
+        <div class="bg-light p-3 text-secondary border bounded">
+            Please select a date from the calendar on the left
+        </div>
+    @endif
+@endif

+ 45 - 30
resources/views/app/mcp/dashboard/measurements-pending-stamping.blade.php

@@ -1,37 +1,51 @@
+<div id="dashboard-measurements-pending-stamping">
 @if($measurementsPendingStamping && count($measurementsPendingStamping))
     <table class="table table-sm table-striped mb-0">
-            <thead>
+        <thead>
+        <tr>
+            <th class="border-bottom-0 border-top-0 text-secondary">Patient</th>
+            <th class="border-bottom-0 border-top-0 text-secondary">Care Month</th>
+            <th class="border-bottom-0 border-top-0 text-secondary">Type</th>
+            <th class="border-bottom-0 border-top-0 text-secondary">Value</th>
+            <th class="border-bottom-0 border-top-0 text-secondary">Timestamp</th>
+        </tr>
+        </thead>
+        <tbody>
+        @foreach($measurementsPendingStamping as $row)
             <tr>
-                <th class="border-bottom-0 border-top-0 text-secondary">Patient</th>
-                <th class="border-bottom-0 border-top-0 text-secondary">Care Month</th>
-                <th class="border-bottom-0 border-top-0 text-secondary">Meas.</th>
+                <td class="pl-2">
+                    <a href="{{ route('patients.view.dashboard', $row->client) }}">
+                        {{$row->client->displayName()}}
+                    </a>
+                </td>
+                <td>
+                    <a native target="_blank"
+                       open-in-stag-popup
+                       update-parent
+                       update-target="#dashboard-measurements-pending-stamping"
+                       mc-initer="cm-matrix-{{$row->client->id}}"
+                       title="Care Month Matrix: {{date('M Y', strtotime($row->careMonth->start_date))}}"
+                       href="/patient-care-month-matrix/{{$row->careMonth->uid}}">
+                        {{ friendly_month($row->careMonth->start_date) }}
+                    </a>
+                </td>
+                <td class="text-nowrap">
+                    {{$row->label}}
+                </td>
+                <td>
+                    @if($row->label === 'BP')
+                        {{ $row->sbp_mm_hg }}/{{ $row->dbp_mm_hg }}
+                    @elseif($row->label === 'Wt. (lbs.)')
+                        {{ round(floatval($row->numeric_value), 2) }}
+                    @endif
+                </td>
+                <td class="text-secondary">
+                    {{ friendly_date_time_short_with_tz_from_timestamp_divide1000($row->ts, 'EASTERN') }} EST
+                </td>
             </tr>
-            </thead>
-            <tbody>
-            @foreach($measurementsPendingStamping as $row)
-                <tr>
-                    <td class="pl-2">
-                        <a href="{{ route('patients.view.dashboard', $row->patient) }}">
-                            {{$row->patient->displayName()}}
-                        </a>
-                    </td>
-                    <td>
-                        <a native target="_blank"
-                           open-in-stag-popup
-                           update-parent
-                           mc-initer="cm-matrix-{{$row->patient->id}}"
-                           title="Care Month Matrix: {{date('M Y', strtotime($row->start_date))}}"
-                           href="/patient-care-month-matrix/{{$row->uid}}">
-                            {{ friendly_month($row->start_date) }}
-                        </a>
-                    </td>
-                    <td>
-                        {{ $row->rm_num_measurements_not_stamped_by_mcp }}
-                    </td>
-                </tr>
-            @endforeach
-            </tbody>
-        </table>
+        @endforeach
+        </tbody>
+    </table>
     <div class="m-2">
         {{ $measurementsPendingStamping->onEachSide(0)->withQueryString()->links() }}
     </div>
@@ -40,3 +54,4 @@
         No measurement pending stamping
     </div>
 @endif
+</div>

+ 4 - 0
resources/views/app/patient/dashboard.blade.php

@@ -691,6 +691,10 @@
                         return false;
                     });
 
+                addMCHook('onHxPopupClosure', function() {
+                    closeStagPopup();
+                });
+
             }
             addMCInitializer('patient-dashboard-devices', init, '#patient-dashboard-devices');
 

+ 23 - 3
resources/views/app/patient/devices.blade.php

@@ -51,8 +51,9 @@
                 <thead>
                 <tr>
                     <th class="px-2 text-secondary">Created</th>
-                    <th class="px-2 text-secondary w-25">Category</th>
-                    <th class="px-2 text-secondary w-50">IMEI</th>
+                    <th class="px-2 text-secondary">Category</th>
+                    <th class="px-2 text-secondary">IMEI</th>
+                    <th class="px-2 text-secondary">Last Measurement</th>
                     <th class="px-2 text-secondary"></th>
                     <th class="px-2 text-secondary"></th>
                 </tr>
@@ -63,6 +64,25 @@
                         <td class="px-2 text-nowrap">{{ friendly_date_time($device->device->created_at) }}</td>
                         <td class="px-2">{{ $device->device->category }}</td>
                         <td class="px-2"><pre class="m-0">{{ $device->device->imei }}</pre></td>
+                        <td class="px-2">
+                            <?php $lastMeasurement = $device->lastDeviceMeasurement(); ?>
+                            @if($lastMeasurement)
+                                @if($lastMeasurement->is_cellular_zero)
+                                    <i class="font-size-11 fa fa-rss"></i>
+                                @elseif($lastMeasurement->label === 'BP')
+                                    {{ $lastMeasurement->sbp_mm_hg }} / {{ $lastMeasurement->dbp_mm_hg }}
+                                @elseif($lastMeasurement->label === 'Wt. (lbs.)')
+                                    {{ round($lastMeasurement->numeric_value, 2) }} lbs
+                                @else
+                                    {{ $lastMeasurement->value }}
+                                @endif
+                                <div>
+                                    <i class="far fa-calendar-check"></i> <span class="text-secondary">{{ friendly_date_time($lastMeasurement->created_at) }}</span>
+                                </div>
+                            @else
+                                <small class="text-muted">-</small>
+                            @endif
+                        </td>
                         <td>
                             <div moe relative>
                                 <a start show class="on-hover-opaque">Deactivate</a>
@@ -76,7 +96,7 @@
                                 </form>
                             </div>
                         </td>
-                        <td>
+                        <td class="text-nowrap">
                             @include('app.generic-bills.modal', ['entityType' => 'ClientBDTDevice', 'entityUid' => $device->uid])
                         </td>
                     </tr>

+ 95 - 71
resources/views/app/patient/partials/appointments.blade.php

@@ -4,81 +4,105 @@
         <span class="mx-2 text-secondary">|</span>
         <a href="/patients/view/{{$patient->uid}}/calendar">Calendar</a>
     </div>
-    <table class="table table-sm border-0 m-0">
-        <tbody>
-        @foreach($patient->appointmentsFromLastWeek as $appointment)
-            <tr>
-                <td class="text-black p-0 border-0 pb-1">
-                    <div class="pb-0 d-flex align-items-center flex-wrap">
-                        <a class="on-hover-opaque mr-1"
-                           href="/patients/view/{{$patient->uid}}/calendar/{{$appointment->uid}}"
-                           title="Update">
-                            <i class="font-size-11 fa fa-edit text-primary"></i>
+    @if(!$patient->appointmentsFromLastWeek || count($patient->appointmentsFromLastWeek) === 0)
+        <div>
+            <td class="text-secondary p-0 border-0">
+                No recent appointments
+            </td>
+        </div>
+    @else
+        <table class="mb-0 table table-sm table-bordered appointments">
+            @foreach($patient->appointmentsFromLastWeek as $appointment)
+                <?php
+                $bgColor = 'bg-white';
+                if($appointment->status === 'COMPLETED') {
+                    $bgColor = 'event-bg-green';
+                }
+                else if($appointment->status === 'CANCELLED') {
+                    $bgColor = 'event-bg-gray';
+                }
+                ?>
+                <tr class="{{$bgColor}}">
+                    <td class="align-middle">
+                        <a href="/patients/view/{{$appointment->client->uid}}" class="font-weight-bold d-block">
+                            {{$appointment->client->displayName() }}
                         </a>
-                        <span class="mr-1 text-nowrap">{{ friendly_date_time($appointment->raw_date, false) }}</span>
-                        @if($appointment->raw_start_time)
-                            <span class="mr-1 text-nowrap">{{ friendly_time($appointment->raw_start_time, false) }}</span>
-                        @endif
-                        @if($appointment->timezone)
-                            <span class="text-secondary text-sm mr-1 text-nowrap">({{ str_replace("_", " ", $appointment->timezone) }})</span>
-                        @endif
-                        <span class="mr-1">/</span>
-                        <span class="font-weight-bold mr-1 text-nowrap">{{$appointment->pro->displayName()}}</span>
-                        <div moe>
-                            <a href="#" start show class="text-sm">({{ $appointment->status }})</a>
-                            <form url="/api/appointment/updateStatus">
-                                <input type="hidden" name="uid" value="{{ $appointment->uid }}">
-                                <div class="mb-2">
-                                    <select class="form-control form-control-sm bg-light" name="status" required>
-                                        <option value="">-- select --</option>
-                                        <option {{ $appointment->status === 'PENDING' ? 'selected' : '' }} value="PENDING">PENDING</option>
-                                        <option {{ $appointment->status === 'CONFIRMED' ? 'selected' : '' }} value="CONFIRMED">CONFIRMED</option>
-                                        <option {{ $appointment->status === 'CANCELLED' ? 'selected' : '' }} value="CANCELLED">CANCELLED</option>
-                                        <option {{ $appointment->status === 'COMPLETED' ? 'selected' : '' }} value="COMPLETED">COMPLETED</option>
-                                    </select>
-                                </div>
-                                <div>
-                                    <button submit class="btn btn-sm btn-primary mr-1">Update</button>
-                                    <button cancel class="btn btn-sm btn-default border">Cancel</button>
-                                </div>
-                            </form>
+                        <div class="mt-1">
+                            {{ friendly_time($appointment->raw_start_time) }} - {{ friendly_time($appointment->raw_end_time) }}
+                            <span class="text-secondary">{{ friendly_timezone($appointment->timezone) }}</span>
                         </div>
-                        @if($appointment->status === 'PENDING')
-                            <div moe class="ml-2">
-                                <a href="#" start show class="text-sm font-weight-bold">Req. Conf.</a>
-                                <form url="/api/appointment/sendConfirmationRequestViaSms">
-                                    <input type="hidden" name="uid" value="{{ $appointment->uid }}">
-                                    <div class="mb-2">
-                                        <label for="" class="text-sm text-secondary mb-1">Cell Number</label>
-                                        <input type="text" class="form-control form-control-sm" name="toSmsNumber" value="{{$patient->cell_number}}" required>
+                        <a href="'/patients/view/{{$appointment->client->uid}}/calendar/{{$appointment->uid}}"
+                           class="d-block mt-1">
+                            <i class="fa fa-edit"></i>
+                        </a>
+                        @if($appointment->title)
+                            <span class="d-inline-block mt-1 text-secondary text-sm">
+                            {{ $appointment->title }}
+                        </span>
+                        @endif
+                    </td>
+                    <td class="align-middle">
+                        <div class="d-flex flex-column">
+                            <div class="d-flex align-items-baseline flex-nowrap">
+                                @if($appointment->status === 'PENDING')
+                                    <div class="text-warning-mellow font-weight-bold text-nowrap">
+                                        <i class="fa fa-exclamation-triangle"></i>
+                                        Pending
                                     </div>
-                                    <div>
-                                        <button submit class="btn btn-sm btn-primary mr-1">Send</button>
-                                        <button cancel class="btn btn-sm btn-default border">Cancel</button>
+                                @elseif($appointment->status === 'CONFIRMED')
+                                    <div class="text-success font-weight-bold text-nowrap">
+                                        <i class="fa fa-check"></i>
+                                        Confirmed
                                     </div>
-                                </form>
+                                @elseif($appointment->status === 'CANCELLED')
+                                    <div class="text-danger font-weight-bold text-nowrap">
+                                        <i class="fa fa-stop"></i>
+                                        Cancelled
+                                    </div>
+                                @elseif($appointment->status === 'COMPLETED')
+                                    <div class="text-success font-weight-bold text-nowrap">
+                                        <i class="far fa-calendar-check"></i>
+                                        Completed
+                                    </div>
+                                @endif
+                                <div class="ml-2" moe relative>
+                                    <a href="#" start show><i class="fa fa-edit"></i></a>
+                                    <form url="/api/appointment/updateStatus">
+                                        <input type="hidden" name="uid" value="{{$appointment->uid}}">
+                                        <p class="text-nowrap mb-2 font-weight-bold text-secondary">Change appointment
+                                            status</p>
+                                        <select name="status"
+                                                class="form-control form-control-sm input-sm bg-light mb-2">
+                                            <option value="PENDING" {{$appointment->status === 'PENDING' ? 'selected' : ''}}>
+                                                PENDING
+                                            </option>
+                                            <option value="CONFIRMED" {{$appointment->status === 'CONFIRMED' ? 'selected' : ''}}>
+                                                CONFIRMED
+                                            </option>
+                                            <option value="CANCELLED" {{$appointment->status === 'CANCELLED' ? 'selected' : ''}}>
+                                                CANCELLED
+                                            </option>
+                                            <option value="COMPLETED" {{$appointment->status === 'COMPLETED' ? 'selected' : ''}}>
+                                                COMPLETED
+                                            </option>
+                                        </select>
+                                        <div class="mb-0">
+                                            <button class="btn btn-primary btn-sm" submit>Submit</button>
+                                            <button class="btn btn-default border btn-sm" cancel>Cancel</button>
+                                        </div>
+                                    </form>
+                                </div>
                             </div>
-                        @endif
-                        <span class="text-sm ml-2">{{ $appointment->title ? $appointment->title : '' }}</span>
-                        {{--@if($appointment->title && $appointment->description)<span class="text-secondary mx-1">/</span>@endif--}}
-                        {{--<span class="text-sm">{{ $appointment->description ? $appointment->description : '' }}</span>--}}
-                    </div>
-                </td>
-            </tr>
-        @endforeach
-        @if(!$patient->appointmentsFromLastWeek || count($patient->appointmentsFromLastWeek) === 0)
-            <tr>
-                <td class="text-secondary p-0 border-0">
-                    No recent appointments
-                </td>
-            </tr>
-        @endif
-        <tr>
-            <td class="text-secondary pt-2 px-0 border-0">
-                <a href="/patients/view/{{$patient->uid}}/appointments/all/all">See all appointments</a>
-            </td>
-        </tr>
-        </tbody>
-    </table>
+                        </div>
+                    </td>
+                </tr>
+            @endforeach
+        </table>
+    @endif
+    <div class="mt-2">
+        <div class="text-secondary pt-2 px-0 border-0">
+            <a href="/patients/view/{{$patient->uid}}/appointments/all/all">See all appointments</a>
+        </div>
+    </div>
 </div>
 

+ 2 - 48
resources/views/app/patient/partials/measurements.blade.php

@@ -1,52 +1,6 @@
-<div class="mt-2 mb-3">
+<div class="mt-2 mb-3" id="patient-dashboard-measurements">
     <div class="d-flex align-items-center mb-2 py-2 border-top border-bottom">
         <h6 class="my-0 font-weight-bold text-secondary">Measurements</h6>
-
-        {{--
-        <span class="mx-2 text-secondary">|</span>
-        <div moe>
-            <a start show class="py-0 font-weight-normal">Add BP</a>
-            <form url="/api/measurement/createForBP">
-                <input type="hidden" name="clientUid" value="{{ $patient->uid }}">
-                <p class="font-weight-bold text-secondary mb-2">Add BP Measurement</p>
-                <div class="mb-2">
-                    <label class="text-secondary text-sm mb-1">Systolic BP (mmHg)</label>
-                    <input required autofocus type="number" class="form-control form-control-sm" name="sbpMmHg" value="" placeholder="Systolic BP">
-                </div>
-                <div class="mb-2">
-                    <label class="text-secondary text-sm mb-1">Diastolic BP (mmHg)</label>
-                    <input required autofocus type="number" class="form-control form-control-sm" name="dbpMmHg" value="" placeholder="Diastolic BP">
-                </div>
-                <div class="mb-2">
-                    <input required type="date" class="form-control form-control-sm" name="effectiveDate" max="{{ date('Y-m-d') }}" value="{{ date('Y-m-d') }}">
-                </div>
-                <div class="d-flex align-items-center">
-                    <button class="btn btn-sm btn-primary mr-2" submit>Save</button>
-                    <button class="btn btn-sm btn-default mr-2 border" cancel>Cancel</button>
-                </div>
-            </form>
-        </div>
-        <span class="mx-2 text-secondary">|</span>
-        <div moe>
-            <a start show class="py-0 font-weight-normal">Add Weight</a>
-            <form url="/api/measurement/create">
-                <input type="hidden" name="clientUid" value="{{ $patient->uid }}">
-                <input type="hidden" name="label" value="Wt. (lbs.)">
-                <p class="font-weight-bold text-secondary mb-2">Add Weight Measurement</p>
-                <div class="mb-2">
-                    <input required type="number" class="form-control form-control-sm" name="value" value="" placeholder="Weight">
-                </div>
-                <div class="mb-2">
-                    <input required type="date" class="form-control form-control-sm" name="effectiveDate" max="{{ date('Y-m-d') }}" value="{{ date('Y-m-d') }}">
-                </div>
-                <div class="d-flex align-items-center">
-                    <button class="btn btn-sm btn-primary mr-2" submit>Save</button>
-                    <button class="btn btn-sm btn-default mr-2 border" cancel>Cancel</button>
-                </div>
-            </form>
-        </div>
-        --}}
-
         <span class="mx-2 text-secondary">|</span>
         <a start show class="py-0 font-weight-normal"
            href="/patients/view/{{ $patient->uid }}/measurements">
@@ -76,7 +30,7 @@
                                     <a href="#" start show>
                                         <i class="fa fa-check text-secondary on-hover-opaque mr-2" title="Not Stamped. Click to stamp."></i>
                                     </a>
-                                    <form url="/api/measurement/stamp" class="width-300px">
+                                    <form url="/api/measurement/stamp" class="width-300px" target="#patient-dashboard-measurements">
                                         <input type="hidden" name="uid" value="{{$measurement->uid}}">
                                         <p class="mb-1">Stamp this measurement?</p>
                                         <div class="mb-2">

+ 87 - 0
resources/views/app/patient/segment-templates/_custom_items/edit.blade.php

@@ -0,0 +1,87 @@
+<div class="row">
+    <div class="col-9">
+        <div class="d-flex align-items-center mb-2">
+            <span class="font-weight-bold">My Custom Items</span>
+            <span class="mx-2 text-secondary">|</span>
+            <div moe>
+                <a href="#" start show>Add</a>
+                <div custom-item-form url="/api/sectionTemplateCustomItem/create">
+                    <div class="mb-2">
+                        <input type="text" placeholder="Label"
+                               v-model="newCustomItemLabel"
+                               class="form-control form-control-sm label_new_custom_item">
+                    </div>
+                    <div>
+                        <button type="button" class="btn btn-sm btn-primary mr-1"
+                                v-on:click.prevent="saveCustomItem(newCustomItemLabel)">Submit</button>
+                        <button type="button" class="btn btn-sm btn-default border"
+                                v-on:click.prevent="cancelCustomItem()">Cancel</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row custom-items-container">
+            <div class="col-4" v-for="item in customFields" v-if="!item.other">
+                <label class="d-flex align-items-start mb-1">
+                    <input type="checkbox" class="mx-0 mt-1"
+                           v-model="item.value">
+                    <div class="ml-2 pr-3">
+                        <div>
+                            <span class="mr-2">@{{ item.label }}</span>
+                            <div moe relative no-mask v-show="item.value" >
+                                <a href="#" start show>
+                                    <i class="fa-comment" :class="item.comments ? 'fas' : 'far'"></i>
+                                </a>
+                                <div url="/nop" right>
+                                    <div class="mb-2">
+                                        <textarea class="form-control form-control-sm ns-custom-comment min-width-200px" v-model="item.comments"></textarea>
+                                    </div>
+                                    <div class="">
+                                        <button type="button" class="btn btn-sm btn-primary" cancel>Close</button>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <span v-show="item.value && item.comments"
+                              v-html="item.comments"
+                              class="text-sm text-secondary"></span>
+                    </div>
+                </label>
+            </div>
+        </div>
+    </div>
+    <div class="col-3 border-left">
+        <div class="d-flex align-items-center mb-2">
+            <span class="font-weight-bold">Other Custom Items</span>
+        </div>
+        <div class="custom-items-container">
+            <div v-for="item in customFields" v-if="item.other">
+                <label class="d-flex align-items-start mb-1">
+                    <input type="checkbox" class="mx-0 mt-1"
+                           v-model="item.value">
+                    <div class="ml-2 pr-3">
+                        <div>
+                            <span class="mr-2">@{{ item.label }}</span>
+                            <div moe relative no-mask v-show="item.value" >
+                                <a href="#" start show>
+                                    <i class="fa-comment" :class="item.comments ? 'fas' : 'far'"></i>
+                                </a>
+                                <div url="/nop" right>
+                                    <div class="mb-2">
+                                        <textarea class="form-control form-control-sm ns-custom-comment min-width-200px" v-model="item.comments"></textarea>
+                                    </div>
+                                    <div class="">
+                                        <button type="button" class="btn btn-sm btn-primary" cancel>Close</button>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <span v-show="item.value && item.comments"
+                              v-html="item.comments"
+                              class="text-sm text-secondary"></span>
+                    </div>
+                </label>
+            </div>
+        </div>
+    </div>
+</div>

+ 2 - 1
resources/views/app/patient/segment-templates/history_family/edit.blade.php

@@ -50,7 +50,8 @@ if(!$contentData) {
 
 <div class="p-3 border-top mt-3 mcp-theme-1">
     <div {{!!$segment ? 'visit-moe' : 'moe'}} close-on-save close-on-cancel class="d-block">
-        <form show url="/api/visitPoint/upsertGlobalSingleton" class="mcp-theme-1">
+        <form show url="/api/visitPoint/upsertGlobalSingleton" class="mcp-theme-1"
+                    {{!$segment ? 'hook=onHxPopupClosure' : ''}}>
             @if(!!@$segment)
                 <input type="hidden" name="segmentUid" value="<?= $segment->uid ?>">
             @else

+ 30 - 59
resources/views/app/patient/segment-templates/history_social/edit.blade.php

@@ -59,7 +59,8 @@ for ($i = 0; $i < count($fields); $i++) {
 
 <div class="p-3 border-top mt-3 mcp-theme-1">
     <div {{!!$segment ? 'visit-moe' : 'moe'}} close-on-save close-on-cancel class="d-block">
-        <form show url="/api/visitPoint/upsertGlobalSingleton" class="mcp-theme-1">
+        <form show url="/api/visitPoint/upsertGlobalSingleton" class="mcp-theme-1"
+                {{!$segment ? 'hook=onHxPopupClosure' : ''}}>
             @if(!!@$segment)
                 <input type="hidden" name="segmentUid" value="<?= $segment->uid ?>">
             @else
@@ -113,59 +114,7 @@ for ($i = 0; $i < count($fields); $i++) {
                 </div>
                 <div class="row border-top pt-3">
                     <div class="col-12">
-                        <div class="d-flex align-items-center mb-2">
-                            <span class="font-weight-bold">Custom Items</span>
-                            <span class="mx-2 text-secondary">|</span>
-                            <div moe>
-                                <a href="#" start show>Add</a>
-                                <div custom-item-form url="/api/sectionTemplateCustomItem/create">
-                                    <div class="mb-2">
-                                        <input type="text" placeholder="Label"
-                                               v-model="newCustomItemLabel"
-                                               class="form-control form-control-sm label_new_custom_item">
-                                    </div>
-                                    <div>
-                                        <button type="button" class="btn btn-sm btn-primary mr-1"
-                                                v-on:click.prevent="saveCustomItem(newCustomItemLabel)">Submit</button>
-                                        <button type="button" class="btn btn-sm btn-default border"
-                                                v-on:click.prevent="cancelCustomItem()">Cancel</button>
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-
-                        {{-- custom items --}}
-                        <div class="d-flex align-items-start flex-wrap custom-items-container">
-                            <div class="w-25" v-for="item in customFields">
-                                <label class="d-flex align-items-start mb-1">
-                                    <input type="checkbox" class="mx-0 mt-1"
-                                           v-model="item.value">
-                                    <div class="ml-2 pr-3">
-                                        <div>
-                                            <span class="mr-2">@{{ item.label }}</span>
-                                            <div moe relative no-mask v-show="item.value" >
-                                                <a href="#" start show>
-                                                    <i class="fa-comment" :class="item.comments ? 'fas' : 'far'"></i>
-                                                </a>
-                                                <div url="/nop" right>
-                                                    <div class="mb-2">
-                                                        <textarea class="form-control form-control-sm ns-custom-comment min-width-200px" v-model="item.comments"></textarea>
-                                                    </div>
-                                                    <div class="">
-                                                        <button type="button" class="btn btn-sm btn-primary" cancel>Close</button>
-                                                    </div>
-                                                </div>
-                                            </div>
-                                        </div>
-                                        <span v-show="item.value && item.comments"
-                                              v-html="item.comments"
-                                              class="text-sm text-secondary">
-                                        </span>
-                                    </div>
-                                </label>
-                            </div>
-                        </div>
-
+                        @include('app.patient.segment-templates._custom_items.edit')
                     </div>
                 </div>
                 <hr class="m-neg-4">
@@ -189,23 +138,40 @@ for ($i = 0; $i < count($fields); $i++) {
 
             let model = <?= $contentData ? json_encode($contentData) : '{}' ?>;
             model.newCustomItemLabel = '';
-            let customFields = <?= json_encode($customFields) ?>;
+            let myCustomFields = <?= json_encode($customFields) ?>;
             if(!model.customFields) {
                 model.customFields = [];
             }
-            for (let i = 0; i < customFields.length; i++) {
+            for (let i = 0; i < myCustomFields.length; i++) {
                 let found = model.customFields.filter(function(_item) {
-                    return _item.label === customFields[i];
+                    return _item.label === myCustomFields[i];
                 }).length;
                 if(!found) {
                     model.customFields.push({
-                        label: customFields[i],
+                        label: myCustomFields[i],
                         value: '',
                         comments: '',
                     })
                 }
             }
 
+            // if not own AND not active - remove from model.customFields
+            for (let i = model.customFields.length - 1; i >= 0 ; i--) {
+                if(myCustomFields.indexOf(model.customFields[i].label) === -1) {
+                    if(!!model.customFields[i].value) {
+                        model.customFields[i].other = true;
+                    }
+                    else {
+                        model.customFields.splice(i, 1);
+                    }
+                }
+            }
+
+            // sort by label
+            model.customFields.sort(function (a, b) {
+                return a.label.localeCompare(b.label);
+            });
+
             new Vue({
                 el: '#edit-univ_history_social-container',
                 delimiters: ["@{{","}}"],
@@ -237,7 +203,12 @@ for ($i = 0; $i < count($fields); $i++) {
                             if(_data && _data.success) {
                                 hideMoeFormMask();
                                 $('[custom-item-form]').hide();
-                                $('.custom-items-container').closest('.visit-segment').find('.refresh-segment').trigger('click');
+                                // $('.custom-items-container').closest('.visit-segment').find('.refresh-segment').trigger('click');
+                                self.customFields.push({
+                                    label: _label,
+                                    value: '',
+                                    comments: '',
+                                });
                             }
                             else {
                                 toastr.error(_data.message);

+ 33 - 60
resources/views/app/patient/segment-templates/history_surgical/edit.blade.php

@@ -7,6 +7,8 @@ use App\Models\Note;
 /** @var Note $note */
 /** @var Segment $segment */
 
+if(!@$segment) $segment = null;
+
 $fields = [
     [
         "" => ["Aneurysm repair", "Appendectomy", "Back surgery", "Bariatric surgery/gastric bypass", "Bilateral tubal ligation", "Breast resection/mastectomy", "CABG", "Carotid endarterectomy/stent", "Carpal tunnel release surgery",]
@@ -53,8 +55,9 @@ for ($i = 0; $i < count($fields); $i++) {
 ?>
 
 <div class="p-3 border-top mt-3 mcp-theme-1">
-    <div visit-moe close-on-save close-on-cancel class="d-block">
-        <form show url="/api/visitPoint/upsertGlobalSingleton" class="mcp-theme-1">
+    <div {{!!$segment ? 'visit-moe' : 'moe'}} close-on-save close-on-cancel class="d-block">
+        <form show url="/api/visitPoint/upsertGlobalSingleton" class="mcp-theme-1"
+                {{!$segment ? 'hook=onHxPopupClosure' : ''}}>
             @if(!!@$segment)
                 <input type="hidden" name="segmentUid" value="<?= $segment->uid ?>">
             @else
@@ -111,59 +114,7 @@ for ($i = 0; $i < count($fields); $i++) {
                 </div>
                 <div class="row border-top pt-3">
                     <div class="col-12">
-                        <div class="d-flex align-items-center mb-2">
-                            <span class="font-weight-bold">Custom Items</span>
-                            <span class="mx-2 text-secondary">|</span>
-                            <div moe>
-                                <a href="#" start show>Add</a>
-                                <div custom-item-form url="/api/sectionTemplateCustomItem/create">
-                                    <div class="mb-2">
-                                        <input type="text" placeholder="Label"
-                                               v-model="newCustomItemLabel"
-                                               class="form-control form-control-sm label_new_custom_item">
-                                    </div>
-                                    <div>
-                                        <button type="button" class="btn btn-sm btn-primary mr-1"
-                                                v-on:click.prevent="saveCustomItem(newCustomItemLabel)">Submit</button>
-                                        <button type="button" class="btn btn-sm btn-default border"
-                                                v-on:click.prevent="cancelCustomItem()">Cancel</button>
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-
-                        {{-- custom items --}}
-                        <div class="d-flex align-items-start flex-wrap custom-items-container">
-                            <div class="w-25" v-for="item in customFields">
-                                <label class="d-flex align-items-start mb-1">
-                                    <input type="checkbox" class="mx-0 mt-1"
-                                           v-model="item.value">
-                                    <div class="ml-2 pr-3">
-                                        <div>
-                                            <span class="mr-2">@{{ item.label }}</span>
-                                            <div moe relative no-mask v-show="item.value" >
-                                                <a href="#" start show>
-                                                    <i class="fa-comment" :class="item.comments ? 'fas' : 'far'"></i>
-                                                </a>
-                                                <div url="/nop" right>
-                                                    <div class="mb-2">
-                                                        <textarea class="form-control form-control-sm ns-custom-comment min-width-200px" v-model="item.comments"></textarea>
-                                                    </div>
-                                                    <div class="">
-                                                        <button type="button" class="btn btn-sm btn-primary" cancel>Close</button>
-                                                    </div>
-                                                </div>
-                                            </div>
-                                        </div>
-                                        <span v-show="item.value && item.comments"
-                                              v-html="item.comments"
-                                              class="text-sm text-secondary">
-                                        </span>
-                                    </div>
-                                </label>
-                            </div>
-                        </div>
-
+                        @include('app.patient.segment-templates._custom_items.edit')
                     </div>
                 </div>
                 <hr class="m-neg-4">
@@ -187,23 +138,40 @@ for ($i = 0; $i < count($fields); $i++) {
 
             let model = <?= $contentData ? json_encode($contentData) : '{}' ?>;
             model.newCustomItemLabel = '';
-            let customFields = <?= json_encode($customFields) ?>;
+            let myCustomFields = <?= json_encode($customFields) ?>;
             if(!model.customFields) {
                 model.customFields = [];
             }
-            for (let i = 0; i < customFields.length; i++) {
+            for (let i = 0; i < myCustomFields.length; i++) {
                 let found = model.customFields.filter(function(_item) {
-                    return _item.label === customFields[i];
+                    return _item.label === myCustomFields[i];
                 }).length;
                 if(!found) {
                     model.customFields.push({
-                        label: customFields[i],
+                        label: myCustomFields[i],
                         value: '',
                         comments: '',
                     })
                 }
             }
 
+            // if not own AND not active - remove from model.customFields
+            for (let i = model.customFields.length - 1; i >= 0 ; i--) {
+                if(myCustomFields.indexOf(model.customFields[i].label) === -1) {
+                    if(!!model.customFields[i].value) {
+                        model.customFields[i].other = true;
+                    }
+                    else {
+                        model.customFields.splice(i, 1);
+                    }
+                }
+            }
+
+            // sort by label
+            model.customFields.sort(function (a, b) {
+                return a.label.localeCompare(b.label);
+            });
+
             new Vue({
                 el: '#edit-univ_history_surgical-container',
                 delimiters: ["@{{","}}"],
@@ -235,7 +203,12 @@ for ($i = 0; $i < count($fields); $i++) {
                             if(_data && _data.success) {
                                 hideMoeFormMask();
                                 $('[custom-item-form]').hide();
-                                $('.custom-items-container').closest('.visit-segment').find('.refresh-segment').trigger('click');
+                                // $('.custom-items-container').closest('.visit-segment').find('.refresh-segment').trigger('click');
+                                self.customFields.push({
+                                    label: _label,
+                                    value: '',
+                                    comments: '',
+                                });
                             }
                             else {
                                 toastr.error(_data.message);

+ 30 - 59
resources/views/app/patient/segment-templates/past_medical_history/edit.blade.php

@@ -69,7 +69,8 @@ for ($i = 0; $i < count($fields); $i++) {
 
 <div class="p-3 border-top mt-3 mcp-theme-1">
     <div {{!!$segment ? 'visit-moe' : 'moe'}} close-on-save close-on-cancel class="d-block">
-        <form show url="/api/visitPoint/upsertGlobalSingleton" class="mcp-theme-1">
+        <form show url="/api/visitPoint/upsertGlobalSingleton" class="mcp-theme-1"
+                {{!$segment ? 'hook=onHxPopupClosure' : ''}}>
             @if(!!@$segment)
                 <input type="hidden" name="segmentUid" value="<?= $segment->uid ?>">
             @else
@@ -153,59 +154,7 @@ for ($i = 0; $i < count($fields); $i++) {
                 </div>
                 <div class="row border-top pt-3">
                     <div class="col-12">
-                        <div class="d-flex align-items-center mb-2">
-                            <span class="font-weight-bold">Custom Items</span>
-                            <span class="mx-2 text-secondary">|</span>
-                            <div moe>
-                                <a href="#" start show>Add</a>
-                                <div custom-item-form url="/api/sectionTemplateCustomItem/create">
-                                    <div class="mb-2">
-                                        <input type="text" placeholder="Label"
-                                               v-model="newCustomItemLabel"
-                                               class="form-control form-control-sm label_new_custom_item">
-                                    </div>
-                                    <div>
-                                        <button type="button" class="btn btn-sm btn-primary mr-1"
-                                                v-on:click.prevent="saveCustomItem(newCustomItemLabel)">Submit</button>
-                                        <button type="button" class="btn btn-sm btn-default border"
-                                                v-on:click.prevent="cancelCustomItem()">Cancel</button>
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-
-                        {{-- custom items --}}
-                        <div class="d-flex align-items-start flex-wrap custom-items-container">
-                            <div class="w-25" v-for="item in customFields">
-                                <label class="d-flex align-items-start mb-1">
-                                    <input type="checkbox" class="mx-0 mt-1"
-                                           v-model="item.value">
-                                    <div class="ml-2 pr-3">
-                                        <div>
-                                            <span class="mr-2">@{{ item.label }}</span>
-                                            <div moe relative no-mask v-show="item.value" >
-                                                <a href="#" start show>
-                                                    <i class="fa-comment" :class="item.comments ? 'fas' : 'far'"></i>
-                                                </a>
-                                                <div url="/nop" right>
-                                                    <div class="mb-2">
-                                                        <textarea class="form-control form-control-sm ns-custom-comment min-width-200px" v-model="item.comments"></textarea>
-                                                    </div>
-                                                    <div class="">
-                                                        <button type="button" class="btn btn-sm btn-primary" cancel>Close</button>
-                                                    </div>
-                                                </div>
-                                            </div>
-                                        </div>
-                                        <span v-show="item.value && item.comments"
-                                              v-html="item.comments"
-                                              class="text-sm text-secondary">
-                                        </span>
-                                    </div>
-                                </label>
-                            </div>
-                        </div>
-
+                        @include('app.patient.segment-templates._custom_items.edit')
                     </div>
                 </div>
                 <hr class="m-neg-4">
@@ -229,23 +178,40 @@ for ($i = 0; $i < count($fields); $i++) {
 
             let model = <?= $contentData ? json_encode($contentData) : '{}' ?>;
             model.newCustomItemLabel = '';
-            let customFields = <?= json_encode($customFields) ?>;
+            let myCustomFields = <?= json_encode($customFields) ?>;
             if(!model.customFields) {
                 model.customFields = [];
             }
-            for (let i = 0; i < customFields.length; i++) {
+            for (let i = 0; i < myCustomFields.length; i++) {
                 let found = model.customFields.filter(function(_item) {
-                    return _item.label === customFields[i];
+                    return _item.label === myCustomFields[i];
                 }).length;
                 if(!found) {
                     model.customFields.push({
-                        label: customFields[i],
+                        label: myCustomFields[i],
                         value: '',
                         comments: '',
                     })
                 }
             }
 
+            // if not own AND not active - remove from model.customFields
+            for (let i = model.customFields.length - 1; i >= 0 ; i--) {
+                if(myCustomFields.indexOf(model.customFields[i].label) === -1) {
+                    if(!!model.customFields[i].value) {
+                        model.customFields[i].other = true;
+                    }
+                    else {
+                        model.customFields.splice(i, 1);
+                    }
+                }
+            }
+
+            // sort by label
+            model.customFields.sort(function (a, b) {
+                return a.label.localeCompare(b.label);
+            });
+
             new Vue({
                 el: '#edit-univ_history_past_medical-container',
                 delimiters: ["@{{","}}"],
@@ -277,7 +243,12 @@ for ($i = 0; $i < count($fields); $i++) {
                             if(_data && _data.success) {
                                 hideMoeFormMask();
                                 $('[custom-item-form]').hide();
-                                $('.custom-items-container').closest('.visit-segment').find('.refresh-segment').trigger('click');
+                                // $('.custom-items-container').closest('.visit-segment').find('.refresh-segment').trigger('click');
+                                self.customFields.push({
+                                    label: _label,
+                                    value: '',
+                                    comments: '',
+                                });
                             }
                             else {
                                 toastr.error(_data.message);

+ 5 - 3
resources/views/layouts/patient.blade.php

@@ -318,6 +318,7 @@ $isVisitNote = ($routeName === 'patients.view.notes.view.dashboard' && @$note &&
 					</div>
 				@endif
 				<div class="card {{$isVisitNote ? 'card m-0 border-0 rounded-0' : 'my-3'}}" id="patient-header">
+					<div id="patient-header-content">
 					<div class="card-header @if($patient->client_engagement_status_category == 'DUMMY') alert-warning @endif py-1 hide-inside-ticket-popup">
 						<?php
 						$thumbnail = $patient->profile_picture_base64;
@@ -386,7 +387,7 @@ $isVisitNote = ($routeName === 'patients.view.notes.view.dashboard' && @$note &&
 												<b>{{$patient->client_engagement_status_category ? ucwords(strtolower(str_replace('_', ' ', $patient->client_engagement_status_category == 'DUMMY' ? 'Test Chart' : $patient->client_engagement_status_category))) : '-'}}</b>
 												<div moe class="ml-2 hide-inside-popup">
 													<a start show><i class="fa fa-edit"></i></a>
-													<form url="/api/client/updateClientEngagementAssessmentStatus" class="mcp-theme-1">
+													<form url="/api/client/updateClientEngagementAssessmentStatus" class="mcp-theme-1" target="#patient-header-content">
 														<input type="hidden" name="uid" value="{{$patient->uid}}">
 														<div class="mb-2">
 															<label class="mb-1 text-secondary text-sm">Status</label>
@@ -697,7 +698,7 @@ $isVisitNote = ($routeName === 'patients.view.notes.view.dashboard' && @$note &&
                                             <div moe relative>
                                                 <button class="col-2-button" start show><i class="fa fa-plus text-sm text-secondary"></i>&nbsp;SMS
                                                 </button>
-                                                <form url="/api/clientSms/createOutgoing" right class="mcp-theme-1">
+                                                <form url="/api/clientSms/createOutgoing" right class="mcp-theme-1" noreload>
                                                     <input type="hidden" name="uid" value="{{ $patient->uid }}">
                                                     <div class="mb-2">
                                                         <label for="" class="text-sm text-secondary mb-1">Cell
@@ -832,6 +833,7 @@ $isVisitNote = ($routeName === 'patients.view.notes.view.dashboard' && @$note &&
 							</div>
 						</div> <!-- z -->
 					</div>
+					</div>
 					@if($pro->pro_type === 'ADMIN')
 						<div class="screen-only card-header py-2 d-flex align-items-center mcp-theme-1 bg-aliceblue hide-inside-popup">
 							<b class="">Tags ({{count($patient->clientTags)}}):</b>
@@ -918,7 +920,7 @@ $isVisitNote = ($routeName === 'patients.view.notes.view.dashboard' && @$note &&
 					}
 				});
 
-				$('[data-toggle="tooltip"]').tooltip('hover');
+				// $('[data-toggle="tooltip"]').tooltip('hover');
 			}
 			addMCInitializer('patient-add-note-popup', init, '#patient-header')
 		}).call(window);

+ 1 - 0
routes/web.php

@@ -410,6 +410,7 @@ Route::middleware('pro.auth')->group(function () {
     // pro dashboard events (ajax)
     Route::get('pro-dashboard-event-dates/{from}/{to}', 'HomeController@dashboardAppointmentDates')->name('pro-dashboard-event-dates');
     Route::get('pro-dashboard-events/{from}/{to}', 'HomeController@dashboardAppointments')->name('pro-dashboard-events');
+    Route::get('pro-dashboard-events-display/{from}/{to}', 'HomeController@dashboardAppointmentsDisplay')->name('pro-dashboard-events');
 
     // pro dashboard measurements
     Route::get('pro-dashboard-measurements/{filter}', 'HomeController@dashboardMeasurements')->name('pro-dashboard-measurements');

+ 31 - 14
yemi.js

@@ -187,23 +187,13 @@ var doAjaxFormData = function (url, data, pre, post, onSuccess, onFailure, suppr
 
 var justLog = false; //THIS IS FOR TEST MODE, FORMS WILL NOT TRIGGER REFRESH/REDIR
 
-var pageReload = function () {
+var pageReload = function (_target) {
     setTimeout(function () {
         hideMoeFormMask();
-        fastReload();
+        fastReload(_target);
     }, 500);
 };
 
-var fastReload = function() {
-    var targetLocation = window.top.location.pathname + window.top.location.search;
-    if(targetLocation.indexOf('/mc') === 0) {
-        targetLocation = targetLocation.substr(3);
-    }
-    if(targetLocation === '' || targetLocation[0] !== '/') targetLocation = '/' + targetLocation;
-    fastLoad(targetLocation, false, false);
-    return false;
-}
-
 if (typeof String.prototype.startsWith != 'function') {
     // see below for better implementation!
     String.prototype.startsWith = function (str) {
@@ -329,6 +319,9 @@ var initMoes = function() {
         var form = moe.find('[url]')[0]; // REQUIRED
         var url = $(form).attr('url'); // REQUIRED
         var redir = $(form).attr('redir'); // OPTIONAL
+        var target = $(form).attr('target'); // OPTIONAL
+        var noreload = $(form).is('[noreload]'); // OPTIONAL
+        var hook = $(form).attr('hook'); // OPTIONAL
         var submit = moe.find('[submit]'); // REQUIRED
         var cancel = moe.find('[cancel]')[0]; // OPTIONAL
 
@@ -506,8 +499,20 @@ var initMoes = function() {
                     doAjax(url, data, null, function () {
                         moe.isProcessing = false;
                     }, function (data) {
+                        if(noreload) {
+                            $(cancel).trigger('click.moe');
+                            hideMoeFormMask();
+                            hideMask();
+                            toastr.success('Done');
+                            return;
+                        }
                         if (justLog) { // this is to test!
                             console.log('RETURNED', data);
+                        } else if (hook) {
+                            $(cancel).trigger('click.moe');
+                            hideMoeFormMask();
+                            hideMask();
+                            runMCHook(hook);
                         } else if(isDynamicStagPopupPresent()) {
                             refreshDynamicStagPopup();
                         } else if (redir) {
@@ -530,7 +535,7 @@ var initMoes = function() {
                                 initAutoRxAndICDComplete();
                             });
                         } else {
-                            pageReload();
+                            pageReload(target);
                         }
                     }, function (errorMessage) {
 
@@ -540,8 +545,20 @@ var initMoes = function() {
                     doAjaxFormData(url, data, null, function () {
                         moe.isProcessing = false;
                     }, function (data) {
+                        if(noreload) {
+                            $(cancel).trigger('click.moe');
+                            hideMoeFormMask();
+                            hideMask();
+                            toastr.success('Done');
+                            return;
+                        }
                         if (justLog) { // this is to test!
                             console.log('RETURNED', data);
+                        } else if (hook) {
+                            $(cancel).trigger('click.moe');
+                            hideMoeFormMask();
+                            hideMask();
+                            runMCHook(hook);
                         } else if(isDynamicStagPopupPresent()) {
                             refreshDynamicStagPopup();
                         } else if (redir) {
@@ -564,7 +581,7 @@ var initMoes = function() {
                                 initAutoRxAndICDComplete();
                             });
                         } else {
-                            pageReload();
+                            pageReload(target);
                         }
                     }, function (errorMessage) {
 

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно