Browse Source

CA dashboard

Samson Mutunga 1 year ago
parent
commit
44722738bb

+ 17 - 0
app/Http/Controllers/ClientProAccessController.php

@@ -4,10 +4,20 @@ namespace App\Http\Controllers;
 
 use App\Models\Client;
 use App\Models\ClientProAccess;
+use App\Models\ClientReviewRequest;
 use Illuminate\Http\Request;
 class ClientProAccessController extends Controller
 {
 
+    public function dashboard(Request $request){
+        $performer = $this->performer();
+        $pro = $performer->pro;
+        $performerProID = $performer->pro->id;
+
+        $milliseconds = strtotime(date('Y-m-d')) . '000'; //required by the calendar
+        return view('app.ca.dashboard', compact( 'milliseconds'));
+    }
+
     public function patients(Request $request)
     {
         $filters = $request->all();
@@ -63,4 +73,11 @@ class ClientProAccessController extends Controller
         $patients = $patients->orderBy('created_at', 'DESC')->paginate(20);
         return view('app.ca.patients', compact('patients', 'filters'));
     }
+    public function clientReviewRequests(Request $request){
+        $hideTitle = $request->get('hideTitle');
+        $performer = $this->performer();
+        $pro = $performer->pro;
+        $reviewRequests = ClientReviewRequest::where('pro_id', $pro->id)->where('is_active', true)->orderBy('created_at', 'DESC')->paginate(50);
+        return view('app.ps.review-requests.list', compact('reviewRequests', 'hideTitle'));
+    }
 }

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

@@ -1383,7 +1383,7 @@ WHERE cl.shadow_pro_id IS NULL
     {
         $performer = $this->performer();
         $pro = $performer->pro;
-       
+        
         if($pro->pro_type === 'ADMIN'){
             return $this->dashboard_ADMIN($request);
         }elseif($pro->is_enrolled_as_mcp && $pro->is_considered_for_mcp_assignment) {
@@ -1392,8 +1392,10 @@ WHERE cl.shadow_pro_id IS NULL
             return $this->dashboard_HCP($request); //TODO for HCP
         }elseif($pro->is_considered_for_supervising_physician){
             return redirect()->route('ps.dashboard');
-        }else{
+        }elseif($pro->is_considered_for_dna){
             return $this->dashboard_DNA($request);
+        }else{
+            return redirect()->route('ca.dashboard'); 
         }
     }
 

+ 302 - 0
resources/views/app/ca/dashboard.blade.php

