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

Tickets v1 (wip) - Integrate lab, imaging and equipment [draft]

Vijayakrishnan 4 жил өмнө
parent
commit
f2111db6c5

+ 57 - 507
resources/views/app/patient/tickets.blade.php

@@ -3,6 +3,8 @@
 
     <?php
 
+    $categories = ['erx', 'lab', 'imaging', 'equipment'];
+
     function adjustBrightness($hex, $steps) {
         $steps = max(-255, min(255, $steps));
         $hex = str_replace('#', '', $hex);
@@ -60,339 +62,10 @@
             </select>
         </div>
 
-        <div class="my-4">
-            <div class="d-flex align-items-end mb-3">
-                <h4 class="font-weight-bold m-0 text-secondary font-size-16">ERx
-                    <span v-if="statusFilter === 'open'" class="text-secondary font-weight-normal">(@{{ erxNumOpen }} open)</span>
-                    <span v-if="statusFilter === 'closed'" class="text-secondary font-weight-normal">(@{{ erxNumClosed }} closed)</span>
-                    <span v-if="statusFilter === 'all'" class="text-secondary font-weight-normal">(@{{ erxNumOpen }} open, @{{ erxNumClosed }} closed)</span>
-                </h4>
-                <a class="py-1 px-3 c-pointer btn btn-sm btn-primary text-white mx-4 font-weight-bold"
-                   v-on:click.prevent="showErxPopup()">Add</a>
-                <a class="py-0 font-weight-normal c-pointer flex-grow-1 text-right pr-2"
-                   v-if="!erxCollapsed"
-                   v-on:click.prevent="erxCollapsed = true">
-                    <i class="text-secondary fa fa-chevron-up"></i>
-                </a>
-                <a class="py-0 font-weight-normal c-pointer flex-grow-1 text-right pr-2"
-                   v-if="erxCollapsed"
-                   v-on:click.prevent="erxCollapsed = false">
-                    <i class="text-secondary fa fa-chevron-down"></i>
-                </a>
-            </div>
-            <div class="ticket-section" :class="erxCollapsed ? 'ticket-section-collapsed' : ''">
-                <table class="table table-sm tickets-table mb-0">
-                <tbody>
-                <tr v-for="(item, index) in ticketsByType.erx"
-                    v-if="statusFilter === 'all' || (statusFilter === 'open' && item.is_open) || (statusFilter === 'closed' && !item.is_open)"
-                    :class="(item.is_open ? ' ' : 'opacity-60 bg-light ') + (currentItemUid === item.uid ? 'current' : '')">
-                    <td class="px-2 py-2 c-pointer" v-on:click.prevent="showErxPopup(item)">
-                        <div class="d-flex align-items-center">
-                            <div class="pro-initials text-uppercase"
-                                 :title="allProsFlat['pro_' + item.assigned_pro_id].displayedName"
-                                 :style="'background-color: ' + allProsFlat['pro_' + item.assigned_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + item.assigned_pro_id].colors.fc + ';'">
-                                @{{allProsFlat['pro_' + item.assigned_pro_id].displayedInitials}}
-                            </div>
-                            <div class="flex-grow-1 d-inline-flex ml-2 flex-wrap align-items-center">
-                                <span class="font-weight-bold text-dark font-size-13">@{{item.data.medication}}</span>
-                                <span class="d-inline-flex align-items-center" v-if="item.data.strength">
-                                    <span class="mx-2 text-secondary">•</span>
-                                    <span>@{{item.data.strength}}</span>
-                                </span>
-<!--                                <span class="d-inline-flex align-items-center" v-if="item.data.route">
-                                    <span class="mx-2 text-secondary">•</span>
-                                    <span>@{{item.data.route}}</span>
-                                </span>
-                                <span class="d-inline-flex align-items-center" v-if="item.data.frequency">
-                                    <span class="mx-2 text-secondary">•</span>
-                                    <span>@{{item.data.frequency}}</span>
-                                </span>-->
-                                <!--
-                                <span class="d-inline-flex align-items-center" v-if="item.data.dispense">
-                                    <span class="mx-2 text-secondary">•</span>
-                                    <span>Dispense:</span> @{{item.data.dispense}}
-                                    <span class="text-secondary ml-1" v-html="inWords(item.data.dispense)"></span>
-                                </span>
-                                <span class="d-inline-flex align-items-center" v-if="item.data.refills">
-                                    <span class="mx-2 text-secondary">•</span>
-                                    <span><span>Refills:</span> @{{item.data.refills}}</span>
-                                </span>
-                                <span class="d-inline-flex align-items-center" v-if="item.data.purpose">
-                                    <span class="mx-2 text-secondary">•</span>
-                                    <span><span>Purpose:</span> @{{item.data.purpose}}</span>
-                                </span>
-                                -->
-                                <span class="text-nowrap ml-4 text-secondary" v-html="pharmacy(item.data)"></span>
-                                <span class="text-nowrap ml-auto text-sm" v-if="item.data.due_date">
-                                    <div title="Due Date" class="pro-initials text-uppercase text-white bg-info"><i class="fa fa-calendar-day"></i></div>
-                                    <span class="text-secondary ml-1">@{{ item.data.due_date }}</span>
-                                </span>
-                            </div>
-                        </div>
-                        <!--
-                        <div>
-                            <span class="text-secondary text-sm mt-1">Created:</span>
-                            @{{ item.created_at }}
-                        </div>
-                        -->
-                    </td>
-                    {{--@include('app.patient.tickets.ticket_vue_collab_column')--}}
-                    {{--<td class="px-2">
-                        <a class="mr-2 c-pointer" v-on:click.prevent="showPopup('erx-popup', item)">Edit</a>
-                        <a class="mr-2 c-pointer" v-if="item.is_open" v-on:click.prevent="closeItem(item)">Close</a>
-                        <a class="mr-2 c-pointer" v-if="!item.is_open" v-on:click.prevent="openItem(item)">Open</a>
-
-                        @include('app.patient.partials.ticket_action_links')
-                    </td>--}}
-                </tr>
-                </tbody>
-            </table>
-            </div>
-            <div class="stag-popup stag-popup-sm stag-slide mcp-theme-1" stag-popup-key="erx-popup">
-                <form method="POST" action="" class="p-0">
-                    <h3 class="stag-popup-title mb-0 p-3 bg-light">
-                        <span class="text-nowrap overflow-hidden text-ellipsis mr-3">@{{ erxPopupMode === 'add' ? 'Add ERx Ticket' : erxPopupItem.data.medication + '  •  ' + erxPopupItem.data.strength }}</span>
-                        <div v-if="erxPopupMode === 'edit'" class="ml-auto mr-3">
-                            <a v-if="erxPopupItem.is_open" href="#"
-                               class="btn btn-sm btn-default border bg-white text-dark text-nowrap shadow-none"
-                               v-on:click.prevent="closeItem(erxPopupItem)">
-                                <i class="fa fa-check text-success mr-2"></i>Mark Complete
-                            </a>
-                            <a v-if="!erxPopupItem.is_open" href="#"
-                               class="btn btn-sm btn-success text-nowrap text-white shadow-none"
-                               v-on:click.prevent="openItem(erxPopupItem)">
-                                <i class="fa fa-check mr-2"></i>Complete
-                            </a>
-                        </div>
-                        <a href="#" class="text-secondary"
-                           onclick="return closeStagPopup()"><i class="fa fa-chevron-right"></i></a>
-                    </h3>
-
-                    <!-- common - only applicable for edit -->
-                    <div class="p-3 border-bottom">
-
-                        <div v-if="erxPopupMode === 'edit'">
-                            <div class="row mb-2">
-                                <div class="col-3 d-inline-flex align-items-center">
-                                    <label class="text-secondary m-0">Assigned Pro</label>
-                                </div>
-                                <div class="col-9">
-                                    <div class="d-flex align-items-center">
-                                        <div class="pro-initials text-uppercase"
-                                             :title="allProsFlat['pro_' + erxPopupItem.assigned_pro_id].displayedName"
-                                             :style="'background-color: ' + allProsFlat['pro_' + erxPopupItem.assigned_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + erxPopupItem.assigned_pro_id].colors.fc + ';'">
-                                            @{{allProsFlat['pro_' + erxPopupItem.assigned_pro_id].displayedInitials}}
-                                        </div>
-                                        <div class="flex-grow-1 ml-2">
-                                            <select provider-search
-                                                    data-field="assigned_pro_uid"
-                                                    v-model="erxPopupItem.assigned_pro_uid"
-                                                    :data-pro-name="[erxPopupItem.assigned_pro.name_last, erxPopupItem.assigned_pro.name_first].filter(Boolean).join(', ')"
-                                                    class="form-control form-control-sm">
-                                                <option value=""> --select--</option>
-                                            </select>
-                                        </div>
-                                    </div>
-                                </div>
-                            </div>
-                            <div class="row mb-2">
-                                <div class="col-3 d-inline-flex align-items-center">
-                                    <label class="text-secondary m-0">Ordering Pro</label>
-                                </div>
-                                <div class="col-9">
-                                    <div class="d-flex align-items-center">
-                                        <div class="pro-initials text-uppercase"
-                                             :title="allProsFlat['pro_' + erxPopupItem.ordering_pro_id].displayedName"
-                                             :style="'background-color: ' + allProsFlat['pro_' + erxPopupItem.ordering_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + erxPopupItem.ordering_pro_id].colors.fc + ';'">
-                                            @{{allProsFlat['pro_' + erxPopupItem.ordering_pro_id].displayedInitials}}
-                                        </div>
-                                        <div class="flex-grow-1 ml-2">
-                                            <select provider-search
-                                                    data-field="ordering_pro_uid"
-                                                    v-model="erxPopupItem.ordering_pro_uid"
-                                                    :data-pro-name="[erxPopupItem.ordering_pro.name_last, erxPopupItem.ordering_pro.name_first].filter(Boolean).join(', ')"
-                                                    class="form-control form-control-sm">
-                                                <option value=""> --select--</option>
-                                            </select>
-                                        </div>
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-
-                        <div class="row">
-                            <div class="col-3 d-inline-flex align-items-center">
-                                <label class="text-secondary m-0">Due Date</label>
-                            </div>
-                            <div class="col-9">
-                                <div class="d-flex align-items-center">
-                                    <div class="pro-initials text-uppercase text-white bg-info"
-                                         title="Due Date">
-                                        <i class="fa fa-calendar-day"></i>
-                                    </div>
-                                    <div class="flex-grow-1 ml-2">
-                                        <input type="text" data-field="due_date" placeholder="Due Date"
-                                               v-model="erxPopupItem.data.due_date" class="form-control form-control-sm date-input">
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-
-                    </div>
-
-                    <div class="p-3 border-bottom">
-
-                        <div class="row mb-2">
-                            <div class="col-12">
-                                <label class="text-secondary mb-0 font-weight-normal font-size-16">ERx</label>
-                            </div>
-                        </div>
-                        <div class="row mb-2">
-                            <div class="col-9">
-                                <label class="text-sm text-secondary mb-1">Medication</label>
-                                <input type="hidden" v-model="erxPopupItem.data.medication">
-                                <input required type="text" data-field="medication" placeholder="Medication"
-                                       :value="erxPopupItem.data.medication"
-                                       class="form-control form-control-sm">
-                            </div>
-                            <div class="col-3 pl-0">
-                                <label class="text-sm text-secondary mb-1">Strength</label>
-                                <input type="hidden" v-model="erxPopupItem.data.strength">
-                                <input type="text" data-field="strength" placeholder="Strength"
-                                       :value="erxPopupItem.data.strength"
-                                       class="form-control form-control-sm min-width-unset">
-                            </div>
-                        </div>
-                        <div class="row mb-2">
-                            <div class="col-3">
-                                <label class="text-sm text-secondary mb-1">Frequency</label>
-                                <input type="text" placeholder="Frequency"
-                                       v-model="erxPopupItem.data.frequency" class="form-control form-control-sm min-width-unset"
-                                       data-option-list="frequency-options">
-                                <div id="frequency-options" class="data-option-list">
-                                    <div>Once a day</div>
-                                    <div>Twice a day</div>
-                                </div>
-                            </div>
-                            <div class="col-3 pl-0">
-                                <label class="text-sm text-secondary mb-1">Route</label>
-                                <input required type="text" placeholder="Route"
-                                       v-model="erxPopupItem.data.route" class="form-control form-control-sm min-width-unset"
-                                       data-option-list="route-options">
-                                <div id="route-options" class="data-option-list">
-                                    <div>PO (by mouth)</div>
-                                    <div>PR (per rectum)</div>
-                                    <div>IM (intramuscular)</div>
-                                    <div>IV (intravenous)</div>
-                                    <div>ID (intradermal)</div>
-                                    <div>IN (intranasal)</div>
-                                    <div>TP (topical)</div>
-                                    <div>SL (sublingual)</div>
-                                    <div>BUCC (buccal)</div>
-                                    <div>IP (intraperitoneal)</div>
-                                </div>
-                            </div>
-                            <div class="col-3 pl-0">
-                                <label class="text-sm text-secondary mb-1">Dispense Amount</label>
-                                <input required type="number" placeholder="Dispense Amount"
-                                       v-model="erxPopupItem.data.dispense" class="form-control form-control-sm min-width-unset">
-                            </div>
-                            <div class="col-3 pl-0">
-                                <label class="text-sm text-secondary mb-1">Refills</label>
-                                <input type="number" placeholder="Refills"
-                                       v-model="erxPopupItem.data.refills" class="form-control form-control-sm min-width-unset">
-                            </div>
-                        </div>
-                        <div class="row">
-                            <div class="col-12">
-                                <label class="text-sm text-secondary mb-1">Purpose</label>
-                                <input required type="text"  placeholder="Purpose"
-                                       data-field="icd" v-model="erxPopupItem.data.purpose" class="form-control form-control-sm">
-                            </div>
-                        </div>
-
-                    </div>
-                    <div class="p-3 border-bottom">
-                        <div class="row mb-2">
-                            <div class="col-12">
-                                <label class="text-secondary mb-0 font-weight-normal font-size-16">Preferred Pharmacy</label>
-                            </div>
-                        </div>
-                        <div class="row mb-2">
-                            <div class="col-12">
-                                <label class="text-sm text-secondary mb-1">Business Name</label>
-                                <input type="text" autocomplete="donotdoit" placeholder="Business Name" id="pharmacy-search" v-model="erxPopupItem.data.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">
-                            <div class="col-4">
-                                <label class="text-sm text-secondary mb-1">City</label>
-                                <input type="text" placeholder="City" v-model="erxPopupItem.data.pharmacyCity" class="form-control form-control-sm min-width-unset">
-                            </div>
-                            <div class="col-2 pl-0">
-                                <label class="text-sm text-secondary mb-1">State</label>
-                                <input type="text" placeholder="State" v-model="erxPopupItem.data.pharmacyState" class="form-control form-control-sm min-width-unset">
-                            </div>
-                            <div class="col-3 pl-0">
-                                <label class="text-sm text-secondary mb-1">Phone</label>
-                                <input type="text" placeholder="Phone" v-model="erxPopupItem.data.pharmacyPhone" class="form-control form-control-sm min-width-unset">
-                            </div>
-                            <div class="col-3 pl-0">
-                                <label class="text-sm text-secondary mb-1">Fax</label>
-                                <input type="text" placeholder="Fax" v-model="erxPopupItem.data.pharmacyFax" class="form-control form-control-sm min-width-unset">
-                            </div>
-                        </div>
-                        <div class="row mb-2">
-                            <div class="col-12">
-                                <label class="text-sm text-secondary mb-1">Address Memo</label>
-                                <input type="text" placeholder="Address Memo" autocomplete="donotdoit" v-model="erxPopupItem.data.pharmacyAddressMemo" class="form-control form-control-sm">
-                            </div>
-                        </div>
-                        <div v-if="erxPopupMode === 'add'" class="d-flex align-items-center justify-content-start mt-3">
-                            <button type="button" class="btn btn-sm btn-primary mr-2" v-on:click.prevent="saveErxPopupItem()">Submit</button>
-                            <button type="button" class="btn btn-sm btn-default border" onclick="return closeStagPopup()">Cancel</button>
-                        </div>
-                    </div>
-
-                    <!-- comments -->
-                    <div v-if="erxPopupMode === 'edit' && erxPopupItem.data.comments && erxPopupItem.data.comments.length" class="px-3 pt-3 pb-0 bg-light">
-                        <div class="row mb-3">
-                            <div class="col-12">
-                                <label class="text-secondary mb-0 font-weight-normal font-size-16">Comments (@{{ erxPopupItem.data.comments.length }})</label>
-                            </div>
-                        </div>
-                        <div v-for="(message) in erxPopupItem.data.comments" class="d-flex align-items-start pb-3">
-                            <div class="pro-initials text-uppercase mr-2"
-                                 :title="allProsFlat['pro_' + message.pro_id].displayedName"
-                                 :style="'background-color: ' + allProsFlat['pro_' + message.pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + message.pro_id].colors.fc + ';'">
-                                @{{allProsFlat['pro_' + message.pro_id].displayedInitials}}
-                            </div>
-                            <div class="flex-grow-1">
-                                <div class="">
-                                    @{{ allProsFlat['pro_' + message.pro_id].displayedName }}
-                                    <span class="text-secondary ml-3">@{{ message.created_at }}</span>
-                                </div>
-                                <div>@{{ message.message }}</div>
-                            </div>
-                        </div>
-                    </div>
-
-                    <div v-if="erxPopupMode === 'edit'" class="comment-input-outer p-3 bg-light d-flex align-items-start border-top">
-                        <div class="pro-initials text-uppercase mr-2"
-                             :title="allProsFlat['pro_' + own_pro_id].displayedName"
-                             :style="'background-color: ' + allProsFlat['pro_' + own_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + own_pro_id].colors.fc + ';'">
-                            @{{allProsFlat['pro_' + own_pro_id].displayedInitials}}
-                        </div>
-                        <div class="flex-grow-1 position-relative">
-                            <textarea class="form-control form-control-sm txt-comment shadow-none" v-model="comment"></textarea>
-                            <a href="#" v-on:click.prevent="saveErxComment()" class="btn btn-sm btn-primary text-white btn-save-comment">Comment</a>
-                        </div>
-                    </div>
-                </form>
-            </div>
-            @include('app.patient.partials.ticket_update_pro_form',['ticketType'=>'erx'])
-        </div>
+        @include('app.patient.tickets.erx')
+        @include('app.patient.tickets.lab')
+        @include('app.patient.tickets.imaging')
+        @include('app.patient.tickets.equipment')
 
     </div>
 
@@ -413,9 +86,9 @@
 
             $ticketsByType = [
                 "erx" => [],
-                "equipment" => [],
                 "lab" => [],
                 "imaging" => [],
+                "equipment" => [],
             ];
 
             $ticketsArray = [];
@@ -453,49 +126,14 @@
 
                         statusFilter: 'open',
 
-                        // erx
-                        erxCollapsed: false,
-                        erxPopupMode: 'add',
-                        erxPopupItem: {
-                            uid: '',
-                            is_open: true,
-                            assigned_pro_uid: '',
-                            ordering_pro_uid: '',
-                            data: {
-                                due_date: '',
-                                medication: '',
-                                strength: '',
-                                amount: '',
-                                route: '',
-                                frequency: '',
-                                dispense: '',
-                                refills: '',
-                                purpose: '',
-                                pharmacyName: '',
-                                pharmacyCity: '',
-                                pharmacyState: '',
-                                pharmacyAddressMemo: '',
-                                pharmacyPhone: '',
-                                pharmacyFax: '',
-                                comments: [{
-                                    pro_id: '',
-                                    message: '',
-                                    created_at: '',
-                                }],
-                            }
-                        },
-
-                        // lab
-                        labPopupMode: 'add',
-                        labPopupItem: {
-                            uid: '',
-                            is_open: true,
-                            tests: [''],
-                            icds: [''],
-                            memo: '',
-                        },
+                        // category specific fields
+                        @include('app.patient.tickets.erx-data')
+                        @include('app.patient.tickets.lab-data')
+                        @include('app.patient.tickets.imaging-data')
+                        @include('app.patient.tickets.equipment-data')
 
                         // common
+                        currentCategory: '',
                         currentItemUid: '',
                         allPros: {!! json_encode($allPros) !!},
                         allProsFlat: {!! json_encode($allProsFlat) !!},
@@ -506,7 +144,9 @@
                         comment: '',
 
                         // debounced auto-saver
-                        autoSave: null,
+                        <?php for ($i=0; $i<count($categories); $i++) { ?>
+                            {{ $categories[$i] }}AutoSave: null,
+                        <?php } ?>
                     },
                     computed: {
                         numAll: function() {
@@ -518,133 +158,38 @@
                         numClosed: function() {
                             return this.tickets.filter(_x => !_x.is_open).length;
                         },
-                        erxNumAll: function() {
-                            return this.ticketsByType.erx.length;
-                        },
-                        erxNumOpen: function() {
-                            return this.ticketsByType.erx.filter(_x => _x.is_open).length;
-                        },
-                        erxNumClosed: function() {
-                            return this.ticketsByType.erx.filter(_x => !_x.is_open).length;
-                        },
-                        erxCurrentItemData: function() {
-                            return this.erxPopupItem.data;
-                        }
+                        <?php for ($i=0; $i<count($categories); $i++) { ?>
+                            {{ $categories[$i] }}NumAll: function() {
+                                return this.ticketsByType.{{ $categories[$i] }}.length;
+                            },
+                            {{ $categories[$i] }}NumOpen: function() {
+                                return this.ticketsByType.{{ $categories[$i] }}.filter(_x => _x.is_open).length;
+                            },
+                            {{ $categories[$i] }}NumClosed: function() {
+                                return this.ticketsByType.{{ $categories[$i] }}.filter(_x => !_x.is_open).length;
+                            },
+                            {{ $categories[$i] }}CurrentItemData: function() {
+                                return this.{{ $categories[$i] }}PopupItem.data;
+                            },
+                        <?php } ?>
                     },
                     watch: {
-                        erxCurrentItemData: {
-                            handler: function(val, oldVal) {
-                                if (this.erxPopupMode !== 'edit' || !this.currentItemUid || this.reloading) return;
-                                this.autoSave();
+                        <?php for ($i=0; $i<count($categories); $i++) { ?>
+                            {{ $categories[$i] }}CurrentItemData: { // ex: erxCurrentItemData, labCurrentItemData, etc.
+                                handler: function(val, oldVal) {
+                                    if (this.{{ $categories[$i] }}PopupMode !== 'edit' || !this.currentItemUid || this.reloading) return;
+                                    this.{{ $categories[$i] }}AutoSave();
+                                },
+                                deep: true
                             },
-                            deep: true
-                        }
+                        <?php } ?>
                     },
                     methods: {
 
-                        // erx
-                        showErxPopup: function(_item) {
-                            this.erxPopupMode = _item ? 'edit' : 'add';
-                            this.erxPopupItem = _item ? JSON.parse(JSON.stringify(_item)) : {
-                                uid: '',
-                                is_open: true,
-                                assigned_pro_uid: '',
-                                ordering_pro_uid: '',
-                                data: {
-                                    due_date: '',
-                                    medication: '',
-                                    strength: '',
-                                    amount: '',
-                                    route: '',
-                                    frequency: '',
-                                    dispense: '',
-                                    refills: '',
-                                    purpose: '',
-                                    pharmacyName: '',
-                                    pharmacyCity: '',
-                                    pharmacyState: '',
-                                    pharmacyAddressMemo: '',
-                                    pharmacyPhone: '',
-                                    pharmacyFax: '',
-                                    comments: [],
-                                }
-                            };
-                            this.erxPopupItem.assigned_pro_uid = '';
-                            this.erxPopupItem.ordering_pro_uid = '';
-                            if(!this.erxPopupItem.comments) {
-                                this.erxPopupItem.comments = [];
-                            }
-                            this.comment = '';
-                            showStagPopup('erx-popup', true);
-                            Vue.nextTick(() => {
-                                $('#ticketsApp [pro-suggest-initialized]').removeAttr('pro-suggest-initialized');
-                                initProSuggest();
-                                if (_item) {
-                                    this.currentItemUid = _item.uid;
-                                }
-                            });
-                        },
-                        saveErxPopupItem: function(_autoSave = false) {
-                            let form = $('#ticketsApp form').first();
-
-                            if(!_autoSave) {
-                                if(!form[0].checkValidity()) {
-                                    form[0].reportValidity();
-                                    return false;
-                                }
-                            }
-
-                            if(!_autoSave) showMask();
-                            let payload = {};
-                            if(this.erxPopupMode === 'add') {
-                                payload.clientUid = '{{ $patient->uid }}';
-                                payload.category = 'erx';
-                                payload.assignedProUid = '{{ $pro->uid  }}';
-                                payload.managerProUid = '{{ $pro->uid  }}';
-                                payload.orderingProUid = '{{ $pro->uid  }}';
-                                payload.initiatingProUid = '{{ $pro->uid  }}';
-                                payload.data = JSON.stringify(this.erxPopupItem.data);
-                            }
-                            else {
-                                payload.uid = this.erxPopupItem.uid;
-                                payload.newData = JSON.stringify(this.erxPopupItem.data);
-                            }
-
-                            $.post(
-                                '/api/ticket/' + (this.erxPopupMode === 'add' ? 'create' : 'updateData'),
-                                payload,
-                                (_data) => {
-                                    console.log(_data);
-                                    if(!_autoSave) {
-                                        fastReload();
-                                    }
-                                    else {
-                                        this.reloadPopupItem('erx');
-                                    }
-                                },
-                                'json');
-
-                            return false;
-                        },
-                        saveErxComment: function() {
-                            if(!this.comment) return;
-                            let comment = {
-                                pro_id: this.own_pro_id,
-                                created_at: new Date().toLocaleString(),
-                                message: this.comment
-                            };
-                            if(!this.erxPopupItem.data.comments) {
-                                this.erxPopupItem.data.comments = [];
-                            }
-                            this.erxPopupItem.data.comments.push(comment);
-                            this.autoSave();
-                        },
-
-                        // lab
-
-                        // imaging
-
-                        // equipment
+                        @include('app.patient.tickets.methods', ['category' => 'erx'])
+                        @include('app.patient.tickets.methods', ['category' => 'lab'])
+                        @include('app.patient.tickets.methods', ['category' => 'imaging'])
+                        @include('app.patient.tickets.methods', ['category' => 'equipment'])
 
                         // common
                         reloadPopupItem: function(_type) {
@@ -670,14 +215,14 @@
                             $.post('/api/ticket/close', {
                                 uid: _item.uid
                             }, (_data) => {
-                                this.reloadPopupItem('erx');
+                                this.reloadPopupItem(this.currentCategory);
                             });
                         },
                         openItem: function(_item) {
                             $.post('/api/ticket/open', {
                                 uid: _item.uid
                             }, (_data) => {
-                                this.reloadPopupItem('erx');
+                                this.reloadPopupItem(this.currentCategory);
                             });
                         },
                         initRxAutoSuggest: function() {
@@ -738,7 +283,7 @@
                             $(document).on('pro-changed', '#ticketsApp select[provider-search]', function() {
                                 console.log('ALIX pro-changed', $(this).attr('data-field'), $(this).val());
                                 if(!!$(this).val()) {
-                                    self.erxPopupItem[$(this).attr('data-field')] = $(this).val();
+                                    self[self.currentCategory + 'PopupItem'][$(this).attr('data-field')] = $(this).val();
 
                                     // save
                                     let proType = '';
@@ -752,12 +297,12 @@
                                     }
                                     if (proType) {
                                         $.post('/api/ticket/update' + proType + 'Pro', {
-                                            uid: self.erxPopupItem.uid,
+                                            uid: self[self.currentCategory + 'PopupItem'].uid,
                                             newProUid: $(this).val()
                                         }, function(_data) {
                                             if (!self.hasError(_data)) {
                                                 // toastr.success(proType + ' pro updated');
-                                                self.reloadPopupItem('erx');
+                                                self.reloadPopupItem(self.currentCategory);
                                             }
                                         });
                                     }
@@ -777,7 +322,7 @@
                                 })
                                 .off('changeDate')
                                 .on('changeDate', function() {
-                                    self.erxPopupItem.data.due_date = $(this).val();
+                                    self[self.currentCategory + 'PopupItem'].data.due_date = $(this).val();
                                 });
 
                             $(document).off('focus', '#ticketsApp input.form-control');
@@ -815,7 +360,7 @@
                             ].filter(Boolean).join(', ');
                         },
                         @include('app.patient.tickets.pharmacy-suggest')
-                        @include('app.patient.tickets.ticket_vue_methods',['ticketType'=>'erx'])
+                        @include('app.patient.tickets.ticket_vue_methods')
                     },
                     mounted: function () {
                         this.initRxAutoSuggest();
@@ -823,9 +368,14 @@
                         initFastLoad($('#ticketsApp'));
                         this.initPharmacySearch();
                         this.initDomElementEvents();
-                        this.autoSave = debounce(() => {
-                            this.saveErxPopupItem(true);
-                        }, 1000);
+
+                        <?php for ($i=0; $i<count($categories); $i++) { ?>
+                            {{ $categories[$i] }}AutoSave: null,
+                            this.{{ $categories[$i] }}AutoSave = debounce(() => {
+                                this.{{ $categories[$i] }}SavePopupItem(true);
+                            }, 1000);
+                        <?php } ?>
+
                     }
                 })
             }

