Przeglądaj źródła

RPM admin - multi-sort

Vijayakrishnan 3 lat temu
rodzic
commit
c541d2aed8

+ 42 - 0
app/Helpers/helpers.php

@@ -14,6 +14,48 @@ use App\Models\Bill;
 use Illuminate\Support\Facades\Http;
 use Soundasleep\Html2Text as Html2Text;
 
+if(!function_exists('currentSortForKey')) {
+    function currentSortForKey($current, $key) {
+        $found = false;
+        $current = $current ? $current : [];
+        for ($i = 0; $i < count($current); $i++) {
+            if($current[$i]['key'] === $key) { // if exists, reverse
+                return ["index" => ($i + 1), "order" => $current[$i]['order']];
+            }
+        }
+        return FALSE;
+    }
+}
+
+if(!function_exists('includeOrReverseInMultiSort')) {
+    function includeOrReverseInMultiSort($current, $key) {
+        $found = false;
+        $current = $current ? $current : [];
+        for ($i = 0; $i < count($current); $i++) {
+            if($current[$i]['key'] === $key) { // if exists, reverse
+                $current[$i]['order'] = ($current[$i]['order'] === 'DESC' ? 'ASC' : 'DESC');
+                $found = true;
+                break;
+            }
+        }
+        if (!$found) { // if not exists, include
+            $current[] = ["key" => $key, "order" => 'ASC'];
+        }
+        return $current;
+    }
+}
+
+if(!function_exists('removeFromMultiSort')) {
+    function removeFromMultiSort($current, $key) {
+        $found = false;
+        $current = $current ? $current : [];
+        $current = array_filter($current, function($_x) use ($key) {
+            return $_x['key'] !== $key;
+        });
+        return array_values($current);
+    }
+}
+
 if(!function_exists('toFeetAndInches')) {
     function toFeetAndInches($value, $ftLabel = ' ft.', $inLabel = ' in.') {
         if(!$value) return '-';

+ 13 - 8
app/Http/Controllers/PracticeManagementController.php

@@ -1686,16 +1686,21 @@ WHERE
             $orderBy = "ORDER BY care_month.number_of_days_with_remote_measurements DESC NULLS LAST, care_month.rm_total_time_in_seconds_by_mcp DESC NULLS LAST, care_month.rm_total_time_in_seconds_by_rmm_pro DESC NULLS LAST";
         }
         else {
-            $sortBy = $request->input('sort_by');
-            $sortDir = $request->input('sort_dir');
-            if($sortBy && $sortDir) {
-                if(!in_array($sortBy, ['number_of_days_with_remote_measurements', 'rm_total_time_in_seconds_by_mcp', 'rm_total_time_in_seconds_by_rmm_pro'])) {
-                    $orderBy = "ORDER BY $sortBy $sortDir NULLS LAST, care_month.number_of_days_with_remote_measurements DESC NULLS LAST, care_month.rm_total_time_in_seconds_by_mcp DESC NULLS LAST, care_month.rm_total_time_in_seconds_by_rmm_pro DESC NULLS LAST";
-                }
-                else {
-                    $orderBy = "ORDER BY $sortBy $sortDir NULLS LAST";
+            $sortBy = json_decode($request->input('sort_by'));
+            $orderByClause = [];
+            $includeDefaultKeys = true;
+            foreach ($sortBy as $sortCriteria) {
+                $orderByClause[] = "{$sortCriteria->key} {$sortCriteria->order} NULLS LAST";
+                if(in_array($sortCriteria->key, ['number_of_days_with_remote_measurements', 'rm_total_time_in_seconds_by_mcp', 'rm_total_time_in_seconds_by_rmm_pro'])) {
+                    $includeDefaultKeys = false;
                 }
             }
+            if($includeDefaultKeys) {
+                $orderByClause[] = "care_month.number_of_days_with_remote_measurements DESC NULLS LAST";
+                $orderByClause[] = "care_month.rm_total_time_in_seconds_by_mcp DESC NULLS LAST";
+                $orderByClause[] = "care_month.rm_total_time_in_seconds_by_rmm_pro DESC NULLS LAST";
+            }
+            $orderBy = 'ORDER BY ' . implode(', ', $orderByClause);
         }
 
         // filters from the UI

+ 15 - 0
public/css/style.css

@@ -3676,3 +3676,18 @@ table.v-top th {
     padding-left: 0.5rem;
     padding-right: 0.5rem;
 }
+.sort-header-arrows[sort-index]:after {
+    content: attr(sort-index);
+    font-weight: normal;
+    font-size: 9px;
+    position: absolute;
+    top: -16px;
+    width: 14px;
+    height: 14px;
+    color: #0d59af;
+    border: 1px solid #0d59af;
+    border-radius: 100%;
+    text-align: center;
+    line-height: 12px;
+    right: -12px;
+}

+ 22 - 0
resources/views/app/practice-management/_sort_header_multi.blade.php

@@ -0,0 +1,22 @@
+<?php
+// sort=key:order,key:order...
+$current = request()->input('sort_by');
+$current = $current ? json_decode($current, true) : [];
+$currentSortForKey = currentSortForKey($current, $key);
+$targetSortParamForInclusionOrReversal = json_encode(includeOrReverseInMultiSort($current, $key));
+$targetSortParamForRemoval = json_encode(removeFromMultiSort($current, $key));
+?>
+<div class="d-flex align-items-end flex-wrap">
+    <a href="{{ $route }}?{{queryLineExcept(['sort_by'])}}&sort_by={!! urlencode($targetSortParamForInclusionOrReversal) !!}" class="text-decoration-none">
+        <b class="{{$currentSortForKey ? 'text-primary' : 'text-secondary'}}">{!! $label !!}</b>
+        <span class="ml-1 d-inline-flex align-items-baseline position-relative sort-header-arrows" @if($currentSortForKey) sort-index="{{$currentSortForKey['index']}}" @endif>
+            <i class="text-sm fa fa-chevron-up {{$currentSortForKey && $currentSortForKey['order'] === 'DESC' ? '' : 'on-hover-opaque text-secondary'}}"></i>
+            <i class="ml-1 text-sm fa fa-chevron-down {{$currentSortForKey && $currentSortForKey['order'] === 'ASC' ? '' : 'on-hover-opaque text-secondary'}}"></i>
+        </span>
+    </a>
+    @if($currentSortForKey)
+        <a href="{{ $route }}?{{queryLineExcept(['sort_by'])}}&sort_by={!! urlencode($targetSortParamForRemoval) !!}" class="text-sm on-hover-opaque text-secondary ml-1">
+            <i class="fa fa-times"></i>
+        </a>
+    @endif
+</div>

+ 13 - 13
resources/views/app/practice-management/rpm-matrix-for-admin-table.blade.php

@@ -24,21 +24,21 @@
         <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></th>
-                <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' => 'CM MCP', 'key' => 'mcp_name'])</th>
-                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'Age', 'key' => 'age_in_years'])</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"></th>
+                <th class="border-0 pl-2">@include('app.practice-management._sort_header_multi', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'Name', 'key' => 'client_name'])</th>
+                <th class="border-0">@include('app.practice-management._sort_header_multi', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'CM MCP', 'key' => 'mcp_name'])</th>
+                <th class="border-0">@include('app.practice-management._sort_header_multi', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'Age', 'key' => 'age_in_years'])</th>
+                {{--<th class="border-0">@include('app.practice-management._sort_header_multi', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'RPM?', 'key' => 'is_enrolled_in_rm'])</th>--}}
                 <th class="border-0 text-secondary">BP</th>
                 <th class="border-0 text-secondary">Scale</th>