@@ -0,0 +1,302 @@
+@extends ('layouts.template')
+
+@section('content')
+
+    <style>
+        #dashboard-mcp tr.thin th,
+        #dashboard-mcp tr.thin td,
+        #dashboard-mcp .dashboard-stats-table tr td,
+        #dashboard-mcp .dashboard-stats-table tr th {
+            padding: 0.25em;
+            font-weight: normal;
+        }
+
+        #dashboard-dna table.appointments tr td {
+            vertical-align: middle;
+        }
+    </style>
+
+    <div id="dashboard-dna">
+    <div class="p-3">
+        <div class="">
+            <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>
+                    </div>
+                    <div class="card mb-4" stag-collapsible-card="dna-key-numbers">
+                        <div class="card-header pl-2">
+                            <strong>
+                                Key Numbers
+                            </strong>
+                        </div>
+                        <div class="card-body p-0">
+                            <table class="table table-sm mb-0">
+                                <tbody>
+                                    <tr>
+                                        <th class="px-2 text-center">{{$pro->activeClientReviewRequests->count()}}<th>  
+                                        <th class="pl-2">
+                                            <a class="font-weight-normal" href="{{route('ca.client-review-requests', ['hideTitle' => true])}}" native target="_blank" open-in-stag-popup popup-style="tall" title="Charts Pending My Review">Charts Pending My Review </a>
+                                        </th>
+                                    </tr>
+                                    
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                    
+                    <div class="card mb-4" stag-collapsible-card="dna-practice-management" collapsed>
+                        <div class="card-header pl-2">
+                            <strong>
+                                Practice Management
+                            </strong>
+                        </div>
+                        <div class="card-body p-0">
+                            <table class="table table-sm mb-0">
+                                <tbody>
+                                <tr class="thin">
+                                    <th colspan="2" class="font-weight-normal px-2 pl-2">Billing & Reimbursement</th>
+                                </tr>
+                                <tr class="thin">
+                                    <th class="font-weight-normal px-2 pl-4">{{friendly_date_time($performer->pro->getNextPaymentDateAsDna(), false)}}</th>
+                                    <th class="font-weight-normal pl-2">Next Payment Date</th>
+                                </tr>
+                                <tr class="thin">
+                                    <th class="font-weight-normal px-2 pl-4">
+                                        ${{friendly_money($performer->pro->balance)}}</th>
+                                    <th class="font-weight-normal pl-2 w-100"><a
+                                            href="/practice-management/financial-transactions">Current balance</a></th>
+                                </tr>
+                                <tr class="thin">
+                                    <th class="font-weight-normal px-2 pl-4">
+                                        ${{friendly_money($performer->pro->getProcessingAmountAsDna())}}</th>
+                                    <th class="font-weight-normal pl-2"><a
+                                            href="/practice-management/bills-under-processing">Processing</a></th>
+                                </tr>
+
+                               
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-md-9">
+                    <div class="row mcp-theme-1">
+                        <div class="col-md-6 mcp-theme-1">
+                          
+
+                            <!-- ENCOUNTERS PENDING MY REVIEW -->
+                            <div class="card mb-4">
+                                <div class="card-header pl-2">
+                                    <strong>
+                                        Charts Pending My Review
+                                    </strong>
+                                </div>
+                                <div class="card-body p-0">
+                                    @include('app.ca.dashboard.client-charts-pending-my-review')
+                                </div>
+                            </div>
+
+                          
+
+                        </div>
+                        <div class="col-md-6 mcp-theme-1">
+                            <div class="card mb-4">
+                                <div class="card-header pl-2">
+                                    <strong>
+                                        Messages
+                                    </strong>
+                                </div>
+                                <div class="card-body p-0">
+                                    @include('app.dna.dashboard.messages')
+                                </div>
+                            </div>
+                            
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    </div>
+
+    <div class="stag-popup stag-popup-md ticket-popup mcp-theme-1" stag-popup-key="ticket-popup"></div>
+
+    <script>
+        (function () {
+
+            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('-');
+            }
+
+            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 = $('#dna-dashboard-appointments');
+                    apptscontainer.html(_data);
+                    initFastLoad(apptscontainer);
+                    initMoes();
+                });
+            }
+
+            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');
+            }
+
+            function getFormattedCurrentDate() {
+                let date = new Date();
+                let day = date.getDate();
+                day = day < 10 ? '0' + day : day;
+                return date.getFullYear() + '-' + parseInt(date.getMonth() + 1) + '-' + day;
+            }
+
+            function init(_target = null) {
+
+                if(_target && _target !== '.stag-content') return;
+
+                calendarElem = $('.pro-dashboard-inline-calendar');
+                calendarElem.datepicker({
+                    dateFormat: 'yy-mm-dd',
+                    onSelect: function (_date) {
+                        onDateChange(_date);
+                    },
+                    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'];
+                        }
+                        return [true, 'no-events'];
+                    },
+                    defaultDate: 0
+                });
+
+                let date = new Date();
+                let day = date.getDate();
+                day = day < 10 ? '0' + day : day;
+                let mon = parseInt(date.getMonth() + 1);
+                mon = mon < 10 ? '0' + mon : mon;
+                let dateStr = date.getFullYear() + '-' + mon + '-' + day;
+                loadEventDates(dateStr);
+
+                onDateChange(getFormattedCurrentDate());
+                selectedDate = getFormattedCurrentDate();
+
+                $(document)
+                    .off('click', '.ack-client-pro-change')
+                    .on('click', '.ack-client-pro-change', function () {
+                        let trigger = $(this).text('…');
+                        $.post('/api/clientProChange/accept', {
+                            uid: $(this).attr('data-uid')
+                        }, _data => {
+                            if (!hasResponseError(_data)) {
+                                trigger.hide();
+                                let doneElem = $('<i class="text-success fa fa-check"></i>');
+                                doneElem.insertAfter(trigger);
+                                setTimeout(() => {
+                                    let ackContainer = trigger.closest('.ack-container');
+                                    trigger.closest('div').slideUp('fast', function () {
+                                        $(this).remove();
+                                        if (!ackContainer.find('>div').length) {
+                                            ackContainer.remove();
+                                        }
+                                    });
+                                }, 500);
+                            }
+                        }, 'json');
+                        return false;
+                    });
+
+                $(document)
+                    .off('click', '.ack-client-memo')
+                    .on('click', '.ack-client-memo', function () {
+                        let trigger = $(this).text('…');
+                        $.post('/api/clientMemo/stamp', {
+                            uid: $(this).attr('data-uid')
+                        }, _data => {
+                            if (!hasResponseError(_data)) {
+                                trigger.hide();
+                                let doneElem = $('<i class="text-success fa fa-check"></i>');
+                                doneElem.insertAfter(trigger);
+                                setTimeout(() => {
+                                    let tbody = trigger.closest('tbody');
+                                    trigger.closest('tr').remove();
+                                    if (!tbody.find('>tr').length) {
+                                        tbody.closest('.ack-container').remove();
+                                    }
+                                }, 500);
+                            }
+                        }, 'json');
+                        return false;
+                    });
+
+                $(document)
+                    .off('click', '.ack-pro-appt-update')
+                    .on('click', '.ack-pro-appt-update', function () {
+                        let trigger = $(this).text('…');
+                        $.post('/api/appointmentConfirmationDecision/acknowledgeAsAppointmentPro', {
+                            uid: $(this).attr('data-uid')
+                        }, _data => {
+                            if (!hasResponseError(_data)) {
+                                trigger.hide();
+                                let doneElem = $('<i class="text-success fa fa-check"></i>');
+                                doneElem.insertAfter(trigger);
+                                setTimeout(() => {
+                                    let ackContainer = trigger.closest('tbody');
+                                    trigger.closest('tr').slideUp('fast', function () {
+                                        $(this).remove();
+                                        if (!ackContainer.find('>tr').length) {
+                                            ackContainer.remove();
+                                        }
+                                    });
+                                }, 500);
+                            }
+                        }, 'json');
+                        return false;
+                    });
+
+                addMCHook('refreshDashboardAppointments', function() {
+                    onDateChange(selectedDate);
+                });
+            }
+
+            addMCInitializer('pro-dashboard', init, '#pro-dashboard-container');
+        })();
+    </script>
+@endsection

