Преглед изворни кода

Updated rpm-matrix for ADMIN (wip)

Vijayakrishnan пре 3 година
родитељ
комит
9bf3b46d02

+ 254 - 0
app/Http/Controllers/PracticeManagementController.php

@@ -1318,6 +1318,66 @@ WHERE care_month.uid = '{$careMonthUid}' AND client.uid = '{$clientUid}'
         return view('app.practice-management.remote-monitoring-row-by-pro-type', ['iPatient' => $patients[0], 'trIndex' => $request->input('trIndex'), 'mode' => $mode]);
     }
 
+    private function remoteMonitoring_RowForAdmin(Request $request) {
+
+        $clientUid = $request->input('clientUid');
+        $careMonthUid = $request->input('careMonthUid');
+
+        $query = "
+SELECT client.name_first, client.name_last,
+       (client.name_first || ' ' || client.name_last) as client_name,
+       client.uid as client_uid, 
+       client.dob,
+       client.is_enrolled_in_rm,
+       client.most_recent_completed_mcp_note_date,
+       client.most_recent_completed_mcp_note_id,
+       mrmnote.effective_dateest::date as most_recent_completed_mcp_note_date_cm,
+       mrmnote.id as most_recent_completed_mcp_note_id_cm,
+       mrmnote.uid as most_recent_completed_mcp_note_uid_cm,
+       client.cell_number,
+       client.is_assigned_cellular_bp_device,
+       client.is_assigned_cellular_weight_scale_device,
+       care_month.uid as care_month_uid,
+       care_month.id as care_month_id,
+       care_month.start_date,
+       care_month.rm_total_time_in_seconds_by_mcp,
+       care_month.rm_total_time_in_seconds_by_rmm_pro,
+       care_month.number_of_days_with_remote_measurements,
+       care_month.has_mcp_interacted_with_client_about_rm,
+       care_month.rm_num_measurements_not_stamped_by_mcp,
+       care_month.rm_num_measurements_not_stamped_by_non_hcp,
+       care_month.rm_num_measurements_not_stamped_by_rmm,
+       care_month.rm_num_measurements_not_stamped_by_rme,
+       care_month.mcp_pro_id as care_month_mcp_pro_id,
+       care_month.rmm_pro_id as care_month_rmm_pro_id,
+       client.mcp_pro_id,
+       client.default_na_pro_id,
+       client.rmm_pro_id,
+       client.rme_pro_id,
+       client.cell_number,
+       care_month.most_recent_cellular_bp_dbp_mm_hg,
+       care_month.most_recent_cellular_bp_sbp_mm_hg,
+       care_month.most_recent_cellular_bp_measurement_at,      
+       care_month.most_recent_cellular_weight_value,
+       care_month.most_recent_cellular_weight_measurement_at
+FROM care_month join client on care_month.client_id = client.id join note mrnote on client.most_recent_completed_mcp_note_id = mrnote.id
+     left join note mrmnote on mrmnote.id = (
+        select max(n.id) from note n 
+        where 
+              n.client_id = client.id AND 
+              n.is_cancelled = FALSE AND
+              (n.is_signed_by_hcp IS NOT NULL AND n.is_signed_by_hcp = TRUE) AND
+              n.effective_dateest::date >= care_month.start_date::date AND 
+              n.effective_dateest::date < (care_month.start_date::date + INTERVAL '1 month')
+     )
+WHERE care_month.uid = '{$careMonthUid}' AND client.uid = '{$clientUid}'
+";
+
+        $patients = DB::select($query);
+
+        return view('app.practice-management.remote-monitoring-row-for-admin', ['iPatient' => $patients[0], 'trIndex' => $request->input('trIndex')]);
+    }
+
     private function rpmMatrixByProType(Request $request, $mode) {
 
         $performer = $this->performer();
@@ -1525,6 +1585,196 @@ WHERE
         return view('app.practice-management.rpm-matrix-by-pro-type', compact('patients', 'daysRemaining', 'careMonthStart', 'mode'));
     }
 