-                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'DSLV', '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' => '<i class="text-sm fa fa-phone rotateh"></i> MCP', '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' => '<i class="text-sm fa fa-phone rotateh"></i> Any', 'key' => 'has_anyone_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.<br>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<br>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<br>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<br>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<br>Mins.', 'key' => 'rm_total_time_in_seconds_by_rmm_pro'])</th>
+                <th class="border-0">@include('app.practice-management._sort_header_multi', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => 'DSLV', 'key' => 'most_recent_completed_mcp_note_date'])</th>
+                <th class="border-0">@include('app.practice-management._sort_header_multi', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => '<i class="text-sm fa fa-phone rotateh"></i> MCP', 'key' => 'has_mcp_interacted_with_client_about_rm'])</th>
+                <th class="border-0">@include('app.practice-management._sort_header_multi', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => '<i class="text-sm fa fa-phone rotateh"></i> Any', 'key' => 'has_anyone_interacted_with_client_about_rm'])</th>
+                <th class="border-0">@include('app.practice-management._sort_header_multi', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => '#Meas.<br>Days', 'key' => 'number_of_days_with_remote_measurements'])</th>
+                <th class="border-0">@include('app.practice-management._sort_header_multi', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => '#MCP<br>Unst.', 'key' => 'rm_num_measurements_not_stamped_by_mcp'])</th>
+                <th class="border-0">@include('app.practice-management._sort_header_multi', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => '#RMM<br>Unst.', 'key' => 'rm_num_measurements_not_stamped_by_rmm'])</th>
+                <th class="border-0">@include('app.practice-management._sort_header_multi', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => '#MCP<br>Mins.', 'key' => 'rm_total_time_in_seconds_by_mcp'])</th>
+                <th class="border-0">@include('app.practice-management._sort_header_multi', ['route' => route("practice-management.rpm-matrix-admin"), 'label' => '#RMM<br>Mins.', 'key' => 'rm_total_time_in_seconds_by_rmm_pro'])</th>
                 <th class="border-0 text-secondary">MCP</th>
                 <th class="border-0 text-secondary">RMM</th>
                 <th class="border-0 text-secondary">454</th>