Browse Source

Pharmacy live search in add/edit ERx

Vijayakrishnan 4 năm trước cách đây
mục cha
commit
ba3370edcb

+ 24 - 0
app/Http/Controllers/HomeController.php

@@ -6,6 +6,7 @@ use App\Lib\Backend;
 use App\Models\Appointment;
 use App\Models\AppSession;
 use App\Models\ClientSMS;
+use App\Models\Facility;
 use App\Models\Ticket;
 use DateTime;
 
@@ -385,6 +386,29 @@ class HomeController extends Controller
         return view('app/patient-suggest', compact('clients'));
     }
 
+    public function pharmacySuggest(Request $request)
+    {
+        $term = $request->input('term') ? trim($request->input('term')) : '';
+        if (empty($term)) return '';
+        $pharmacies = Facility::where('facility_type', 'Pharmacy')
+            ->where(function ($q) use ($term) {
+                $q->orWhere('name', 'ILIKE', '%' . $term . '%')
+                    ->orWhere('address_line1', 'ILIKE', '%' . $term . '%')
+                    ->orWhere('address_line2', 'ILIKE', '%' . $term . '%')
+                    ->orWhere('address_city', 'ILIKE', '%' . $term . '%')
+                    ->orWhere('address_state', 'ILIKE', '%' . $term . '%')
+                    ->orWhere('phone', 'ILIKE', '%' . $term . '%')
+                    ->orWhere('address_zip', 'ILIKE', '%' . $term . '%');
+            })
+            ->orderBy('name', 'asc')
+            ->orderBy('address_line1', 'asc')
+            ->orderBy('address_city', 'asc')
+            ->orderBy('address_state', 'asc')
+            ->get();
+
+        return view('app/pharmacy-suggest', compact('pharmacies'));
+    }
+
     public function unmappedSMS(Request $request, $filter = '')
     {
         $proID = $this->performer()->pro->id;

+ 12 - 0
app/Models/Facility.php

@@ -9,4 +9,16 @@ class Facility extends Model
 
     protected $table = 'facility';
 
+    public function displayString()
+    {
+        return implode(", ", array_filter([
+            $this->name,
+            $this->address_line1,
+            $this->address_city,
+            $this->address_state,
+        ], function ($_item) {
+            return !empty($_item);
+        }));
+    }
+
 }

+ 4 - 0
public/css/style.css

@@ -1194,3 +1194,7 @@ button.note-templates-trigger-assessment {
 .in-table-markup p:last-of-type {
     margin-bottom: 0;
 }
+.suggestions-outer.pharmacy-suggestions {
+    left: 1rem;
+    width: calc(100% - 2rem);
+}

+ 1 - 1
resources/views/app/patient-suggest.blade.php

@@ -3,7 +3,7 @@
 @endif
 <?php $activeSet = false; ?>
 @foreach($clients as $client)
-    <a class="d-block suggest-item text-nowrap {{ $activeSet ? '' : 'active'  }}"
+    <a class="d-block suggest-item patient-suggest text-nowrap {{ $activeSet ? '' : 'active'  }}"
        href="" data-target-uid="{{$client->uid}}">
         {{$client->displayName()}}
         {!! $client->cell_number ? '<span class="text-sm text-secondary ml-1">(' . $client->cell_number . ')</span>' : '' !!}

+ 5 - 2
resources/views/app/patient/action-items-erx-single.blade.php

@@ -139,9 +139,10 @@
                         </div>
                     </div>
                     <div class="row mb-2">
-                        <div class="col-8">
+                        <div class="col-12">
                             <label class="text-sm text-secondary mb-1">Business Name</label>
-                            <input type="text" v-model="popupItem.pharmacyName" class="form-control form-control-sm">
+                            <input type="text" autocomplete="donotdoit" id="pharmacy-search" v-model="popupItem.pharmacyName" class="form-control form-control-sm">
+                            <div class="suggestions-outer pharmacy-suggestions position-absolute d-none"></div>
                         </div>
                     </div>
                     <div class="row mb-2">
@@ -382,12 +383,14 @@
                                     this.item.pharmacyFax,
                                 ].filter(Boolean).join('<br>');
                             },
+                            @include('app.patient.partials.pharmacy-suggest')
                             @include('app.patient.partials.ticket_vue_methods',['ticketType'=>'erx'])
                         },
                         mounted: function () {
                             this.initRxAutoSuggest();
                             this.initICDAutoSuggest();
                             initFastLoad($('#erxSingleApp'));
+                            this.initPharmacySearch();
                         }
                     })
                 }