+ 41 - 0
resources/views/app/patient/tickets/equipment-data.blade.php

@@ -0,0 +1,41 @@
+// equipment
+equipmentCollapsed: false,
+equipmentPopupMode: 'add',
+equipmentModel: {
+    uid: '',
+    is_open: true,
+    assigned_pro_uid: '',
+    ordering_pro_uid: '',
+    data: {
+        due_date: '',
+        items: [''],
+        purpose: '',
+        memo: '',
+        shipping_status: '',
+        tracking_number: '',
+        comments: [{
+            pro_id: '',
+            message: '',
+            created_at: '',
+        }],
+    }
+},
+equipmentPopupItem: {
+    uid: '',
+    is_open: true,
+    assigned_pro_uid: '',
+    ordering_pro_uid: '',
+    data: {
+        due_date: '',
+        items: [''],
+        purpose: '',
+        memo: '',
+        shipping_status: '',
+        tracking_number: '',
+        comments: [{
+            pro_id: '',
+            message: '',
+            created_at: '',
+        }],
+    }
+},

+ 298 - 0
resources/views/app/patient/tickets/equipment.blade.php

@@ -0,0 +1,298 @@
+<div class="my-4">
+    <div class="d-flex align-items-end mb-3">
+        <h4 class="font-weight-bold m-0 text-secondary font-size-16">Equipment
+            <span v-if="statusFilter === 'open'" class="text-secondary font-weight-normal">(@{{ equipmentNumOpen }} open)</span>
+            <span v-if="statusFilter === 'closed'" class="text-secondary font-weight-normal">(@{{ equipmentNumClosed }} closed)</span>
+            <span v-if="statusFilter === 'all'" class="text-secondary font-weight-normal">(@{{ equipmentNumOpen }} open, @{{ equipmentNumClosed }} closed)</span>
+        </h4>
+        <a class="px-3 c-pointer font-weight-bold"
+           v-on:click.prevent="equipmentShowPopup()">+ New</a>
+        <a class="py-0 font-weight-normal c-pointer flex-grow-1 text-right pr-2"
+           v-if="!equipmentCollapsed"
+           v-on:click.prevent="equipmentCollapsed = true">
+            <i class="text-secondary fa fa-chevron-up"></i>
+        </a>
+        <a class="py-0 font-weight-normal c-pointer flex-grow-1 text-right pr-2"
+           v-if="equipmentCollapsed"
+           v-on:click.prevent="equipmentCollapsed = false">
+            <i class="text-secondary fa fa-chevron-down"></i>
+        </a>
+    </div>
+    <div class="ticket-section" :class="equipmentCollapsed ? 'ticket-section-collapsed' : ''">
+        <table class="table table-sm tickets-table mb-0 border-bottom">
+            <tbody>
+            <tr v-for="(item, index) in ticketsByType.equipment"
+                v-if="(statusFilter === 'all' || (statusFilter === 'open' && item.is_open) || (statusFilter === 'closed' && !item.is_open)) && (item.data.items && Array.isArray(item.data.items) && item.data.items.length)"
+                :class="(item.is_open ? ' ' : 'opacity-60 bg-light ') + (currentItemUid === item.uid ? 'current' : '')">
+                <td class="px-2 py-2 c-pointer" v-on:click.prevent="equipmentShowPopup(item)">
+                    <div class="d-flex align-items-center">
+                        <div class="pro-initials text-uppercase"
+                             :title="allProsFlat['pro_' + item.assigned_pro_id].displayedName"
+                             :style="'background-color: ' + allProsFlat['pro_' + item.assigned_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + item.assigned_pro_id].colors.fc + ';'">
+                            @{{allProsFlat['pro_' + item.assigned_pro_id].displayedInitials}}
+                        </div>
+                        <div class="flex-grow-1 d-inline-flex ml-2 flex-wrap align-items-center">
+                            <span class="font-weight-bold text-dark font-size-13"
+                                  v-html="item.data.items && Array.isArray(item.data.items) ? item.data.items.join(', ') : '-'"></span>
+                            <span class="text-nowrap ml-auto text-sm" v-if="item.data.due_date">
+                                <div title="Due Date" class="pro-initials text-uppercase text-white bg-info"><i class="fa fa-calendar-day"></i></div>
+                                <span class="text-secondary ml-1">@{{ item.data.due_date }}</span>
+                            </span>
+                        </div>
+                    </div>
+                    <!--
+                    <div>
+                        <span class="text-secondary text-sm mt-1">Created:</span>
+                        @{{ item.created_at }}
+                    </div>
+                    -->
+                </td>
+
+            </tr>
+            </tbody>
+        </table>
+    </div>
+    <div class="stag-popup stag-popup-sm stag-slide mcp-theme-1" stag-popup-key="equipment-popup">
+        <form method="POST" action="" class="p-0">
+            <h3 class="stag-popup-title mb-0 p-3 bg-light">
+                <span class="flex-grow-1 text-nowrap overflow-hidden text-ellipsis mr-3">@{{ equipmentPopupMode === 'add' ? 'Add Equipment Ticket' : equipmentPopupItem.data.medication + '  •  ' + equipmentPopupItem.data.strength }}</span>
+                <div v-if="equipmentPopupMode === 'edit'" class="ml-auto mr-3">
+                    <a v-if="equipmentPopupItem.is_open" href="#"
+                       class="btn btn-sm btn-default border bg-white text-dark text-nowrap shadow-none"
+                       v-on:click.prevent="closeItem(equipmentPopupItem)">
+                        <i class="fa fa-check text-success mr-2"></i>Mark Complete
+                    </a>
+                    <a v-if="!equipmentPopupItem.is_open" href="#"
+                       class="btn btn-sm btn-success text-nowrap text-white shadow-none"
+                       v-on:click.prevent="openItem(equipmentPopupItem)">
+                        <i class="fa fa-check mr-2"></i>Complete
+                    </a>
+                </div>
+                <a href="#" class="text-secondary"
+                   onclick="return closeStagPopup()"><i class="fa fa-chevron-right"></i></a>
+            </h3>
+
+            <!-- common - only applicable for edit -->
+            <div class="p-3 border-bottom">
+
+                <div v-if="equipmentPopupMode === 'edit'">
+                    <div class="row mb-2">
+                        <div class="col-3 d-inline-flex align-items-center">
+                            <label class="text-secondary m-0">Assigned Pro</label>
+                        </div>
+                        <div class="col-9">
+                            <div class="d-flex align-items-center">
+                                <div class="pro-initials text-uppercase"
+                                     :title="allProsFlat['pro_' + equipmentPopupItem.assigned_pro_id].displayedName"
+                                     :style="'background-color: ' + allProsFlat['pro_' + equipmentPopupItem.assigned_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + equipmentPopupItem.assigned_pro_id].colors.fc + ';'">
+                                    @{{allProsFlat['pro_' + equipmentPopupItem.assigned_pro_id].displayedInitials}}
+                                </div>
+                                <div class="flex-grow-1 ml-2">
+                                    <select provider-search
+                                            data-field="assigned_pro_uid"
+                                            v-model="equipmentPopupItem.assigned_pro_uid"
+                                            :data-pro-name="[equipmentPopupItem.assigned_pro.name_last, equipmentPopupItem.assigned_pro.name_first].filter(Boolean).join(', ')"
+                                            class="form-control form-control-sm">
+                                        <option value=""> --select--</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="row mb-2">
+                        <div class="col-3 d-inline-flex align-items-center">
+                            <label class="text-secondary m-0">Ordering Pro</label>
+                        </div>
+                        <div class="col-9">
+                            <div class="d-flex align-items-center">
+                                <div class="pro-initials text-uppercase"
+                                     :title="allProsFlat['pro_' + equipmentPopupItem.ordering_pro_id].displayedName"
+                                     :style="'background-color: ' + allProsFlat['pro_' + equipmentPopupItem.ordering_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + equipmentPopupItem.ordering_pro_id].colors.fc + ';'">
+                                    @{{allProsFlat['pro_' + equipmentPopupItem.ordering_pro_id].displayedInitials}}
+                                </div>
+                                <div class="flex-grow-1 ml-2">
+                                    <select provider-search
+                                            data-field="ordering_pro_uid"
+                                            v-model="equipmentPopupItem.ordering_pro_uid"
+                                            :data-pro-name="[equipmentPopupItem.ordering_pro.name_last, equipmentPopupItem.ordering_pro.name_first].filter(Boolean).join(', ')"
+                                            class="form-control form-control-sm">
+                                        <option value=""> --select--</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="row">
+                    <div class="col-3 d-inline-flex align-items-center">
+                        <label class="text-secondary m-0">Due Date</label>
+                    </div>
+                    <div class="col-9">
+                        <div class="d-flex align-items-center">
+                            <div class="pro-initials text-uppercase text-white bg-info"
+                                 title="Due Date">
+                                <i class="fa fa-calendar-day"></i>
+                            </div>
+                            <div class="flex-grow-1 ml-2">
+                                <input type="text" data-field="due_date" placeholder="Due Date"
+                                       v-model="equipmentPopupItem.data.due_date" class="form-control form-control-sm date-input">
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+            </div>
+
+            <div class="p-3 border-bottom">
+
+                <div class="row mb-2">
+                    <div class="col-12">
+                        <label class="text-secondary mb-0 font-weight-normal font-size-16">Equipment</label>
+                    </div>
+                </div>
+                <div class="row mb-2">
+                    <div class="col-9">
+                        <label class="text-sm text-secondary mb-1">Medication</label>
+                        <input type="hidden" v-model="equipmentPopupItem.data.medication">
+                        <input required type="text" data-field="medication" placeholder="Medication"
+                               :value="equipmentPopupItem.data.medication"
+                               class="form-control form-control-sm">
+                    </div>
+                    <div class="col-3 pl-0">
+                        <label class="text-sm text-secondary mb-1">Strength</label>
+                        <input type="hidden" v-model="equipmentPopupItem.data.strength">
+                        <input type="text" data-field="strength" placeholder="Strength"
+                               :value="equipmentPopupItem.data.strength"
+                               class="form-control form-control-sm min-width-unset">
+                    </div>
+                </div>
+                <div class="row mb-2">
+                    <div class="col-3">
+                        <label class="text-sm text-secondary mb-1">Frequency</label>
+                        <input type="text" placeholder="Frequency"
+                               v-model="equipmentPopupItem.data.frequency" class="form-control form-control-sm min-width-unset"
+                               data-option-list="frequency-options">
+                        <div id="frequency-options" class="data-option-list">
+                            <div>Once a day</div>
+                            <div>Twice a day</div>
+                        </div>
+                    </div>
+                    <div class="col-3 pl-0">
+                        <label class="text-sm text-secondary mb-1">Route</label>
+                        <input required type="text" placeholder="Route"
+                               v-model="equipmentPopupItem.data.route" class="form-control form-control-sm min-width-unset"
+                               data-option-list="route-options">
+                        <div id="route-options" class="data-option-list">
+                            <div>PO (by mouth)</div>
+                            <div>PR (per rectum)</div>
+                            <div>IM (intramuscular)</div>
+                            <div>IV (intravenous)</div>
+                            <div>ID (intradermal)</div>
+                            <div>IN (intranasal)</div>
+                            <div>TP (topical)</div>
+                            <div>SL (sublingual)</div>
+                            <div>BUCC (buccal)</div>
+                            <div>IP (intraperitoneal)</div>
+                        </div>
+                    </div>
+                    <div class="col-3 pl-0">
+                        <label class="text-sm text-secondary mb-1">Dispense Amount</label>
+                        <input required type="number" placeholder="Dispense Amount"
+                               v-model="equipmentPopupItem.data.dispense" class="form-control form-control-sm min-width-unset">
+                    </div>
+                    <div class="col-3 pl-0">
+                        <label class="text-sm text-secondary mb-1">Refills</label>
+                        <input type="number" placeholder="Refills"
+                               v-model="equipmentPopupItem.data.refills" class="form-control form-control-sm min-width-unset">
+                    </div>
+                </div>
+                <div class="row">
+                    <div class="col-12">
+                        <label class="text-sm text-secondary mb-1">Purpose</label>
+                        <input required type="text"  placeholder="Purpose"
+                               data-field="icd" v-model="equipmentPopupItem.data.purpose" class="form-control form-control-sm">
+                    </div>
+                </div>
+
+            </div>
+            <div class="p-3 border-bottom">
+                <div class="row mb-2">
+                    <div class="col-12">
+                        <label class="text-secondary mb-0 font-weight-normal font-size-16">Preferred Pharmacy</label>
+                    </div>
+                </div>
+                <div class="row mb-2">
+                    <div class="col-12">
+                        <label class="text-sm text-secondary mb-1">Business Name</label>
+                        <input type="text" autocomplete="donotdoit" placeholder="Business Name" id="pharmacy-search" v-model="equipmentPopupItem.data.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">
+                    <div class="col-4">
+                        <label class="text-sm text-secondary mb-1">City</label>
+                        <input type="text" placeholder="City" v-model="equipmentPopupItem.data.pharmacyCity" class="form-control form-control-sm min-width-unset">
+                    </div>
+                    <div class="col-2 pl-0">
+                        <label class="text-sm text-secondary mb-1">State</label>
+                        <input type="text" placeholder="State" v-model="equipmentPopupItem.data.pharmacyState" class="form-control form-control-sm min-width-unset">
+                    </div>
+                    <div class="col-3 pl-0">
+                        <label class="text-sm text-secondary mb-1">Phone</label>
+                        <input type="text" placeholder="Phone" v-model="equipmentPopupItem.data.pharmacyPhone" class="form-control form-control-sm min-width-unset">
+                    </div>
+                    <div class="col-3 pl-0">
+                        <label class="text-sm text-secondary mb-1">Fax</label>
+                        <input type="text" placeholder="Fax" v-model="equipmentPopupItem.data.pharmacyFax" class="form-control form-control-sm min-width-unset">
+                    </div>
+                </div>
+                <div class="row mb-2">
+                    <div class="col-12">
+                        <label class="text-sm text-secondary mb-1">Address Memo</label>
+                        <input type="text" placeholder="Address Memo" autocomplete="donotdoit" v-model="equipmentPopupItem.data.pharmacyAddressMemo" class="form-control form-control-sm">
+                    </div>
+                </div>
+                <div v-if="equipmentPopupMode === 'add'" class="d-flex align-items-center justify-content-start mt-3">
+                    <button type="button" class="btn btn-sm btn-primary mr-2" v-on:click.prevent="saveequipmentPopupItem()">Submit</button>
+                    <button type="button" class="btn btn-sm btn-default border" onclick="return closeStagPopup()">Cancel</button>
+                </div>
+            </div>
+
+            <!-- comments -->
+            <div v-if="equipmentPopupMode === 'edit' && equipmentPopupItem.data.comments && equipmentPopupItem.data.comments.length" class="px-3 pt-3 pb-0 bg-light">
+                <div class="row mb-3">
+                    <div class="col-12">
+                        <label class="text-secondary mb-0 font-weight-normal font-size-16">Comments (@{{ equipmentPopupItem.data.comments.length }})</label>
+                    </div>
+                </div>
+                <div v-for="(message) in equipmentPopupItem.data.comments" class="d-flex align-items-start pb-3">
+                    <div class="pro-initials text-uppercase mr-2"
+                         :title="allProsFlat['pro_' + message.pro_id].displayedName"
+                         :style="'background-color: ' + allProsFlat['pro_' + message.pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + message.pro_id].colors.fc + ';'">
+                        @{{allProsFlat['pro_' + message.pro_id].displayedInitials}}
+                    </div>
+                    <div class="flex-grow-1">
+                        <div class="">
+                            @{{ allProsFlat['pro_' + message.pro_id].displayedName }}
+                            <span class="text-secondary ml-3">@{{ message.created_at }}</span>
+                        </div>
+                        <div>@{{ message.message }}</div>
+                    </div>
+                </div>
+            </div>
+
+            <div v-if="equipmentPopupMode === 'edit'" class="comment-input-outer p-3 bg-light d-flex align-items-start border-top">
+                <div class="pro-initials text-uppercase mr-2"
+                     :title="allProsFlat['pro_' + own_pro_id].displayedName"
+                     :style="'background-color: ' + allProsFlat['pro_' + own_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + own_pro_id].colors.fc + ';'">
+                    @{{allProsFlat['pro_' + own_pro_id].displayedInitials}}
+                </div>
+                <div class="flex-grow-1 position-relative">
+                    <textarea class="form-control form-control-sm txt-comment shadow-none" v-model="comment"></textarea>
+                    <a href="#" v-on:click.prevent="equipmentSaveComment()" class="btn btn-sm btn-primary text-white btn-save-comment">Comment</a>
+                </div>
+            </div>
+        </form>
+    </div>
+</div>