+    public function rpmMatrixForAdmin(Request $request) {
+
+        $performer = $this->performer();
+
+        // abort_if($performer->pro->pro_type !== 'ADMIN' && !$performer->pro->can_view_rm_matrix, 403);
+
+        $ym = ($request->input('y') ?: 'Y') . '-' . ($request->input('m') ?: 'm');
+        $careMonthStart = date($ym . '-01');
+
+        $rc = $request->input('rc') ?: 1;
+        $rc2 = $request->input('rc2') ?: 2;
+
+        $conditions = [];// $this->rpmConditions($performer, $rc, $rc2);
+
+        $sortBy = $request->input('sort_by') ?: 'name_first';
+        $sortDir = $request->input('sort_dir') ?: 'ASC';
+        $orderBy = "ORDER BY $sortBy $sortDir NULLS LAST";
+
+        // special case of if-bill-exists
+        if($sortBy === 'mcp_rm_generic_bill_id' || $sortBy === 'rmm_rm_generic_bill_id') {
+            if($sortDir === 'ASC') {
+                $orderBy = "ORDER BY $sortBy $sortDir NULLS FIRST";
+            }
+            else {
+                $orderBy = "ORDER BY $sortBy $sortDir NULLS LAST";
+            }
+        }
+
+        // filters from the UI
+        if(trim($request->input('f_name'))) {
+            $v = trim($request->input('f_name'));
+            $conditions[] = "(client.name_first ILIKE '%{$v}%' OR client.name_last ILIKE '%{$v}%')";
+        }
+        if(trim($request->input('f_dob_op')) && trim($request->input('f_dob'))) {
+            $o = trim($request->input('f_dob_op'));
+            $v = trim($request->input('f_dob'));
+            $conditions[] = "(client.dob {$o} '{$v}')";
+        }
+        if(trim($request->input('f_rpm'))) {
+            $v = trim($request->input('f_rpm'));
+            if($v === 'yes') {
+                $conditions[] = "(client.is_enrolled_in_rm IS NOT NULL AND client.is_enrolled_in_rm = 'YES')";
+            }
+            elseif($v === 'no') {
+                $conditions[] = "(client.is_enrolled_in_rm IS NULL OR client.is_enrolled_in_rm != 'YES')";
+            }
+        }
+        if(trim($request->input('f_cell_bp'))) {
+            $v = trim($request->input('f_cell_bp'));
+            if($v === 'yes') {
+                $conditions[] = "(client.is_assigned_cellular_bp_device IS NOT NULL AND client.is_assigned_cellular_bp_device = TRUE)";
+            }
+            elseif($v === 'no') {
+                $conditions[] = "(client.is_assigned_cellular_bp_device IS NULL OR client.is_assigned_cellular_bp_device = FALSE)";
+            }
+        }
+        if(trim($request->input('f_cell_wt'))) {
+            $v = trim($request->input('f_cell_wt'));
+            if($v === 'yes') {
+                $conditions[] = "(client.is_assigned_cellular_weight_scale_device IS NOT NULL AND client.is_assigned_cellular_weight_scale_device = TRUE)";
+            }
+            elseif($v === 'no') {
+                $conditions[] = "(client.is_assigned_cellular_weight_scale_device IS NULL OR client.is_assigned_cellular_weight_scale_device = FALSE)";
+            }
+        }
+        if(trim($request->input('f_comm'))) {
+            $v = trim($request->input('f_comm'));
+            if($v === 'yes') {
+                $conditions[] = "(care_month.has_mcp_interacted_with_client_about_rm IS NOT NULL AND care_month.has_mcp_interacted_with_client_about_rm = TRUE)";
+            }
+            elseif($v === 'no') {
+                $conditions[] = "(care_month.has_mcp_interacted_with_client_about_rm IS NULL OR care_month.has_mcp_interacted_with_client_about_rm = FALSE)";
+            }
+        }
+
+        if(trim($request->input('f_mcp_billable'))) {
+            $v = trim($request->input('f_mcp_billable'));
+            if($v === 'yes') {
+                $conditions[] = "(care_month.mcp_rm_generic_bill_id IS NOT NULL)";
+            }
+            elseif($v === 'no') {
+                $conditions[] = "(care_month.mcp_rm_generic_bill_id IS NULL)";
+            }
+        }
+
+        if(trim($request->input('f_rmm_billable'))) {
+            $v = trim($request->input('f_rmm_billable'));
+            if($v === 'yes') {
+                $conditions[] = "(care_month.rmm_rm_generic_bill_id IS NOT NULL)";
+            }
+            elseif($v === 'no') {
+                $conditions[] = "(care_month.rmm_rm_generic_bill_id IS NULL)";
+            }
+        }
+
+        if(trim($request->input('f_md_op')) && trim($request->input('f_md')) !== '') {
+            $o = trim($request->input('f_md_op'));
+            $v = trim($request->input('f_md'));
+            $conditions[] = "(care_month.number_of_days_with_remote_measurements {$o} {$v})";
+        }
+        if(trim($request->input('f_unst_op')) && trim($request->input('f_unst')) !== '') {
+            $o = trim($request->input('f_unst_op'));
+            $v = trim($request->input('f_unst'));
+            $conditions[] = "(care_month.rm_num_measurements_not_stamped_by_mcp {$o} {$v})";
+        }
+        if(trim($request->input('f_mcp_mins_op')) && trim($request->input('f_mcp_mins')) !== '') {
+            $o = trim($request->input('f_mcp_mins_op'));
+            $v = intval(trim($request->input('f_mcp_mins'))) * 60;
+            $conditions[] = "(care_month.rm_total_time_in_seconds_by_mcp {$o} {$v})";
+        }
+        if(trim($request->input('f_rmm_mins_op')) && trim($request->input('f_rmm_mins')) !== '') {
+            $o = trim($request->input('f_rmm_mins_op'));
+            $v = intval(trim($request->input('f_rmm_mins'))) * 60;
+            $conditions[] = "(care_month.rm_total_time_in_seconds_by_rmm_pro {$o} {$v})";
+        }
+
+        $genericBillIdColumns = "care_month.mcp_rm_generic_bill_id,
+                   mcpBill.uid as mcp_rm_generic_bill_uid,
+                   mcpBill.generic_pro_id as mcp_rm_generic_bill_generic_pro_id,
+                   mcpBill.generic_pro_expected_payment_amount as mcp_rm_generic_bill_expected_payment_amount,
+                   mcpBill.is_signed_by_generic_pro as mcp_rm_generic_bill_signed,
+                   care_month.rmm_rm_generic_bill_id,
+                   rmmBill.uid as rmm_rm_generic_bill_uid,
+                   rmmBill.generic_pro_id as rmm_rm_generic_bill_generic_pro_id,
+                   rmmBill.generic_pro_expected_payment_amount as rmm_rm_generic_bill_expected_payment_amount,
+                   rmmBill.is_signed_by_generic_pro as rmm_rm_generic_bill_signed";
+        $genericBillJoinClause = "left join bill mcpBill on care_month.mcp_rm_generic_bill_id = mcpBill.id
+                   left join bill rmmBill on care_month.rmm_rm_generic_bill_id = rmmBill.id";
+
+        $query = "
+SELECT client.name_first, client.name_last,
+       (client.name_first || ' ' || client.name_last) as client_name,
+       client.uid as client_uid, 
+       client.dob,
+       client.is_enrolled_in_rm,
+       client.most_recent_completed_mcp_note_date,
+       client.most_recent_completed_mcp_note_id,
+       client.cell_number,
+       client.is_assigned_cellular_bp_device,
+       client.is_assigned_cellular_weight_scale_device,
+       care_month.uid as care_month_uid,
+       care_month.id as care_month_id,
+       care_month.start_date,
+       care_month.rm_total_time_in_seconds_by_mcp,
+       care_month.rm_total_time_in_seconds_by_rmm_pro,
+       care_month.number_of_days_with_remote_measurements,
+       care_month.has_mcp_interacted_with_client_about_rm,
+       care_month.rm_num_measurements_not_stamped_by_mcp,
+       care_month.rm_num_measurements_not_stamped_by_non_hcp,
+       care_month.rm_num_measurements_not_stamped_by_rmm,
+       care_month.rm_num_measurements_not_stamped_by_rme,
+       care_month.mcp_pro_id as care_month_mcp_pro_id,
+       care_month.rmm_pro_id as care_month_rmm_pro_id,
+       client.mcp_pro_id,
+       client.default_na_pro_id,
+       client.rmm_pro_id,
+       client.rme_pro_id,
+       client.cell_number,
+       care_month.most_recent_cellular_bp_dbp_mm_hg,
+       care_month.most_recent_cellular_bp_sbp_mm_hg,
+       care_month.most_recent_cellular_bp_measurement_at,      
+       care_month.most_recent_cellular_weight_value,
+       care_month.most_recent_cellular_weight_measurement_at,
+       mcpPro.mcp_rpm_payment_strategy,
+       mcpPro.mcp_rpm_payment_amount,
+       rmmPro.rmm_payment_strategy,
+       rmmPro.rmm_payment_amount,
+       {$genericBillIdColumns}
+FROM care_month join client on care_month.client_id = client.id 
+    join note mrnote on client.most_recent_completed_mcp_note_id = mrnote.id
+    left join pro mcpPro on care_month.mcp_pro_id = mcpPro.id
+    left join pro rmmPro on care_month.rmm_pro_id = rmmPro.id
+    {$genericBillJoinClause}
+WHERE
+      EXTRACT(MONTH from care_month.start_date) = " . ($request->input('m') ?: 'EXTRACT(MONTH from now())') . "
+      AND EXTRACT(YEAR from care_month.start_date) = " . ($request->input('y') ?: 'EXTRACT(YEAR from now())') . "
+      " . (count($conditions) > 0 ? 'AND ' . implode(" AND ", $conditions) : '') . "
+      $orderBy
+";
+
+        // dd($query);
+
+        $patients = DB::select($query);
+
+        $timestamp = strtotime(date('Y-m-d'));
+        $daysRemaining = (int)date('t', $timestamp) - (int)date('j', $timestamp);
+
+        return view('app.practice-management.rpm-matrix-for-admin', compact('patients', 'daysRemaining', 'careMonthStart'));
+    }
+
     public function remoteMonitoringMCP(Request $request) {
         return $this->rpmMatrixByProType($request, 'mcp');
     }