+ 5 - 2
resources/views/app/patient/partials/erx.blade.php

@@ -142,9 +142,10 @@
                 </div>
             </div>
             <div class="row mb-2">
-                <div class="col-8">
+                <div class="col-12">
                     <label class="text-sm text-secondary mb-1">Business Name</label>
-                    <input type="text" v-model="popupItem.pharmacyName" class="form-control form-control-sm">
+                    <input type="text" autocomplete="donotdoit" id="pharmacy-search" v-model="popupItem.pharmacyName" class="form-control form-control-sm">
+                    <div class="suggestions-outer pharmacy-suggestions position-absolute d-none"></div>
                 </div>
             </div>
             <div class="row mb-2">
@@ -394,12 +395,14 @@
                             _item.pharmacyFax,
                         ].filter(Boolean).join('<br>');
                     },
+                    @include('app.patient.partials.pharmacy-suggest')
                     @include('app.patient.partials.ticket_vue_methods',['ticketType'=>'erx'])
                 },
                 mounted: function () {
                     this.initRxAutoSuggest();
                     this.initICDAutoSuggest();
                     initFastLoad($('#erxApp'));
+                    this.initPharmacySearch();
                 }
             })
         }

+ 98 - 0
resources/views/app/patient/partials/pharmacy-suggest.blade.php

@@ -0,0 +1,98 @@
+initPharmacySearch: function () {
+    let self = this;
+    const debounce = (func, wait) => {
+        let timeout;
+        return function executedFunction(...args) {
+            const later = () => {
+                clearTimeout(timeout);
+                func(...args);
+            };
+            clearTimeout(timeout);
+            timeout = setTimeout(later, wait);
+        };
+    };
+    var lastTerm = '';
+    var returnedFunction = debounce(function () {
+        var term = $.trim($('#pharmacy-search').val());
+        if (!!term && lastTerm !== term) {
+            $.get('/pharmacy-suggest?term=' + term, function (_data) {
+                $('.suggestions-outer.pharmacy-suggestions').html(_data).removeClass('d-none');
+            });
+            lastTerm = term;
+        } else {
+            $('.suggestions-outer.pharmacy-suggestions').addClass('d-none');
+        }
+    }, 250);
+    $('#pharmacy-search')
+        .on('keydown', function (e) {
+            var term = $.trim($('#pharmacy-search').val());
+            var activeItem = $('.suggestions-outer.pharmacy-suggestions .suggest-item.active');
+            switch (e.which) {
+                case 27:
+                    $('.suggestions-outer.pharmacy-suggestions').addClass('d-none');
+                    return false;
+                case 38:
+                    if (activeItem.prev().length) {
+                        activeItem.prev()
+                            .addClass('active')
+                            .siblings().removeClass('active');
+                        activeItem = $('.suggestions-outer.pharmacy-suggestions .suggest-item.active');
+                        if (activeItem.length) {
+                            activeItem[0].scrollIntoView();
+                        }
+                    }
+                    return false;
+                case 40:
+                    if (activeItem.next().length) {
+                        activeItem.next()
+                            .addClass('active')
+                            .siblings().removeClass('active');
+                        activeItem = $('.suggestions-outer.pharmacy-suggestions .suggest-item.active');
+                        if (activeItem.length) {
+                            activeItem[0].scrollIntoView();
+                        }
+                    }
+                    return false;
+                case 13:
+                    if (activeItem.length) {
+                        activeItem.first().click();
+                    }
+                    return false;
+                default:
+                    if (!!term) {
+                        $('.suggestions-outer.pharmacy-suggestions')
+                            .html('<span class="d-block no-suggest-items">Searching...</span>')
+                            .removeClass('d-none');
+                        returnedFunction();
+                    } else {
+                        $('.suggestions-outer.pharmacy-suggestions').addClass('d-none');
+                    }
+                    break;
+            }
+        })
+        .on('keypress', function (e) {
+            var term = $.trim($('#pharmacy-search').val());
+            if (!!term) {
+                $('.suggestions-outer.pharmacy-suggestions')
+                    .html('<span class="d-block no-suggest-items">Searching...</span>')
+                    .removeClass('d-none');
+                returnedFunction();
+            } else {
+                $('.suggestions-outer.pharmacy-suggestions').addClass('d-none');
+            }
+        });
+    $(document).on('click', '.suggest-item.pharmacy-suggest[data-target-uid]', function () {
+        $('#pharmacy-search').val('');
+        $('.suggestions-outer.pharmacy-suggestions').addClass('d-none');
+        self.applySuggestion(this);
+        return false;
+    });
+},
+applySuggestion: function(_elem) {
+    this.popupItem.pharmacyName = $(_elem).attr('data-pharmacyName');
+    this.popupItem.pharmacyCity = $(_elem).attr('data-pharmacyCity');
+    this.popupItem.pharmacyState = $(_elem).attr('data-pharmacyState');
+    this.popupItem.pharmacyAddressMemo = $(_elem).attr('data-pharmacyAddressMemo');
+    this.popupItem.pharmacyPhone = $(_elem).attr('data-pharmacyPhone');
+    this.popupItem.pharmacyFax = $(_elem).attr('data-pharmacyFax');
+},