+ 59 - 0
resources/views/app/patient/tickets/erx-data.blade.php

@@ -0,0 +1,59 @@
+// erx
+erxCollapsed: false,
+erxPopupMode: 'add',
+erxModel: {
+    uid: '',
+    is_open: true,
+    assigned_pro_uid: '',
+    ordering_pro_uid: '',
+    data: {
+        due_date: '',
+        medication: '',
+        strength: '',
+        amount: '',
+        route: '',
+        frequency: '',
+        dispense: '',
+        refills: '',
+        purpose: '',
+        pharmacyName: '',
+        pharmacyCity: '',
+        pharmacyState: '',
+        pharmacyAddressMemo: '',
+        pharmacyPhone: '',
+        pharmacyFax: '',
+        comments: [{
+            pro_id: '',
+            message: '',
+            created_at: '',
+        }],
+    }
+},
+erxPopupItem: {
+    uid: '',
+    is_open: true,
+    assigned_pro_uid: '',
+    ordering_pro_uid: '',
+    data: {
+        due_date: '',
+        medication: '',
+        strength: '',
+        amount: '',
+        route: '',
+        frequency: '',
+        dispense: '',
+        refills: '',
+        purpose: '',
+        pharmacyName: '',
+        pharmacyCity: '',
+        pharmacyState: '',
+        pharmacyAddressMemo: '',
+        pharmacyPhone: '',
+        pharmacyFax: '',
+        comments: [{
+            pro_id: '',
+            message: '',
+            created_at: '',
+        }],
+    }
+},