@@ -1549,6 +1799,10 @@ WHERE
         return $this->remoteMonitoring_RowByProType($request, 'rme');
     }
 
+    public function remoteMonitoring_RowADMIN(Request $request) {
+        return $this->remoteMonitoring_RowForAdmin($request);
+    }
+
     public function rpm_work_matrix(Request $request) {
 
         // get the patient having most recent unstamped measurement

+ 1 - 1
config/app.php

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

+ 3 - 0
public/css/style.css

@@ -493,6 +493,9 @@ body>nav.navbar {
     width: 100% !important;
     min-width: unset !important;
 }
+.mcp-theme-1 .max-width-170px {
+    max-width: 170px;
+}
 .mcp-theme-1 .max-width-200px {
     max-width: 200px;
 }

+ 18 - 0
resources/views/app/practice-management/remote-monitoring-row-for-admin.blade.php

@@ -0,0 +1,18 @@
+<?php
+
+$mStr = request()->input('m') ? request()->input('m') : date('m');
+$yStr = request()->input('y') ? request()->input('y') : date('Y');
+$rcmStartDate = $yStr . '-' . $mStr . '-' . '01';
+$m = +$mStr;
+$y = +$yStr;
+
+$daysDiff = -1;
+if($iPatient->most_recent_completed_mcp_note_date) {
+    $careMonthLastDay = date_add(date_create($rcmStartDate), date_interval_create_from_date_string("1 month"));
+    $careMonthLastDay = date_sub($careMonthLastDay, date_interval_create_from_date_string("1 day"));
+    $daysDiff = date_diff($careMonthLastDay, date_create($iPatient->most_recent_completed_mcp_note_date))->days;
+}
+$lastVisitWithin90Days = ($daysDiff !== -1 && $daysDiff <= 90);
+
+?>
+@include('app.practice-management.remote-monitoring-row-markup-for-admin')

+ 114 - 0
resources/views/app/practice-management/remote-monitoring-row-markup-for-admin.blade.php

@@ -0,0 +1,114 @@
+<tr data-client-uid="{{$iPatient->client_uid}}" data-care-month-uid="{{$iPatient->care_month_uid}}">
+    <td class="pl-2">
+        <a href="/patients/view/{{ $iPatient->client_uid }}/care-months/view/{{$iPatient->care_month_uid}}"
+           native target="_blank"
+           open-in-stag-popup
+           update-parent="refresh-rpm-row-{{$trIndex}}"
+           popup-style="tall overflow-visible"
+           mc-initer="care-month-dashboard-{{$iPatient->client_uid}}"
+           title="{{$iPatient->client_name}}"
+           class="text-nowrap d-block max-width-170px overflow-hidden text-ellipsis"
+        ><span class="sort-data">{{ $iPatient->client_name }}</span></a>
+    </td>
+
+    <td>{{friendly_date($iPatient->dob)}}</td>
+    <td>{!! $iPatient->is_enrolled_in_rm === 'YES' ? '<i class="fa fa-check text-success"></i>' : 'No' !!}</td>
+    <td>{!! $iPatient->is_assigned_cellular_bp_device ? '<i class="fa fa-check text-success"></i>' : 'No' !!}</td>
+    <td>{!! $iPatient->is_assigned_cellular_weight_scale_device ? '<i class="fa fa-check text-success"></i>' : 'No' !!}</td>
+    <td>
+        <div class="text-nowrap">
+            <span class="sort-data">{{$iPatient->most_recent_cellular_bp_sbp_mm_hg ?: '-'}}</span>/{{$iPatient->most_recent_cellular_bp_dbp_mm_hg ?: '-'}}
+            @if($iPatient->most_recent_cellular_bp_measurement_at)
+                <span class="text-sm text-secondary text-nowrap ml-1"
+                      title="{{friendly_date_time($iPatient->most_recent_cellular_bp_measurement_at)}}">({{friendly_date_est($iPatient->most_recent_cellular_bp_measurement_at)}})</span>
+            @endif
+        </div>
+    </td>
+    <td>
+        <div class="text-nowrap">
+            <span class="sort-data">{{$iPatient->most_recent_cellular_weight_value ? round($iPatient->most_recent_cellular_weight_value, 1) : '-'}}</span>
+            @if($iPatient->most_recent_cellular_weight_measurement_at)
+                <span class="text-sm text-secondary text-nowrap ml-1"
+                      title="{{friendly_date_time($iPatient->most_recent_cellular_weight_measurement_at)}}">({{friendly_date_est($iPatient->most_recent_cellular_weight_measurement_at)}})</span>
+            @endif
+        </div>
+    </td>
+    
+    <td>
+        <div class="d-flex align-items-baseline">
+            <i class="mr-1 text-sm fa {{$lastVisitWithin90Days ? 'fa-check text-success' : 'fa-exclamation-triangle text-danger on-hover-opaque'}}"></i>
+            <span class="sort-data">{{$daysDiff !== -1 ? $daysDiff : '-'}}</span>
+        </div>
+    </td>
+
+    <td>
+        <div class="d-flex align-items-baseline">
+            <i class="mr-1 text-sm fa {{$iPatient->has_mcp_interacted_with_client_about_rm ? 'fa-check text-success' : 'fa-exclamation-triangle text-danger on-hover-opaque'}}"></i>
+            <span class="sort-data">{{$iPatient->has_mcp_interacted_with_client_about_rm ? 'Yes' : 'No'}}</span>
+        </div>
+    </td>
+
+    <td>
+        <div class="d-flex align-items-baseline">
+            <i class="mr-1 text-sm fa {{$iPatient->number_of_days_with_remote_measurements >= 16 ? 'fa-check text-success' : 'fa-exclamation-triangle text-danger on-hover-opaque'}}"></i>
+            <span class="sort-data">{{$iPatient->number_of_days_with_remote_measurements ?: 0}}</span>
+        </div>
+    </td>
+
+    <td>
+        <span class="sort-data">{{$iPatient->rm_num_measurements_not_stamped_by_mcp}}</span>
+    </td>
+
+    <td>
+        <span class="sort-data">{{$iPatient->rm_num_measurements_not_stamped_by_rmm}}</span>
+    </td>
+
+    <td>
+        <div class="d-flex align-items-baseline">
+            <i class="mr-1 text-sm fa {{$iPatient->rm_total_time_in_seconds_by_mcp >= 1200 ? 'fa-check text-success' : 'fa-exclamation-triangle text-danger on-hover-opaque'}}"></i>
+            <span class="text-nowrap">{{round($iPatient->rm_total_time_in_seconds_by_mcp / 60)}}m {{round($iPatient->rm_total_time_in_seconds_by_mcp % 60)}}s</span>
+            <span class="sort-data d-none">{{$iPatient->rm_total_time_in_seconds_by_mcp}}</span>
+        </div>
+    </td>
+
+    <td>
+        <div class="d-flex align-items-baseline">
+            <i class="mr-1 text-sm fa {{$iPatient->rm_total_time_in_seconds_by_rmm_pro >= 1200 ? 'fa-check text-success' : 'fa-exclamation-triangle text-danger on-hover-opaque'}}"></i>
+            <span class="text-nowrap">{{round($iPatient->rm_total_time_in_seconds_by_rmm_pro / 60)}}m {{round($iPatient->rm_total_time_in_seconds_by_rmm_pro % 60)}}s</span>
+            <span class="sort-data d-none">{{$iPatient->rm_total_time_in_seconds_by_rmm_pro}}</span>
+        </div>
+    </td>
+
+    <td>
+        @if($iPatient->mcp_rm_generic_bill_id)
+            <span class="text-success font-weight-bold">
+                <i class="fa fa-check"></i>
+                Yes
+            </span>
+            (${{friendly_money($iPatient->mcp_rm_generic_bill_expected_payment_amount)}})
+            @if($iPatient->mcp_rm_generic_bill_signed)
+                <span class="text-success">Signed</span>
+            @endif
+        @else
+            <span class="text-danger font-weight-normal">
+                Not yet
+            </span>
+        @endif
+    </td>
+    <td>
+        @if($iPatient->rmm_rm_generic_bill_id)
+            <span class="text-success font-weight-bold">
+                <i class="fa fa-check"></i>
+                Yes
+            </span>
+            (${{friendly_money($iPatient->rmm_rm_generic_bill_expected_payment_amount)}})
+            @if($iPatient->rmm_rm_generic_bill_signed)
+                <span class="text-success">Signed</span>
+            @endif
+        @else
+            <span class="text-danger font-weight-normal">
+                Not yet
+            </span>
+        @endif
+    </td>
+</tr>

+ 403 - 0
resources/views/app/practice-management/rpm-matrix-for-admin.blade.php

@@ -0,0 +1,403 @@
+@extends ('layouts/template')
+
+@section('content')
+    <style>
+        #admin-table-rm-matrix_wrapper {
+            padding-top: 10px;
+        }
+    </style>
+    <link rel="stylesheet" href="https://cdn.datatables.net/1.11.5/css/jquery.dataTables.min.css">
+    <script src="https://cdn.datatables.net/1.11.5/js/jquery.dataTables.min.js"></script>
+    <style>
+        #table-rm-matrix_length, #table-rm-matrix_info {
+            padding-left: 0.5rem;
+        }
+
+        #table-rm-matrix_filter {
+            padding-right: 0.5rem;
+        }
+
+        #table-rm-matrix_paginate {
+            padding: 0.5rem;
+        }
+    </style>
+    <div class="p-3 mcp-theme-1 body-height" id="practice-remote-monitoring" v-cloak>
+
+        <div class="card h-100">
+
+            <div class="card-header px-2 py-2 d-flex align-items-baseline">
+                <form class="d-block w-100" action="" method="GET">
+
+                    <div class="d-flex align-items-end">
+                        <span class="mr-4">
+                            <span class="font-size-14">Remote Monitoring</span>
+                            <i class="fas fa-arrow-right text-sm mx-1"></i>
+                            <b class="font-size-14">{{friendly_month(date((request()->input('y') ?: 'Y') . '-' . (request()->input('m') ?: 'm') . '-d'))}}</b>
+                        </span>
+                        <?php
+
+                        $mStr = request()->input('m') ? request()->input('m') : date('m');
+                        $yStr = request()->input('y') ? request()->input('y') : date('Y');
+                        $rcmStartDate = $yStr . '-' . $mStr . '-' . '01';
+                        $m = +$mStr;
+                        $y = +$yStr;
+                        ?>
+
+                        <div class="ml-auto d-inline-flex flex-nowrap align-items-baseline">
+                            <span class="mr-2">Month</span>
+                            <select class="form-control form-control-sm min-width-unset width-100px mr-3" name="m"
+                                    onchange="fastLoad('{{route('practice-management.rpm-matrix-admin')}}?' + $(this).closest('form').serialize())">
+                                <option value="01" {{$m === 1 ? 'selected' : ''}}>Jan</option>
+                                <option value="02" {{$m === 2 ? 'selected' : ''}}>Feb</option>
+                                <option value="03" {{$m === 3 ? 'selected' : ''}}>Mar</option>
+                                <option value="04" {{$m === 4 ? 'selected' : ''}}>Apr</option>
+                                <option value="05" {{$m === 5 ? 'selected' : ''}}>May</option>
+                                <option value="06" {{$m === 6 ? 'selected' : ''}}>Jun</option>
+                                <option value="07" {{$m === 7 ? 'selected' : ''}}>Jul</option>
+                                <option value="08" {{$m === 8 ? 'selected' : ''}}>Aug</option>
+                                <option value="09" {{$m === 9 ? 'selected' : ''}}>Sep</option>
+                                <option value="10" {{$m === 10 ? 'selected' : ''}}>Oct</option>
+                                <option value="11" {{$m === 11 ? 'selected' : ''}}>Nov</option>
+                                <option value="12" {{$m === 12 ? 'selected' : ''}}>Dec</option>
+                            </select>
+                            <span class="mr-2">Year</span>
+                            <select class="form-control form-control-sm min-width-unset width-100px" name="y"
+                                    onchange="fastLoad('{{route('practice-management.rpm-matrix-admin')}}?' + $(this).closest('form').serialize())">
+                                <option value="2020" {{$y === 2020 ? 'selected' : ''}}>2020</option>
+                                <option value="2021" {{$y === 2021 ? 'selected' : ''}}>2021</option>
+                                <option value="2022" {{$y === 2022 ? 'selected' : ''}}>2022</option>
+                            </select>
+                        </div>
+                    </div>
+
+                    <div class="d-flex align-items-start mt-2 pt-1 border-top">
+
+                        <div>
+                            <label class="mb-0 text-sm {{request()->input('f_name') ? 'text-info' : 'text-secondary'}}">Name</label>
+                            <input type="text"
+                                   class="mr-2 form-control form-control-sm min-width-unset max-width-110px"
+                                   name="f_name" value="{{request()->input('f_name')}}">
+                        </div>
+
+                        <div>
+                            <label class="mb-0 text-sm {{request()->input('f_dob') ? 'text-info' : 'text-secondary'}}">DOB</label>
+                            <div class="d-flex align-items-start">
+                                <select name="f_dob_op"
+                                        class="mr-1 form-control form-control-sm min-width-unset width-40px pl-0">
+                                    <option {{request()->input('f_dob_op') === '=' ? 'selected' : ''}} value="=">&equals;</option>
+                                    <option {{request()->input('f_dob_op') === '>' ? 'selected' : ''}} value=">">&gt;</option>
+                                    <option {{request()->input('f_dob_op') === '<' ? 'selected' : ''}} value="<">&lt;</option>
+                                    <option {{request()->input('f_dob_op') === '>=' ? 'selected' : ''}} value=">=">&ge;</option>
+                                    <option {{request()->input('f_dob_op') === '<=' ? 'selected' : ''}} value="<=">&le;</option>
+                                </select>
+                                <input type="date" name="f_dob"
+                                       value="{{request()->input('f_dob')}}"
+                                       class="mr-2 form-control form-control-sm min-width-unset max-width-140px">
+                            </div>
+                        </div>
+
+                        <div>
+                            <label class="mb-0 text-sm {{request()->input('f_rpm') && request()->input('f_rpm') !== 'any' ? 'text-info' : 'text-secondary'}}">RPM</label>
+                            <select name="f_rpm"
+                                    class="mr-2 form-control form-control-sm min-width-unset width-70px pl-0">
+                                <option {{request()->input('f_rpm') === 'any' ? 'selected' : ''}} value="any">Any</option>
+                                <option {{request()->input('f_rpm') === 'yes' ? 'selected' : ''}} value="yes">Yes</option>
+                                <option {{request()->input('f_rpm') === 'no' ? 'selected' : ''}} value="no">No</option>
+                            </select>
+                        </div>
+
+                        <div>
+                            <label class="mb-0 text-sm {{request()->input('f_cell_bp') && request()->input('f_cell_bp') !== 'any' ? 'text-info' : 'text-secondary'}}">Cell. BP</label>
+                            <select name="f_cell_bp"
+                                    class="mr-2 form-control form-control-sm min-width-unset width-70px pl-0">
+                                <option {{request()->input('f_cell_bp') === 'any' ? 'selected' : ''}} value="any">Any</option>
+                                <option {{request()->input('f_cell_bp') === 'yes' ? 'selected' : ''}} value="yes">Yes</option>
+                                <option {{request()->input('f_cell_bp') === 'no' ? 'selected' : ''}} value="no">No</option>
+                            </select>
+                        </div>
+
+                        <div>
+                            <label class="mb-0 text-sm {{request()->input('f_cell_wt') && request()->input('f_cell_wt') !== 'any' ? 'text-info' : 'text-secondary'}}">Cell. Wt</label>
+                            <select name="f_cell_wt"
+                                    class="mr-2 form-control form-control-sm min-width-unset width-70px pl-0">
+                                <option {{request()->input('f_cell_wt') === 'any' ? 'selected' : ''}} value="any">Any</option>
+                                <option {{request()->input('f_cell_wt') === 'yes' ? 'selected' : ''}} value="yes">Yes</option>
+                                <option {{request()->input('f_cell_wt') === 'no' ? 'selected' : ''}} value="no">No</option>
+                            </select>
+                        </div>
+
+                        <div>
+                            <label class="mb-0 text-sm {{request()->input('f_comm') && request()->input('f_comm') !== 'any' ? 'text-info' : 'text-secondary'}}">Comm.</label>
+                            <select name="f_comm"
+                                    class="mr-2 form-control form-control-sm min-width-unset width-70px pl-0">
+                                <option {{request()->input('f_comm') === 'any' ? 'selected' : ''}} value="any">Any</option>
+                                <option {{request()->input('f_comm') === 'yes' ? 'selected' : ''}} value="yes">Yes</option>
+                                <option {{request()->input('f_comm') === 'no' ? 'selected' : ''}} value="no">No</option>
+                            </select>
+                        </div>
+
+                        <div>
+                            <label class="mb-0 text-sm {{request()->input('f_md') ? 'text-info' : 'text-secondary'}}">Meas. Days</label>
+                            <div class="d-flex align-items-start">
+                                <select name="f_md_op"
+                                        class="mr-1 form-control form-control-sm min-width-unset width-40px pl-0">
+                                    <option {{request()->input('f_md_op') === '=' ? 'selected' : ''}} value="=">&equals;</option>
+                                    <option {{request()->input('f_md_op') === '>' ? 'selected' : ''}} value=">">&gt;</option>
+                                    <option {{request()->input('f_md_op') === '<' ? 'selected' : ''}} value="<">&lt;</option>
+                                    <option {{request()->input('f_md_op') === '>=' ? 'selected' : ''}} value=">=">&ge;</option>
+                                    <option {{request()->input('f_md_op') === '<=' ? 'selected' : ''}} value="<=">&le;</option>
+                                </select>
+                                <input type="number" name="f_md"
+                                       value="{{request()->input('f_md')}}"
+                                       class="mr-2 form-control form-control-sm min-width-unset width-70px">
+                            </div>
+                        </div>
+
+                        <div>
+                            <label class="mb-0 text-sm {{request()->input('f_unst') ? 'text-info' : 'text-secondary'}}">Unstamped</label>
+                            <div class="d-flex align-items-start">
+                                <select name="f_unst_op"
+                                        class="mr-1 form-control form-control-sm min-width-unset width-40px pl-0">
+                                    <option {{request()->input('f_unst_op') === '=' ? 'selected' : ''}} value="=">&equals;</option>
+                                    <option {{request()->input('f_unst_op') === '>' ? 'selected' : ''}} value=">">&gt;</option>
+                                    <option {{request()->input('f_unst_op') === '<' ? 'selected' : ''}} value="<">&lt;</option>
+                                    <option {{request()->input('f_unst_op') === '>=' ? 'selected' : ''}} value=">=">&ge;</option>
+                                    <option {{request()->input('f_unst_op') === '<=' ? 'selected' : ''}} value="<=">&le;</option>
+                                </select>
+                                <input type="number" name="f_unst"
+                                       value="{{request()->input('f_unst')}}"
+                                       class="mr-2 form-control form-control-sm min-width-unset width-70px">
+                            </div>
+                        </div>
+
+                        <div>
+                            <label class="mb-0 text-sm {{request()->input('f_mcp_mins') ? 'text-info' : 'text-secondary'}}">MCP Mins.</label>
+                            <div class="d-flex align-items-start">
+                                <select name="f_mcp_mins_op"
+                                        class="mr-1 form-control form-control-sm min-width-unset width-40px pl-0">
+                                    <option {{request()->input('f_mcp_mins_op') === '=' ? 'selected' : ''}} value="=">&equals;</option>
+                                    <option {{request()->input('f_mcp_mins_op') === '>' ? 'selected' : ''}} value=">">&gt;</option>
+                                    <option {{request()->input('f_mcp_mins_op') === '<' ? 'selected' : ''}} value="<">&lt;</option>
+                                    <option {{request()->input('f_mcp_mins_op') === '>=' ? 'selected' : ''}} value=">=">&ge;</option>
+                                    <option {{request()->input('f_mcp_mins_op') === '<=' ? 'selected' : ''}} value="<=">&le;</option>
+                                </select>
+                                <input type="number" name="f_mcp_mins"
+                                       value="{{request()->input('f_mcp_mins')}}"
+                                       class="mr-2 form-control form-control-sm min-width-unset width-70px">
+                            </div>
+                        </div>
+
+                        <div>
+                            <label class="mb-0 text-sm {{request()->input('f_rmm_mins') ? 'text-info' : 'text-secondary'}}">RMM Mins.</label>
+                            <div class="d-flex align-items-start">
+                                <select name="f_rmm_mins_op"
+                                        class="mr-1 form-control form-control-sm min-width-unset width-40px pl-0">
+                                    <option {{request()->input('f_rmm_mins_op') === '=' ? 'selected' : ''}} value="=">&equals;</option>
+                                    <option {{request()->input('f_rmm_mins_op') === '>' ? 'selected' : ''}} value=">">&gt;</option>
+                                    <option {{request()->input('f_rmm_mins_op') === '<' ? 'selected' : ''}} value="<">&lt;</option>
+                                    <option {{request()->input('f_rmm_mins_op') === '>=' ? 'selected' : ''}} value=">=">&ge;</option>
+                                    <option {{request()->input('f_rmm_mins_op') === '<=' ? 'selected' : ''}} value="<=">&le;</option>
+                                </select>
+                                <input type="number" name="f_rmm_mins"
+                                       value="{{request()->input('f_rmm_mins')}}"
+                                       class="mr-2 form-control form-control-sm min-width-unset width-70px">
+                            </div>
+                        </div>
+
+                        <div>
+                            <label class="mb-0 text-sm {{request()->input('f_mcp_billable') && request()->input('f_mcp_billable') !== 'any' ? 'text-info' : 'text-secondary'}}">MCP Billable</label>
+                            <select name="f_mcp_billable"
+                                    class="mr-2 form-control form-control-sm min-width-unset width-70px pl-0">
+                                <option {{request()->input('f_mcp_billable') === 'all' ? 'selected' : ''}} value="any">All</option>
+                                <option {{request()->input('f_mcp_billable') === 'yes' ? 'selected' : ''}} value="yes">Yes</option>
+                                <option {{request()->input('f_mcp_billable') === 'no' ? 'selected' : ''}} value="no">No</option>
+                            </select>
+                        </div>
+
+                        <div>
+                            <label class="mb-0 text-sm {{request()->input('f_rmm_billable') && request()->input('f_rmm_billable') !== 'any' ? 'text-info' : 'text-secondary'}}">RMM Billable</label>
+                            <select name="f_rmm_billable"
+                                    class="mr-2 form-control form-control-sm min-width-unset width-70px pl-0">
+                                <option {{request()->input('f_rmm_billable') === 'all' ? 'selected' : ''}} value="any">All</option>
+                                <option {{request()->input('f_rmm_billable') === 'yes' ? 'selected' : ''}} value="yes">Yes</option>
+                                <option {{request()->input('f_rmm_billable') === 'no' ? 'selected' : ''}} value="no">No</option>
+                            </select>
+                        </div>
+
+                        <div>
+                            <label class="mb-0 text-sm text-secondary">&nbsp;</label>
+                            <div class="d-flex align-items-start">
+                                <button class="btn-apply btn btn-sm btn-primary mr-2"><i class="fa fa-check"></i></button>
+                                <button class="btn-reset btn btn-sm btn-default bg-white text-secondary border"><i class="fa fa-times"></i></button>
+                            </div>
+                        </div>
+                    </div>
+
+                </form>
+            </div>
+
+            <?php $rc = request()->input('rc') ? request()->input('rc') : 1; ?>
+
+            <div class="card-body p-0">
+                <div class="d-flex align-items-stretch m-0 h-100">
+                    <div class="flex-grow-1 px-0 overflow-auto h-100 rpm-matrix-right-column">
+                        <?php $trIndex = 0; ?>
+                        @foreach ($patients as $iPatient)
+                            <script>
+                                addMCHook(
+                                    'refresh-rpm-row-{{$trIndex}}',
+                                    function () {
+                                        refreshRpmRow({{$trIndex}});
+                                    }
+                                );
+                            </script>
+                            <?php $trIndex++; ?>
+                        @endforeach
+                        <table class="table table-sm table-striped table-hover p-0 m-0 min-width-1100px" id="table-rm-matrix">
+                            <thead class="bg-light">
+                            <tr>
+
+                                <th class="border-0 pl-2">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'Name', 'key' => 'client_name'])</th>
+                                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'DOB', 'key' => 'dob'])</th>
+                                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'RPM?', 'key' => 'is_enrolled_in_rm'])</th>
+                                <th class="border-0 text-secondary">Cell. BP?</th>
+                                <th class="border-0 text-secondary">Cell. Scale?</th>
+                                <th class="border-0 text-secondary">Latest BP</th>
+                                <th class="border-0 text-secondary">Latest Wt</th>
+                                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'Days Since Last Visit', 'key' => 'most_recent_completed_mcp_note_date'])</th>
+                                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'Comm?', 'key' => 'has_mcp_interacted_with_client_about_rm'])</th>
+                                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => '#Meas. Days', 'key' => 'number_of_days_with_remote_measurements'])</th>
+                                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => '#MCP Unst.', 'key' => 'rm_num_measurements_not_stamped_by_mcp'])</th>
+                                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => '#RMM Unst.', 'key' => 'rm_num_measurements_not_stamped_by_rmm'])</th>
+                                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => '#MCP Mins.', 'key' => 'rm_total_time_in_seconds_by_mcp'])</th>
+                                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => '#RMM Mins.', 'key' => 'rm_total_time_in_seconds_by_rmm_pro'])</th>
+                                @if(!request()->input('f_mcp_billable') || request()->input('f_mcp_billable') === 'all')
+                                    <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'MCP Bill', 'key' => 'mcp_rm_generic_bill_id'])</th>
+                                @else
+                                    <th class="border-0 text-secondary">MCP Bill</th>
+                                @endif
+                                @if(!request()->input('f_rmm_billable') || request()->input('f_rmm_billable') === 'all')
+                                    <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'RMM Bill', 'key' => 'rmm_rm_generic_bill_id'])</th>
+                                @else
+                                    <th class="border-0 text-secondary">RMM Bill</th>
+                                @endif
+                            </tr>
+                            </thead>
+                            <tbody>
+                            <?php $trIndex = 0; ?>
+                            @foreach ($patients as $iPatient)
+                                <?php
+
+                                $daysDiff = -1;
+                                if ($iPatient->most_recent_completed_mcp_note_date) {
+                                    $careMonthLastDay = date_add(date_create($rcmStartDate), date_interval_create_from_date_string("1 month"));
+                                    $careMonthLastDay = date_sub($careMonthLastDay, date_interval_create_from_date_string("1 day"));
+                                    $daysDiff = date_diff($careMonthLastDay, date_create($iPatient->most_recent_completed_mcp_note_date))->days;
+                                }
+                                $lastVisitWithin90Days = ($daysDiff !== -1 && $daysDiff <= 90);
+
+                                ?>
+                                @include('app.practice-management.remote-monitoring-row-markup-for-admin')
+                                <?php $trIndex++; ?>
+                            @endforeach
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <script>
+        (function () {
+            let dataTableInst = null;
+            window.refreshRpmRow = function (_index) {
+                let tr = $('#table-rm-matrix tbody tr:eq(' + _index + ')');
+                if (!tr.length) return;
+                let clientUid = tr.attr('data-client-uid'), careMonthUid = tr.attr('data-care-month-uid');
+                $.get('/rpm-matrix-row-for-admin?m={{$mStr}}&y={{$yStr}}&clientUid=' + clientUid + '&careMonthUid=' + careMonthUid + '&trIndex=' + _index, _data => {
+                    let row = $(_data);
+                    @if(request()->input('dt'))
+                    row.find('>td').each(function (_columnIndex) {
+                        dataTableInst.cell(_index, _columnIndex).data(this.innerHTML); //.draw();
+                    });
+                    @else
+                    tr.replaceWith(row);
+                    @endif
+                    $('#practice-remote-monitoring [moe][initialized]').removeAttr('initialized');
+                    initMoes();
+                    tr.addClass('post-refresh-highlight');
+                    setTimeout(function () {
+                        tr.removeClass('post-refresh-highlight');
+                    }, 1000);
+                });
+            }
+
+            function init() {
+                @if(request()->input('dt'))
+                    dataTableInst = $('#table-rm-matrix').DataTable({
+                    paging: false,
+                    columnDefs: [
+                        {
+                            targets: [0, 8],
+                            type: 'string',
+                            render: function (data, type, row, meta) {
+                                if (type === 'sort') {
+                                    return $(data).find('.sort-data').first().text();
+                                }
+                                return data;
+                            },
+                        },
+                        {targets: 1, type: 'date'},
+                        {
+                            targets: 7,
+                            type: 'num',
+                            render: function (data, type, row, meta) {
+                                if (type === 'sort') {
+                                    return $(data).find('.sort-data').first().text();
+                                }
+                                return data;
+                            },
+                        },
+                        {
+                            targets: [5, 6, 10, 11, 12],
+                            type: 'num',
+                            render: function (data, type, row, meta) {
+                                if (type === 'sort') {
+                                    return +($(data).find('.sort-data').first().text());
+                                }
+                                return data;
+                            },
+                        },
+                    ]
+                });
+                @endif
+                $('#practice-remote-monitoring').removeAttr('v-cloak');
+                $('#practice-remote-monitoring [moe][initialized]').removeAttr('initialized');
+
+                let parent = $('#practice-remote-monitoring');
+
+                parent.find('.btn-apply')
+                    .off('click.filter')
+                    .on('click.filter', function() {
+                        fastLoad('{{route('practice-management.rpm-matrix-admin')}}?' + $(this).closest('form').serialize());
+                        return false;
+                    });
+
+                parent.find('.btn-reset')
+                    .off('click.reset')
+                    .on('click.reset', function() {
+                        fastLoad('{{route("practice-management.rpm-matrix-admin")}}');
+                        return false;
+                    });
+
+                initMoes();
+
+                // hack - init split at 22%
+                localStorage['v-split-rounded-rpm-matrix-split'] = 22;
+                initVSplitter('rpm-matrix-split', $('.rpm-matrix-left-column'), $('.rpm-matrix-right-column'), null, {marginLeft: '-3px', width: '5px', height: '100%', marginTop: 0, borderRadius: 0});
+            }
+
+            addMCInitializer('practice-remote-monitoring', init, '#practice-remote-monitoring');
+        }).call(window);
+    </script>
+@endsection