+ 62 - 0
resources/views/app/ca/dashboard/client-charts-pending-my-review.blade.php

@@ -0,0 +1,62 @@
+
+<?php 
+    $reviewRequests = $performer->pro->activeClientReviewRequests;
+?>
+@if(!count($reviewRequests))
+    <div class="mt-3 pl-2">
+        <p>No client review requests found.</p>
+    </div>
+@else
+<div class="table-responsive">
+    <table class="table table-striped table-sm table-bordered">
+        <thead class="bg-light">
+            <tr>
+                <th class="border-0 text-secondary text-nowrap">Created</th>
+                <th class="border-0 text-secondary">Patient</th>
+                <th class="border-0 text-secondary">Scoped Month Start</th>
+                <th class="border-0 text-secondary">Access Start</th>
+                <th class="border-0 text-secondary">Access End</th>                
+                <th class="border-0 text-secondary">Is Active</th>
+                <th class="border-0 text-secondary">Status</th>
+            </tr>
+        </thead>
+        <tbody>
+            @foreach($reviewRequests as $rr)
+            <tr>
+                <td class="text-nowrap">{{ friendlier_date($rr->created_at) }}</td>
+                <td>
+                <a native target="_blank" href="{{route('patients.view.dashboard', $rr->client)}}">
+						{{$rr->client->displayName()}}
+					</a>
+                </td>
+                <td>{{ friendlier_date($rr->scoped_month_start_date) }}</td>
+                <td>{{ friendlier_date($rr->access_start_date) }}</td>
+                <td>{{ friendlier_date($rr->access_end_date) }}</td>                
+                <td>
+                    @if($rr->is_active)
+                    <span class="text-success mr-2">YES
+                        @if($rr->reactivation_memo)
+                        <i class="fas fa-info-circle text-muted" title="{{ $rr->reactivation_memo }}"></i>
+                        @endif
+                    </span>
+                    @else
+                    <span class="text-secondary mr-2">NO
+                        @if($rr->deactivation_memo)
+                        <i class="fas fa-info-circle text-muted" title="{{ $rr->deactivation_memo }}"></i>
+                        @endif
+                    </span>
+                    @endif
+                </td>
+                <td>
+                    <span class="mr-2">{{ $rr->status ?? '--' }}
+                        @if($rr->status_memo )
+                        <i class="fas fa-info-circle text-muted" title="{{ $rr->status_memo }}"></i>
+                        @endif
+                    </span>
+                </td>
+            </tr>
+            @endforeach
+        </tbody>
+    </table>
+</div>
+@endif