+ 325 - 0
resources/views/app/patient/tickets/erx.blade.php

@@ -0,0 +1,325 @@
+<div class="my-4">
+    <div class="d-flex align-items-end mb-3">
+        <h4 class="font-weight-bold m-0 text-secondary font-size-16">ERx
+            <span v-if="statusFilter === 'open'" class="text-secondary font-weight-normal">(@{{ erxNumOpen }} open)</span>
+            <span v-if="statusFilter === 'closed'" class="text-secondary font-weight-normal">(@{{ erxNumClosed }} closed)</span>
+            <span v-if="statusFilter === 'all'" class="text-secondary font-weight-normal">(@{{ erxNumOpen }} open, @{{ erxNumClosed }} closed)</span>
+        </h4>
+        <a class="px-3 c-pointer font-weight-bold"
+           v-on:click.prevent="erxShowPopup()">+ New</a>
+        <a class="py-0 font-weight-normal c-pointer flex-grow-1 text-right pr-2"
+           v-if="!erxCollapsed"
+           v-on:click.prevent="erxCollapsed = true">
+            <i class="text-secondary fa fa-chevron-up"></i>
+        </a>
+        <a class="py-0 font-weight-normal c-pointer flex-grow-1 text-right pr-2"
+           v-if="erxCollapsed"
+           v-on:click.prevent="erxCollapsed = false">
+            <i class="text-secondary fa fa-chevron-down"></i>
+        </a>
+    </div>
+    <div class="ticket-section" :class="erxCollapsed ? 'ticket-section-collapsed' : ''">
+        <table class="table table-sm tickets-table mb-0 border-bottom">
+            <tbody>
+            <tr v-for="(item, index) in ticketsByType.erx"
+                v-if="statusFilter === 'all' || (statusFilter === 'open' && item.is_open) || (statusFilter === 'closed' && !item.is_open)"
+                :class="(item.is_open ? ' ' : 'opacity-60 bg-light ') + (currentItemUid === item.uid ? 'current' : '')">
+                <td class="px-2 py-2 c-pointer" v-on:click.prevent="erxShowPopup(item)">
+                    <div class="d-flex align-items-center">
+                        <div class="pro-initials text-uppercase"
+                             :title="allProsFlat['pro_' + item.assigned_pro_id].displayedName"
+                             :style="'background-color: ' + allProsFlat['pro_' + item.assigned_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + item.assigned_pro_id].colors.fc + ';'">
+                            @{{allProsFlat['pro_' + item.assigned_pro_id].displayedInitials}}
+                        </div>
+                        <div class="flex-grow-1 d-inline-flex ml-2 flex-wrap align-items-center">
+                            <span class="font-weight-bold text-dark font-size-13">@{{item.data.medication}}</span>
+                            <span class="d-inline-flex align-items-center" v-if="item.data.strength">
+                                    <span class="mx-2 text-secondary">•</span>
+                                    <span>@{{item.data.strength}}</span>
+                                </span>
+                            <!--                                <span class="d-inline-flex align-items-center" v-if="item.data.route">
+                                                                <span class="mx-2 text-secondary">•</span>
+                                                                <span>@{{item.data.route}}</span>
+                                                            </span>
+                                                            <span class="d-inline-flex align-items-center" v-if="item.data.frequency">
+                                                                <span class="mx-2 text-secondary">•</span>
+                                                                <span>@{{item.data.frequency}}</span>
+                                                            </span>-->
+                            <!--
+                            <span class="d-inline-flex align-items-center" v-if="item.data.dispense">
+                                <span class="mx-2 text-secondary">•</span>
+                                <span>Dispense:</span> @{{item.data.dispense}}
+                                <span class="text-secondary ml-1" v-html="inWords(item.data.dispense)"></span>
+                            </span>
+                            <span class="d-inline-flex align-items-center" v-if="item.data.refills">
+                                <span class="mx-2 text-secondary">•</span>
+                                <span><span>Refills:</span> @{{item.data.refills}}</span>
+                            </span>
+                            <span class="d-inline-flex align-items-center" v-if="item.data.purpose">
+                                <span class="mx-2 text-secondary">•</span>
+                                <span><span>Purpose:</span> @{{item.data.purpose}}</span>
+                            </span>
+                            -->
+                            <span class="text-nowrap ml-4 text-secondary" v-html="pharmacy(item.data)"></span>
+                            <span class="text-nowrap ml-auto text-sm" v-if="item.data.due_date">
+                                    <div title="Due Date" class="pro-initials text-uppercase text-white bg-info"><i class="fa fa-calendar-day"></i></div>
+                                    <span class="text-secondary ml-1">@{{ item.data.due_date }}</span>
+                                </span>
+                        </div>
+                    </div>
+                    <!--
+                    <div>
+                        <span class="text-secondary text-sm mt-1">Created:</span>
+                        @{{ item.created_at }}
+                    </div>
+                    -->
+                </td>
+
+            </tr>
+            </tbody>
+        </table>
+    </div>
+    <div class="stag-popup stag-popup-sm stag-slide mcp-theme-1" stag-popup-key="erx-popup">
+        <form method="POST" action="" class="p-0">
+            <h3 class="stag-popup-title mb-0 p-3 bg-light">
+                <span class="flex-grow-1 text-nowrap overflow-hidden text-ellipsis mr-3">@{{ erxPopupMode === 'add' ? 'Add ERx Ticket' : erxPopupItem.data.medication + '  •  ' + erxPopupItem.data.strength }}</span>
+                <div v-if="erxPopupMode === 'edit'" class="ml-auto mr-3">
+                    <a v-if="erxPopupItem.is_open" href="#"
+                       class="btn btn-sm btn-default border bg-white text-dark text-nowrap shadow-none"
+                       v-on:click.prevent="closeItem(erxPopupItem)">
+                        <i class="fa fa-check text-success mr-2"></i>Mark Complete
+                    </a>
+                    <a v-if="!erxPopupItem.is_open" href="#"
+                       class="btn btn-sm btn-success text-nowrap text-white shadow-none"
+                       v-on:click.prevent="openItem(erxPopupItem)">
+                        <i class="fa fa-check mr-2"></i>Complete
+                    </a>
+                </div>
+                <a href="#" class="text-secondary"
+                   onclick="return closeStagPopup()"><i class="fa fa-chevron-right"></i></a>
+            </h3>
+
+            <!-- common - only applicable for edit -->
+            <div class="p-3 border-bottom">
+
+                <div v-if="erxPopupMode === 'edit'">
+                    <div class="row mb-2">
+                        <div class="col-3 d-inline-flex align-items-center">
+                            <label class="text-secondary m-0">Assigned Pro</label>
+                        </div>
+                        <div class="col-9">
+                            <div class="d-flex align-items-center">
+                                <div class="pro-initials text-uppercase"
+                                     :title="allProsFlat['pro_' + erxPopupItem.assigned_pro_id].displayedName"
+                                     :style="'background-color: ' + allProsFlat['pro_' + erxPopupItem.assigned_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + erxPopupItem.assigned_pro_id].colors.fc + ';'">
+                                    @{{allProsFlat['pro_' + erxPopupItem.assigned_pro_id].displayedInitials}}
+                                </div>
+                                <div class="flex-grow-1 ml-2">
+                                    <select provider-search
+                                            data-field="assigned_pro_uid"
+                                            v-model="erxPopupItem.assigned_pro_uid"
+                                            :data-pro-name="[erxPopupItem.assigned_pro.name_last, erxPopupItem.assigned_pro.name_first].filter(Boolean).join(', ')"
+                                            class="form-control form-control-sm">
+                                        <option value=""> --select--</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="row mb-2">
+                        <div class="col-3 d-inline-flex align-items-center">
+                            <label class="text-secondary m-0">Ordering Pro</label>
+                        </div>
+                        <div class="col-9">
+                            <div class="d-flex align-items-center">
+                                <div class="pro-initials text-uppercase"
+                                     :title="allProsFlat['pro_' + erxPopupItem.ordering_pro_id].displayedName"
+                                     :style="'background-color: ' + allProsFlat['pro_' + erxPopupItem.ordering_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + erxPopupItem.ordering_pro_id].colors.fc + ';'">
+                                    @{{allProsFlat['pro_' + erxPopupItem.ordering_pro_id].displayedInitials}}
+                                </div>
+                                <div class="flex-grow-1 ml-2">
+                                    <select provider-search
+                                            data-field="ordering_pro_uid"
+                                            v-model="erxPopupItem.ordering_pro_uid"
+                                            :data-pro-name="[erxPopupItem.ordering_pro.name_last, erxPopupItem.ordering_pro.name_first].filter(Boolean).join(', ')"
+                                            class="form-control form-control-sm">
+                                        <option value=""> --select--</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="row">
+                    <div class="col-3 d-inline-flex align-items-center">
+                        <label class="text-secondary m-0">Due Date</label>
+                    </div>
+                    <div class="col-9">
+                        <div class="d-flex align-items-center">
+                            <div class="pro-initials text-uppercase text-white bg-info"
+                                 title="Due Date">
+                                <i class="fa fa-calendar-day"></i>
+                            </div>
+                            <div class="flex-grow-1 ml-2">
+                                <input type="text" data-field="due_date" placeholder="Due Date"
+                                       v-model="erxPopupItem.data.due_date" class="form-control form-control-sm date-input">
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+            </div>
+
+            <div class="p-3 border-bottom">
+
+                <div class="row mb-2">
+                    <div class="col-12">
+                        <label class="text-secondary mb-0 font-weight-normal font-size-16">ERx</label>
+                    </div>
+                </div>
+                <div class="row mb-2">
+                    <div class="col-9">
+                        <label class="text-sm text-secondary mb-1">Medication</label>
+                        <input type="hidden" v-model="erxPopupItem.data.medication">
+                        <input required type="text" data-field="medication" placeholder="Medication"
+                               :value="erxPopupItem.data.medication"
+                               class="form-control form-control-sm">
+                    </div>
+                    <div class="col-3 pl-0">
+                        <label class="text-sm text-secondary mb-1">Strength</label>
+                        <input type="hidden" v-model="erxPopupItem.data.strength">
+                        <input type="text" data-field="strength" placeholder="Strength"
+                               :value="erxPopupItem.data.strength"
+                               class="form-control form-control-sm min-width-unset">
+                    </div>
+                </div>
+                <div class="row mb-2">
+                    <div class="col-3">
+                        <label class="text-sm text-secondary mb-1">Frequency</label>
+                        <input type="text" placeholder="Frequency"
+                               v-model="erxPopupItem.data.frequency" class="form-control form-control-sm min-width-unset"
+                               data-option-list="frequency-options">
+                        <div id="frequency-options" class="data-option-list">
+                            <div>Once a day</div>
+                            <div>Twice a day</div>
+                        </div>
+                    </div>
+                    <div class="col-3 pl-0">
+                        <label class="text-sm text-secondary mb-1">Route</label>
+                        <input required type="text" placeholder="Route"
+                               v-model="erxPopupItem.data.route" class="form-control form-control-sm min-width-unset"
+                               data-option-list="route-options">
+                        <div id="route-options" class="data-option-list">
+                            <div>PO (by mouth)</div>
+                            <div>PR (per rectum)</div>
+                            <div>IM (intramuscular)</div>
+                            <div>IV (intravenous)</div>
+                            <div>ID (intradermal)</div>
+                            <div>IN (intranasal)</div>
+                            <div>TP (topical)</div>
+                            <div>SL (sublingual)</div>
+                            <div>BUCC (buccal)</div>
+                            <div>IP (intraperitoneal)</div>
+                        </div>
+                    </div>
+                    <div class="col-3 pl-0">
+                        <label class="text-sm text-secondary mb-1">Dispense Amount</label>
+                        <input required type="number" placeholder="Dispense Amount"
+                               v-model="erxPopupItem.data.dispense" class="form-control form-control-sm min-width-unset">
+                    </div>
+                    <div class="col-3 pl-0">
+                        <label class="text-sm text-secondary mb-1">Refills</label>
+                        <input type="number" placeholder="Refills"
+                               v-model="erxPopupItem.data.refills" class="form-control form-control-sm min-width-unset">
+                    </div>
+                </div>
+                <div class="row">
+                    <div class="col-12">
+                        <label class="text-sm text-secondary mb-1">Purpose</label>
+                        <input required type="text"  placeholder="Purpose"
+                               data-field="icd" v-model="erxPopupItem.data.purpose" class="form-control form-control-sm">
+                    </div>
+                </div>
+
+            </div>
+            <div class="p-3 border-bottom">
+                <div class="row mb-2">
+                    <div class="col-12">
+                        <label class="text-secondary mb-0 font-weight-normal font-size-16">Preferred Pharmacy</label>
+                    </div>
+                </div>
+                <div class="row mb-2">
+                    <div class="col-12">
+                        <label class="text-sm text-secondary mb-1">Business Name</label>
+                        <input type="text" autocomplete="donotdoit" placeholder="Business Name" id="pharmacy-search" v-model="erxPopupItem.data.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">
+                    <div class="col-4">
+                        <label class="text-sm text-secondary mb-1">City</label>
+                        <input type="text" placeholder="City" v-model="erxPopupItem.data.pharmacyCity" class="form-control form-control-sm min-width-unset">
+                    </div>
+                    <div class="col-2 pl-0">
+                        <label class="text-sm text-secondary mb-1">State</label>
+                        <input type="text" placeholder="State" v-model="erxPopupItem.data.pharmacyState" class="form-control form-control-sm min-width-unset">
+                    </div>
+                    <div class="col-3 pl-0">
+                        <label class="text-sm text-secondary mb-1">Phone</label>
+                        <input type="text" placeholder="Phone" v-model="erxPopupItem.data.pharmacyPhone" class="form-control form-control-sm min-width-unset">
+                    </div>
+                    <div class="col-3 pl-0">
+                        <label class="text-sm text-secondary mb-1">Fax</label>
+                        <input type="text" placeholder="Fax" v-model="erxPopupItem.data.pharmacyFax" class="form-control form-control-sm min-width-unset">
+                    </div>
+                </div>
+                <div class="row mb-2">
+                    <div class="col-12">
+                        <label class="text-sm text-secondary mb-1">Address Memo</label>
+                        <input type="text" placeholder="Address Memo" autocomplete="donotdoit" v-model="erxPopupItem.data.pharmacyAddressMemo" class="form-control form-control-sm">
+                    </div>
+                </div>
+                <div v-if="erxPopupMode === 'add'" class="d-flex align-items-center justify-content-start mt-3">
+                    <button type="button" class="btn btn-sm btn-primary mr-2" v-on:click.prevent="saveErxPopupItem()">Submit</button>
+                    <button type="button" class="btn btn-sm btn-default border" onclick="return closeStagPopup()">Cancel</button>
+                </div>
+            </div>
+
+            <!-- comments -->
+            <div v-if="erxPopupMode === 'edit' && erxPopupItem.data.comments && erxPopupItem.data.comments.length" class="px-3 pt-3 pb-0 bg-light">
+                <div class="row mb-3">
+                    <div class="col-12">
+                        <label class="text-secondary mb-0 font-weight-normal font-size-16">Comments (@{{ erxPopupItem.data.comments.length }})</label>
+                    </div>
+                </div>
+                <div v-for="(message) in erxPopupItem.data.comments" class="d-flex align-items-start pb-3">
+                    <div class="pro-initials text-uppercase mr-2"
+                         :title="allProsFlat['pro_' + message.pro_id].displayedName"
+                         :style="'background-color: ' + allProsFlat['pro_' + message.pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + message.pro_id].colors.fc + ';'">
+                        @{{allProsFlat['pro_' + message.pro_id].displayedInitials}}
+                    </div>
+                    <div class="flex-grow-1">
+                        <div class="">
+                            @{{ allProsFlat['pro_' + message.pro_id].displayedName }}
+                            <span class="text-secondary ml-3">@{{ message.created_at }}</span>
+                        </div>
+                        <div>@{{ message.message }}</div>
+                    </div>
+                </div>
+            </div>
+
+            <div v-if="erxPopupMode === 'edit'" class="comment-input-outer p-3 bg-light d-flex align-items-start border-top">
+                <div class="pro-initials text-uppercase mr-2"
+                     :title="allProsFlat['pro_' + own_pro_id].displayedName"
+                     :style="'background-color: ' + allProsFlat['pro_' + own_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + own_pro_id].colors.fc + ';'">
+                    @{{allProsFlat['pro_' + own_pro_id].displayedInitials}}
+                </div>
+                <div class="flex-grow-1 position-relative">
+                    <textarea class="form-control form-control-sm txt-comment shadow-none" v-model="comment"></textarea>
+                    <a href="#" v-on:click.prevent="erxSaveComment()" class="btn btn-sm btn-primary text-white btn-save-comment">Comment</a>
+                </div>
+            </div>
+        </form>
+    </div>
+</div>