+ 2 - 0
routes/web.php

@@ -352,6 +352,7 @@ Route::middleware('pro.auth')->group(function () {
         Route::get('rpm-mcp', 'PracticeManagementController@remoteMonitoringMCP')->name('rpm-matrix-mcp');
         Route::get('rpm-rmm', 'PracticeManagementController@remoteMonitoringRMM')->name('rpm-matrix-rmm');
         Route::get('rpm-rme', 'PracticeManagementController@remoteMonitoringRME')->name('rpm-matrix-rme');
+        Route::get('rpm-admin', 'PracticeManagementController@rpmMatrixForAdmin')->name('rpm-matrix-admin');
 
 
         //stat tree stuff
@@ -651,6 +652,7 @@ Route::middleware('pro.auth')->group(function () {
     Route::get('rpm-matrix-row-mcp', 'PracticeManagementController@remoteMonitoring_RowMCP')->name('rpm-matrix-row-mcp');
     Route::get('rpm-matrix-row-rmm', 'PracticeManagementController@remoteMonitoring_RowRMM')->name('rpm-matrix-row-rmm');
     Route::get('rpm-matrix-row-rme', 'PracticeManagementController@remoteMonitoring_RowRME')->name('rpm-matrix-row-rme');
+    Route::get('rpm-matrix-row-admin', 'PracticeManagementController@remoteMonitoring_RowADMIN')->name('rpm-matrix-row-admin');
 
     Route::get('/appointment-confirmation-history/{appointment}', 'AppointmentController@appointmentConfirmationHistory')->name('appointment-confirmation-history');