+ 2 - 2
resources/views/layouts/patient-header.blade.php

@@ -251,7 +251,7 @@ $addressParts .= implode(", ", $addressPart2);
             <div class="position-relative ml-2">
                 <div class="screen-only">
                     <div>
-                        <label class="{{ $patient->mcp->is_hcp ? '':'text-danger' }}">MCP:</label> <span class="{{ $patient->mcp->is_hcp ? '':'text-danger' }}">{{$mcpName}}</span>
+                        <label class="{{ $patient->mcp && $patient->mcp->is_hcp ? '':'text-danger' }}">MCP:</label> <span class="{{ $patient->mcp && $patient->mcp->is_hcp ? '':'text-danger' }}">{{$mcpName}}</span>
                         @if($patient->has_mcp_done_onboarding_visit === 'YES')
                             <i class="fa fa-check text-sm" title="MCP Onboarding Visit Completed"></i>
                         @endif
@@ -287,7 +287,7 @@ $addressParts .= implode(", ", $addressPart2);
                                 <button class="bg-transparent text-primary border-0 text-sm"><i class="fa fa-user on-hover-opaque"></i></button>
                             </form>
                         @endif
-                        @if(!$patient->mcp->is_hcp)
+                        @if($patient->mcp && !$patient->mcp->is_hcp)
                             <small class="text-danger font-weight-bold"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $patient->mcp->name_first }} is no longer HCP. Reassign.</small>
                         @endif
                     </div>

+ 4 - 1
routes/web.php

@@ -8,6 +8,7 @@ use App\Http\Controllers\SystemFileController;
 use App\Http\Controllers\MessageController;
 use App\Http\Controllers\CompanyClientController;
 use App\Http\Controllers\CustomerController;
+use App\Http\Controllers\ClientProAccessController;
 
 /*
 |--------------------------------------------------------------------------
@@ -215,7 +216,9 @@ Route::middleware('pro.auth')->group(function () {
     });
 
     Route::name('ca.')->prefix('ca')->group(function () {
-        Route::get('patients', 'ClientProAccessController@patients')->name('patients');
+        Route::get('dashboard', [ClientProAccessController::class, 'dashboard'])->name('dashboard');
+        Route::get('client-review-requests', [ClientProAccessController::class, 'clientReviewRequests'])->name('client-review-requests');
+        Route::get('patients', [ClientProAccessController::class, 'patients'])->name('patients');
 
 
     });