+ 37 - 0
resources/views/app/patient/tickets/imaging-data.blade.php

@@ -0,0 +1,37 @@
+// imaging
+imagingCollapsed: false,
+imagingPopupMode: 'add',
+imagingModel: {
+    uid: '',
+    is_open: true,
+    assigned_pro_uid: '',
+    ordering_pro_uid: '',
+    data: {
+        due_date: '',
+        tests: [''],
+        icds: [''],
+        memo: '',
+        comments: [{
+            pro_id: '',
+            message: '',
+            created_at: '',
+        }],
+    }
+},
+imagingPopupItem: {
+    uid: '',
+    is_open: true,
+    assigned_pro_uid: '',
+    ordering_pro_uid: '',
+    data: {
+        due_date: '',
+        tests: [''],
+        icds: [''],
+        memo: '',
+        comments: [{
+            pro_id: '',
+            message: '',
+            created_at: '',
+        }],
+    }
+},

+ 199 - 0
resources/views/app/patient/tickets/imaging.blade.php

@@ -0,0 +1,199 @@
+<div class="my-4">
+    <div class="d-flex align-items-end mb-3">
+        <h4 class="font-weight-bold m-0 text-secondary font-size-16">Imaging
+            <span v-if="statusFilter === 'open'" class="text-secondary font-weight-normal">(@{{ imagingNumOpen }} open)</span>
+            <span v-if="statusFilter === 'closed'" class="text-secondary font-weight-normal">(@{{ imagingNumClosed }} closed)</span>
+            <span v-if="statusFilter === 'all'" class="text-secondary font-weight-normal">(@{{ imagingNumOpen }} open, @{{ imagingNumClosed }} closed)</span>
+        </h4>
+        <a class="px-3 c-pointer font-weight-bold"
+           v-on:click.prevent="imagingShowPopup()">+ New</a>
+        <a class="py-0 font-weight-normal c-pointer flex-grow-1 text-right pr-2"
+           v-if="!imagingCollapsed"
+           v-on:click.prevent="imagingCollapsed = true">
+            <i class="text-secondary fa fa-chevron-up"></i>
+        </a>
+        <a class="py-0 font-weight-normal c-pointer flex-grow-1 text-right pr-2"
+           v-if="imagingCollapsed"
+           v-on:click.prevent="imagingCollapsed = false">
+            <i class="text-secondary fa fa-chevron-down"></i>
+        </a>
+    </div>
+    <div class="ticket-section" :class="imagingCollapsed ? 'ticket-section-collapsed' : ''">
+        <table class="table table-sm tickets-table mb-0 border-bottom">
+            <tbody>
+            <tr v-for="(item, index) in ticketsByType.imaging"
+                v-if="(statusFilter === 'all' || (statusFilter === 'open' && item.is_open) || (statusFilter === 'closed' && !item.is_open)) && (item.data.tests && Array.isArray(item.data.tests) && item.data.tests.length)"
+                :class="(item.is_open ? ' ' : 'opacity-60 bg-light ') + (currentItemUid === item.uid ? 'current' : '')">
+                <td class="px-2 py-2 c-pointer" v-on:click.prevent="imagingShowPopup(item)">
+                    <div class="d-flex align-items-center">
+                        <div class="pro-initials text-uppercase"
+                             :title="allProsFlat['pro_' + item.assigned_pro_id].displayedName"
+                             :style="'background-color: ' + allProsFlat['pro_' + item.assigned_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + item.assigned_pro_id].colors.fc + ';'">
+                            @{{allProsFlat['pro_' + item.assigned_pro_id].displayedInitials}}
+                        </div>
+                        <div class="flex-grow-1 d-inline-flex ml-2 flex-wrap align-items-center">
+                            <span class="font-weight-bold text-dark font-size-13"
+                                  v-html="item.data.tests && Array.isArray(item.data.tests) ? item.data.tests.join(', ') : '-'"></span>
+                            <span class="text-nowrap ml-auto text-sm" v-if="item.data.due_date">
+                                <div title="Due Date" class="pro-initials text-uppercase text-white bg-info"><i class="fa fa-calendar-day"></i></div>
+                                <span class="text-secondary ml-1">@{{ item.data.due_date }}</span>
+                            </span>
+                        </div>
+                    </div>
+                    <!--
+                    <div>
+                        <span class="text-secondary text-sm mt-1">Created:</span>
+                        @{{ item.created_at }}
+                    </div>
+                    -->
+                </td>
+
+            </tr>
+            </tbody>
+        </table>
+    </div>
+    <div class="stag-popup stag-popup-sm stag-slide mcp-theme-1" stag-popup-key="imaging-popup">
+        <form method="POST" action="" class="p-0">
+            <h3 class="stag-popup-title mb-0 p-3 bg-light">
+                <span class="flex-grow-1 text-nowrap overflow-hidden text-ellipsis mr-3">@{{ imagingPopupMode === 'add' ? 'Add Imaging Ticket' : imagingPopupItem.data.medication + '  •  ' + imagingPopupItem.data.strength }}</span>
+                <div v-if="imagingPopupMode === 'edit'" class="ml-auto mr-3">
+                    <a v-if="imagingPopupItem.is_open" href="#"
+                       class="btn btn-sm btn-default border bg-white text-dark text-nowrap shadow-none"
+                       v-on:click.prevent="closeItem(imagingPopupItem)">
+                        <i class="fa fa-check text-success mr-2"></i>Mark Complete
+                    </a>
+                    <a v-if="!imagingPopupItem.is_open" href="#"
+                       class="btn btn-sm btn-success text-nowrap text-white shadow-none"
+                       v-on:click.prevent="openItem(imagingPopupItem)">
+                        <i class="fa fa-check mr-2"></i>Complete
+                    </a>
+                </div>
+                <a href="#" class="text-secondary"
+                   onclick="return closeStagPopup()"><i class="fa fa-chevron-right"></i></a>
+            </h3>
+
+            <!-- common - only applicable for edit -->
+            <div class="p-3 border-bottom">
+
+                <div v-if="imagingPopupMode === 'edit'">
+                    <div class="row mb-2">
+                        <div class="col-3 d-inline-flex align-items-center">
+                            <label class="text-secondary m-0">Assigned Pro</label>
+                        </div>
+                        <div class="col-9">
+                            <div class="d-flex align-items-center">
+                                <div class="pro-initials text-uppercase"
+                                     :title="allProsFlat['pro_' + imagingPopupItem.assigned_pro_id].displayedName"
+                                     :style="'background-color: ' + allProsFlat['pro_' + imagingPopupItem.assigned_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + imagingPopupItem.assigned_pro_id].colors.fc + ';'">
+                                    @{{allProsFlat['pro_' + imagingPopupItem.assigned_pro_id].displayedInitials}}
+                                </div>
+                                <div class="flex-grow-1 ml-2">
+                                    <select provider-search
+                                            data-field="assigned_pro_uid"
+                                            v-model="imagingPopupItem.assigned_pro_uid"
+                                            :data-pro-name="[imagingPopupItem.assigned_pro.name_last, imagingPopupItem.assigned_pro.name_first].filter(Boolean).join(', ')"
+                                            class="form-control form-control-sm">
+                                        <option value=""> --select--</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="row mb-2">
+                        <div class="col-3 d-inline-flex align-items-center">
+                            <label class="text-secondary m-0">Ordering Pro</label>
+                        </div>
+                        <div class="col-9">
+                            <div class="d-flex align-items-center">
+                                <div class="pro-initials text-uppercase"
+                                     :title="allProsFlat['pro_' + imagingPopupItem.ordering_pro_id].displayedName"
+                                     :style="'background-color: ' + allProsFlat['pro_' + imagingPopupItem.ordering_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + imagingPopupItem.ordering_pro_id].colors.fc + ';'">
+                                    @{{allProsFlat['pro_' + imagingPopupItem.ordering_pro_id].displayedInitials}}
+                                </div>
+                                <div class="flex-grow-1 ml-2">
+                                    <select provider-search
+                                            data-field="ordering_pro_uid"
+                                            v-model="imagingPopupItem.ordering_pro_uid"
+                                            :data-pro-name="[imagingPopupItem.ordering_pro.name_last, imagingPopupItem.ordering_pro.name_first].filter(Boolean).join(', ')"
+                                            class="form-control form-control-sm">
+                                        <option value=""> --select--</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="row">
+                    <div class="col-3 d-inline-flex align-items-center">
+                        <label class="text-secondary m-0">Due Date</label>
+                    </div>
+                    <div class="col-9">
+                        <div class="d-flex align-items-center">
+                            <div class="pro-initials text-uppercase text-white bg-info"
+                                 title="Due Date">
+                                <i class="fa fa-calendar-day"></i>
+                            </div>
+                            <div class="flex-grow-1 ml-2">
+                                <input type="text" data-field="due_date" placeholder="Due Date"
+                                       v-model="imagingPopupItem.data.due_date" class="form-control form-control-sm date-input">
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+            </div>
+
+            <div class="p-3 border-bottom">
+
+                <div class="row mb-2">
+                    <div class="col-12">
+                        <label class="text-secondary mb-0 font-weight-normal font-size-16">Imaging</label>
+                    </div>
+                </div>
+                <div class="row mb-2">
+                    TODO
+                </div>
+                <div v-if="imagingPopupMode === 'add'" class="d-flex align-items-center justify-content-start mt-3">
+                    <button type="button" class="btn btn-sm btn-primary mr-2" v-on:click.prevent="saveimagingPopupItem()">Submit</button>
+                    <button type="button" class="btn btn-sm btn-default border" onclick="return closeStagPopup()">Cancel</button>
+                </div>
+            </div>
+
+            <!-- comments -->
+            <div v-if="imagingPopupMode === 'edit' && imagingPopupItem.data.comments && imagingPopupItem.data.comments.length" class="px-3 pt-3 pb-0 bg-light">
+                <div class="row mb-3">
+                    <div class="col-12">
+                        <label class="text-secondary mb-0 font-weight-normal font-size-16">Comments (@{{ imagingPopupItem.data.comments.length }})</label>
+                    </div>
+                </div>
+                <div v-for="(message) in imagingPopupItem.data.comments" class="d-flex align-items-start pb-3">
+                    <div class="pro-initials text-uppercase mr-2"
+                         :title="allProsFlat['pro_' + message.pro_id].displayedName"
+                         :style="'background-color: ' + allProsFlat['pro_' + message.pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + message.pro_id].colors.fc + ';'">
+                        @{{allProsFlat['pro_' + message.pro_id].displayedInitials}}
+                    </div>
+                    <div class="flex-grow-1">
+                        <div class="">
+                            @{{ allProsFlat['pro_' + message.pro_id].displayedName }}
+                            <span class="text-secondary ml-3">@{{ message.created_at }}</span>
+                        </div>
+                        <div>@{{ message.message }}</div>
+                    </div>
+                </div>
+            </div>
+
+            <div v-if="imagingPopupMode === 'edit'" class="comment-input-outer p-3 bg-light d-flex align-items-start border-top">
+                <div class="pro-initials text-uppercase mr-2"
+                     :title="allProsFlat['pro_' + own_pro_id].displayedName"
+                     :style="'background-color: ' + allProsFlat['pro_' + own_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + own_pro_id].colors.fc + ';'">
+                    @{{allProsFlat['pro_' + own_pro_id].displayedInitials}}
+                </div>
+                <div class="flex-grow-1 position-relative">
+                    <textarea class="form-control form-control-sm txt-comment shadow-none" v-model="comment"></textarea>
+                    <a href="#" v-on:click.prevent="imagingSaveComment()" class="btn btn-sm btn-primary text-white btn-save-comment">Comment</a>
+                </div>
+            </div>
+        </form>
+    </div>
+</div>