+ 18 - 0
resources/views/app/pharmacy-suggest.blade.php

@@ -0,0 +1,18 @@
+@if(!count($pharmacies))
+    <span class="d-block no-suggest-items">No matching pharmacies!</span>
+@endif
+<?php $activeSet = false; ?>
+@foreach($pharmacies as $pharmacy)
+    <a native class="d-block suggest-item pharmacy-suggest text-nowrap {{ $activeSet ? '' : 'active'  }}" href="#"
+       data-target-uid="{{$pharmacy->uid}}"
+       data-pharmacyName="{{$pharmacy->name}}"
+       data-pharmacyCity="{{$pharmacy->address_city}}"
+       data-pharmacyState="{{$pharmacy->address_state}}"
+       data-pharmacyAddressMemo="{{$pharmacy->address_line1}}"
+       data-pharmacyPhone="{{$pharmacy->phone}}"
+       data-pharmacyFax="{{$pharmacy->fax}}"
+    >
+        {{$pharmacy->displayString()}}
+    </a>
+    <?php $activeSet = true; ?>
+@endforeach

+ 1 - 1
resources/views/layouts/guest_template.blade.php

@@ -173,7 +173,7 @@
                         $('.suggestions-outer').addClass('d-none');
                     }
                 });
-            $(document).on('click', '.suggest-item[data-target-uid]', function() {
+            $(document).on('click', '.suggest-item.patient-suggest[data-target-uid]', function() {
                 $('#patient-search').val('');
                 $('.suggestions-outer').addClass('d-none');
                 fastLoad('/patients/view/' + $(this).attr('data-target-uid'), true, false, false);

+ 1 - 1
resources/views/layouts/template.blade.php

@@ -276,7 +276,7 @@
                     $('.suggestions-outer').addClass('d-none');
                 }
             }
-            $(document).on('click', '.suggest-item[data-target-uid]', function() {
+            $(document).on('click', '.suggest-item.patient-suggest[data-target-uid]', function() {
                 $('#patient-search').val('');
                 $('.suggestions-outer').addClass('d-none');
                 fastLoad('/patients/view/' + $(this).attr('data-target-uid'), true, false, false);

+ 4 - 1
routes/web.php

@@ -81,7 +81,7 @@ Route::middleware('pro.auth')->group(function () {
         Route::get('my-favorites/{filter?}', 'PracticeManagementController@myFavorites')->name('myFavorites');
         Route::get('pro-availability/{proUid?}', 'PracticeManagementController@proAvailability')->name('proAvailability');
         Route::get('calendar/{proUid?}', 'PracticeManagementController@calendar')->name('proCalendar');
-       
+
         Route::middleware('pro.auth.admin')->group(function(){
             Route::get('billing-manager/{proUid?}', 'PracticeManagementController@billingManager')->name('billingManager');
             Route::get('tickets', 'PracticeManagementController@tickets')->name('tickets');
@@ -160,6 +160,9 @@ Route::middleware('pro.auth')->group(function () {
     // Patient suggest
     Route::get('/patients-suggest', 'HomeController@patientsSuggest');
 
+    // Pharmacy suggest
+    Route::get('/pharmacy-suggest', 'HomeController@pharmacySuggest');
+
     // embeddable sections
     Route::get('/embed/{patient}/{section}/{selectable}', 'PatientController@embedSection')->name('embed-section');