+ 37 - 0
resources/views/app/patient/tickets/lab-data.blade.php

@@ -0,0 +1,37 @@
+// lab
+labCollapsed: false,
+labPopupMode: 'add',
+labModel: {
+    uid: '',
+    is_open: true,
+    assigned_pro_uid: '',
+    ordering_pro_uid: '',
+    data: {
+        due_date: '',
+        tests: [''],
+        icds: [''],
+        memo: '',
+        comments: [{
+            pro_id: '',
+            message: '',
+            created_at: '',
+        }],
+    }
+},
+labPopupItem: {
+    uid: '',
+    is_open: true,
+    assigned_pro_uid: '',
+    ordering_pro_uid: '',
+    data: {
+        due_date: '',
+        tests: [''],
+        icds: [''],
+        memo: '',
+        comments: [{
+            pro_id: '',
+            message: '',
+            created_at: '',
+        }],
+    }
+},

+ 199 - 0
resources/views/app/patient/tickets/lab.blade.php

@@ -0,0 +1,199 @@
+<div class="my-4">
+    <div class="d-flex align-items-end mb-3">
+        <h4 class="font-weight-bold m-0 text-secondary font-size-16">Lab
+            <span v-if="statusFilter === 'open'" class="text-secondary font-weight-normal">(@{{ labNumOpen }} open)</span>
+            <span v-if="statusFilter === 'closed'" class="text-secondary font-weight-normal">(@{{ labNumClosed }} closed)</span>
+            <span v-if="statusFilter === 'all'" class="text-secondary font-weight-normal">(@{{ labNumOpen }} open, @{{ labNumClosed }} closed)</span>
+        </h4>
+        <a class="px-3 c-pointer font-weight-bold"
+           v-on:click.prevent="labShowPopup()">+ New</a>
+        <a class="py-0 font-weight-normal c-pointer flex-grow-1 text-right pr-2"
+           v-if="!labCollapsed"
+           v-on:click.prevent="labCollapsed = true">
+            <i class="text-secondary fa fa-chevron-up"></i>
+        </a>
+        <a class="py-0 font-weight-normal c-pointer flex-grow-1 text-right pr-2"
+           v-if="labCollapsed"
+           v-on:click.prevent="labCollapsed = false">
+            <i class="text-secondary fa fa-chevron-down"></i>
+        </a>
+    </div>
+    <div class="ticket-section" :class="labCollapsed ? 'ticket-section-collapsed' : ''">
+        <table class="table table-sm tickets-table mb-0 border-bottom">
+            <tbody>
+            <tr v-for="(item, index) in ticketsByType.lab"
+                v-if="(statusFilter === 'all' || (statusFilter === 'open' && item.is_open) || (statusFilter === 'closed' && !item.is_open)) && (item.data.tests && Array.isArray(item.data.tests) && item.data.tests.length)"
+                :class="(item.is_open ? ' ' : 'opacity-60 bg-light ') + (currentItemUid === item.uid ? 'current' : '')">
+                <td class="px-2 py-2 c-pointer" v-on:click.prevent="labShowPopup(item)">
+                    <div class="d-flex align-items-center">
+                        <div class="pro-initials text-uppercase"
+                             :title="allProsFlat['pro_' + item.assigned_pro_id].displayedName"
+                             :style="'background-color: ' + allProsFlat['pro_' + item.assigned_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + item.assigned_pro_id].colors.fc + ';'">
+                            @{{allProsFlat['pro_' + item.assigned_pro_id].displayedInitials}}
+                        </div>
+                        <div class="flex-grow-1 d-inline-flex ml-2 flex-wrap align-items-center">
+                            <span class="font-weight-bold text-dark font-size-13"
+                                  v-html="item.data.tests && Array.isArray(item.data.tests) ? item.data.tests.join(', ') : '-'"></span>
+                            <span class="text-nowrap ml-auto text-sm" v-if="item.data.due_date">
+                                <div title="Due Date" class="pro-initials text-uppercase text-white bg-info"><i class="fa fa-calendar-day"></i></div>
+                                <span class="text-secondary ml-1">@{{ item.data.due_date }}</span>
+                            </span>
+                        </div>
+                    </div>
+                    <!--
+                    <div>
+                        <span class="text-secondary text-sm mt-1">Created:</span>
+                        @{{ item.created_at }}
+                    </div>
+                    -->
+                </td>
+
+            </tr>
+            </tbody>
+        </table>
+    </div>
+    <div class="stag-popup stag-popup-sm stag-slide mcp-theme-1" stag-popup-key="lab-popup">
+        <form method="POST" action="" class="p-0">
+            <h3 class="stag-popup-title mb-0 p-3 bg-light">
+                <span class="flex-grow-1 text-nowrap overflow-hidden text-ellipsis mr-3">@{{ labPopupMode === 'add' ? 'Add Lab Ticket' : labPopupItem.data.medication + '  •  ' + labPopupItem.data.strength }}</span>
+                <div v-if="labPopupMode === 'edit'" class="ml-auto mr-3">
+                    <a v-if="labPopupItem.is_open" href="#"
+                       class="btn btn-sm btn-default border bg-white text-dark text-nowrap shadow-none"
+                       v-on:click.prevent="closeItem(labPopupItem)">
+                        <i class="fa fa-check text-success mr-2"></i>Mark Complete
+                    </a>
+                    <a v-if="!labPopupItem.is_open" href="#"
+                       class="btn btn-sm btn-success text-nowrap text-white shadow-none"
+                       v-on:click.prevent="openItem(labPopupItem)">
+                        <i class="fa fa-check mr-2"></i>Complete
+                    </a>
+                </div>
+                <a href="#" class="text-secondary"
+                   onclick="return closeStagPopup()"><i class="fa fa-chevron-right"></i></a>
+            </h3>
+
+            <!-- common - only applicable for edit -->
+            <div class="p-3 border-bottom">
+
+                <div v-if="labPopupMode === 'edit'">
+                    <div class="row mb-2">
+                        <div class="col-3 d-inline-flex align-items-center">
+                            <label class="text-secondary m-0">Assigned Pro</label>
+                        </div>
+                        <div class="col-9">
+                            <div class="d-flex align-items-center">
+                                <div class="pro-initials text-uppercase"
+                                     :title="allProsFlat['pro_' + labPopupItem.assigned_pro_id].displayedName"
+                                     :style="'background-color: ' + allProsFlat['pro_' + labPopupItem.assigned_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + labPopupItem.assigned_pro_id].colors.fc + ';'">
+                                    @{{allProsFlat['pro_' + labPopupItem.assigned_pro_id].displayedInitials}}
+                                </div>
+                                <div class="flex-grow-1 ml-2">
+                                    <select provider-search
+                                            data-field="assigned_pro_uid"
+                                            v-model="labPopupItem.assigned_pro_uid"
+                                            :data-pro-name="[labPopupItem.assigned_pro.name_last, labPopupItem.assigned_pro.name_first].filter(Boolean).join(', ')"
+                                            class="form-control form-control-sm">
+                                        <option value=""> --select--</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="row mb-2">
+                        <div class="col-3 d-inline-flex align-items-center">
+                            <label class="text-secondary m-0">Ordering Pro</label>
+                        </div>
+                        <div class="col-9">
+                            <div class="d-flex align-items-center">
+                                <div class="pro-initials text-uppercase"
+                                     :title="allProsFlat['pro_' + labPopupItem.ordering_pro_id].displayedName"
+                                     :style="'background-color: ' + allProsFlat['pro_' + labPopupItem.ordering_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + labPopupItem.ordering_pro_id].colors.fc + ';'">
+                                    @{{allProsFlat['pro_' + labPopupItem.ordering_pro_id].displayedInitials}}
+                                </div>
+                                <div class="flex-grow-1 ml-2">
+                                    <select provider-search
+                                            data-field="ordering_pro_uid"
+                                            v-model="labPopupItem.ordering_pro_uid"
+                                            :data-pro-name="[labPopupItem.ordering_pro.name_last, labPopupItem.ordering_pro.name_first].filter(Boolean).join(', ')"
+                                            class="form-control form-control-sm">
+                                        <option value=""> --select--</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="row">
+                    <div class="col-3 d-inline-flex align-items-center">
+                        <label class="text-secondary m-0">Due Date</label>
+                    </div>
+                    <div class="col-9">
+                        <div class="d-flex align-items-center">
+                            <div class="pro-initials text-uppercase text-white bg-info"
+                                 title="Due Date">
+                                <i class="fa fa-calendar-day"></i>
+                            </div>
+                            <div class="flex-grow-1 ml-2">
+                                <input type="text" data-field="due_date" placeholder="Due Date"
+                                       v-model="labPopupItem.data.due_date" class="form-control form-control-sm date-input">
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+            </div>
+
+            <div class="p-3 border-bottom">
+
+                <div class="row mb-2">
+                    <div class="col-12">
+                        <label class="text-secondary mb-0 font-weight-normal font-size-16">Lab</label>
+                    </div>
+                </div>
+                <div class="row mb-2">
+                    TODO
+                </div>
+                <div v-if="labPopupMode === 'add'" class="d-flex align-items-center justify-content-start mt-3">
+                    <button type="button" class="btn btn-sm btn-primary mr-2" v-on:click.prevent="labSavePopupItem()">Submit</button>
+                    <button type="button" class="btn btn-sm btn-default border" onclick="return closeStagPopup()">Cancel</button>
+                </div>
+            </div>
+
+            <!-- comments -->
+            <div v-if="labPopupMode === 'edit' && labPopupItem.data.comments && labPopupItem.data.comments.length" class="px-3 pt-3 pb-0 bg-light">
+                <div class="row mb-3">
+                    <div class="col-12">
+                        <label class="text-secondary mb-0 font-weight-normal font-size-16">Comments (@{{ labPopupItem.data.comments.length }})</label>
+                    </div>
+                </div>
+                <div v-for="(message) in labPopupItem.data.comments" class="d-flex align-items-start pb-3">
+                    <div class="pro-initials text-uppercase mr-2"
+                         :title="allProsFlat['pro_' + message.pro_id].displayedName"
+                         :style="'background-color: ' + allProsFlat['pro_' + message.pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + message.pro_id].colors.fc + ';'">
+                        @{{allProsFlat['pro_' + message.pro_id].displayedInitials}}
+                    </div>
+                    <div class="flex-grow-1">
+                        <div class="">
+                            @{{ allProsFlat['pro_' + message.pro_id].displayedName }}
+                            <span class="text-secondary ml-3">@{{ message.created_at }}</span>
+                        </div>
+                        <div>@{{ message.message }}</div>
+                    </div>
+                </div>
+            </div>
+
+            <div v-if="labPopupMode === 'edit'" class="comment-input-outer p-3 bg-light d-flex align-items-start border-top">
+                <div class="pro-initials text-uppercase mr-2"
+                     :title="allProsFlat['pro_' + own_pro_id].displayedName"
+                     :style="'background-color: ' + allProsFlat['pro_' + own_pro_id].colors.bc + '; color: ' + allProsFlat['pro_' + own_pro_id].colors.fc + ';'">
+                    @{{allProsFlat['pro_' + own_pro_id].displayedInitials}}
+                </div>
+                <div class="flex-grow-1 position-relative">
+                    <textarea class="form-control form-control-sm txt-comment shadow-none" v-model="comment"></textarea>
+                    <a href="#" v-on:click.prevent="labSaveComment()" class="btn btn-sm btn-primary text-white btn-save-comment">Comment</a>
+                </div>
+            </div>
+        </form>
+    </div>
+</div>

+ 68 - 0
resources/views/app/patient/tickets/methods.blade.php

@@ -0,0 +1,68 @@
+{{ $category }}ShowPopup: function(_item) {
+    this.{{ $category }}PopupMode = _item ? 'edit' : 'add';
+    this.{{ $category }}PopupItem = _item ? JSON.parse(JSON.stringify(_item)) : JSON.parse(JSON.stringify(this.{{ $category }}Model));
+    this.{{ $category }}PopupItem.assigned_pro_uid = '';
+    this.{{ $category }}PopupItem.ordering_pro_uid = '';
+    if(!this.{{ $category }}PopupItem.comments) this.{{ $category }}PopupItem.comments = [];
+    this.comment = '';
+    showStagPopup('{{ $category }}-popup', true);
+    Vue.nextTick(() => {
+        $('#ticketsApp [pro-suggest-initialized]').removeAttr('pro-suggest-initialized');
+        initProSuggest();
+        if (_item) {
+            this.currentCategory = '{{ $category }}';
+            this.currentItemUid = _item.uid;
+        }
+    });
+},
+{{ $category }}SavePopupItem: function(_autoSave = false) {
+    let form = $('#ticketsApp form').first();
+    if(!_autoSave) {
+        if(!form[0].checkValidity()) {
+            form[0].reportValidity();
+            return false;
+        }
+    }
+    if(!_autoSave) showMask();
+    let payload = {};
+    if(this.{{ $category }}PopupMode === 'add') {
+        payload.clientUid = '{{ $patient->uid }}';
+        payload.category = '{{ $category }}';
+        payload.assignedProUid = '{{ $pro->uid  }}';
+        payload.managerProUid = '{{ $pro->uid  }}';
+        payload.orderingProUid = '{{ $pro->uid  }}';
+        payload.initiatingProUid = '{{ $pro->uid  }}';
+        payload.data = JSON.stringify(this.{{ $category }}PopupItem.data);
+    }
+    else {
+        payload.uid = this.{{ $category }}PopupItem.uid;
+        payload.newData = JSON.stringify(this.{{ $category }}PopupItem.data);
+    }
+    $.post(
+        '/api/ticket/' + (this.{{ $category }}PopupMode === 'add' ? 'create' : 'updateData'),
+        payload,
+        (_data) => {
+            console.log(_data);
+            if(!_autoSave) {
+                fastReload();
+            }
+            else {
+                this.reloadPopupItem('{{ $category }}');
+            }
+        },
+        'json');
+    return false;
+},
+{{ $category }}SaveComment: function() {
+    if(!this.comment) return;
+    let comment = {
+        pro_id: this.own_pro_id,
+        created_at: new Date().toLocaleString(),
+        message: this.comment
+    };
+    if(!this.{{ $category }}PopupItem.data.comments) {
+        this.{{ $category }}PopupItem.data.comments = [];
+    }
+    this.{{ $category }}PopupItem.data.comments.push(comment);
+    this.{{ $category }}AutoSave();
+},

+ 0 - 36
resources/views/app/patient/tickets/ticket_vue_methods.blade.php

@@ -1,40 +1,4 @@
 
-showProUpdatePopup: function(_name, _proToUpdate, _item) {
-    closeStagPopup();
-    this.proToUpdate = _proToUpdate
-    this.popupItem =JSON.parse(JSON.stringify(_item))
-    let self = this;
-    Vue.nextTick(function() {
-        showStagPopup('{{$ticketType}}-pro-update-popup', true);
-    });
-},
-
-updateTicketPro: function() {
-    let self  = this;
-    let form = $('#{{$ticketType}}App form').first();
-    if(!form[0].checkValidity()) {
-        form[0].reportValidity();
-        return false;
-    }
-
-    showMask();
-    let payload = this.popupItem;
-    payload.newProUid = self.newProUid;
-
-    $.post(
-        '/api/ticket/update' + self.proToUpdate +'Pro',
-        payload,
-        function(_data) {
-            console.log(_data);
-            fastReload();
-        },
-        'json');
-
-    return false;
-},
-
-
-
 setIsEntryErrorToTrue: function(_item){
     showMask();
     $.post('/api/ticket/setIsEntryErrorToTrue', {