Преглед на файлове

Appointment calendar updates

Vijayakrishnan преди 4 години
родител
ревизия
c00ec27b3d

+ 1 - 1
app/Helpers/helpers.php

@@ -47,7 +47,7 @@ if(!function_exists('friendly_time')) {
         if(!$value || empty($value)) return $default;
         try {
             $result = strtotime($value);
-            $result = date("h:ia", $result);
+            $result = date("h:i a", $result);
             return $result;
         }
         catch (Exception $e) {

+ 7 - 1
public/css/style.css

@@ -714,10 +714,13 @@ body .node input[type="number"] {
 }
 .slot-picker td {
     text-align: center;
-    border: 1px solid #ddd;
+    border: 1px solid #ddd !important;
     padding: 2px 5px;
     cursor: pointer;
 }
+.slot-picker th {
+    border: 0 !important;
+}
 .slot-picker td:hover {
     background: aliceblue;
 }
@@ -742,3 +745,6 @@ body .node input[type="number"] {
 .pro-appointment-calendar .datepicker td {
     height: 25px;
 }
+.datepicker td, .datepicker th {
+    border: none !important;
+}

+ 140 - 0
resources/views/app/patient/partials/_appointment-form.blade.php

@@ -0,0 +1,140 @@
+<form url="/api/appointment/{{ $appointment ? 'update' : 'create' }}"
+      class="mcp-theme-1 add-appt-form"
+      {{ $appointment ? 'trigger-reload' : '' }}>
+    @if($appointment)
+        <input type="hidden" name="uid" value="{{$appointment->uid}}">
+    @else
+        <input type="hidden" name="clientUid" value="{{$patient->uid}}">
+    @endif
+    <div class="row mb-3">
+        <div class="col-6 pr-2">
+            <label class="text-secondary text-sm mb-1">Pro *</label>
+            <select name="proUid" class="form-control form-control-sm appointment-pro-select"
+                    required>
+                <option value=""> --select-- </option>
+                @foreach($pros as $iPro)
+                    <option value="{{$iPro->uid}}"
+                        {{ ($appointment ? ($iPro->uid === $appointment->pro->uid) : ($iPro->uid === $pro->uid)) ? 'selected' : '' }}>
+                        {{$iPro->displayName()}}
+                    </option>
+                @endforeach
+            </select>
+        </div>
+        <div class="col-6 pl-0">
+            <label class="text-secondary text-sm mb-1">Timezone *</label>
+            <select name="timeZone" class="form-control form-control-sm" {{ $appointment ? ' data-trigger="change"' : '' }} required>
+                <option value=""> --select-- </option>
+                <option {{ $appointment && $appointment->timezone === 'EASTERN' ? 'selected' : '' }}
+                        value="EASTERN">Eastern</option>
+                <option {{ $appointment && $appointment->timezone === 'CENTRAL' ? 'selected' : '' }}
+                        value="CENTRAL">Central</option>
+                <option {{ $appointment && $appointment->timezone === 'MOUNTAIN' ? 'selected' : '' }}
+                        value="MOUNTAIN">Mountain</option>
+                <option {{ $appointment && $appointment->timezone === 'PACIFIC' ? 'selected' : '' }}
+                        value="PACIFIC">Pacific</option>
+                <option {{ $appointment && $appointment->timezone === 'ALASKA' ? 'selected' : '' }}
+                        value="ALASKA">Alaska</option>
+                <option {{ $appointment && $appointment->timezone === 'HAWAII' ? 'selected' : '' }}
+                        value="HAWAII">Hawaii</option>
+                <option {{ $appointment && $appointment->timezone === 'PUERTO_RICO' ? 'selected' : '' }}
+                        value="PUERTO_RICO">Puerto Rico</option>
+            </select>
+        </div>
+    </div>
+    <input type="hidden" name="date" min="{{ date('Y-m-d') }}"
+           value="{{ $appointment ? date("Y-m-d", strtotime($appointment->raw_date)) : '' }}">
+    <input type="hidden" name="startTime" class="form-control form-control-sm"
+           value="{{ $appointment ? date("H:i", strtotime($appointment->raw_start_time)) : '' }}">
+    <input type="hidden" name="endTime" class="form-control form-control-sm"
+           value="{{ $appointment ? date("H:i", strtotime($appointment->raw_end_time)) : '' }}">
+    <div class="mb-2 d-flex align-items-start">
+        <div class="pro-appointment-calendar disabled flex-grow-0 d-inline-flex justify-content-center"></div>
+        <div class="pro-appointment-time-selector pl-2 flex-grow-1 border-left">
+            <div class="slot-picker start-time disabled mb-2">
+                <table class="table-condensed w-100">
+                    <thead>
+                    <tr>
+                        <th class="prev"></th>
+                        <th colspan="4" class="datepicker-switch text-center selected-date pb-1">Start Time</th>
+                        <th class="next"></th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    <tr>
+                        <td class="slot" data-start="540" data-end="570">9:00</td>
+                        <td class="slot" data-start="570" data-end="600">9:30</td>
+                        <td class="slot" data-start="600" data-end="630">10:00</td>
+                        <td class="slot" data-start="630" data-end="660">10:30</td>
+                        <td class="slot" data-start="660" data-end="690">11:00</td>
+                        <td class="slot" data-start="690" data-end="720">11:30</td>
+                    </tr>
+                    <tr>
+                        <td class="slot" data-start="720" data-end="750">12:00</td>
+                        <td class="slot" data-start="750" data-end="780">12:30</td>
+                        <td class="slot" data-start="780" data-end="810">13:00</td>
+                        <td class="slot" data-start="810" data-end="840">13:30</td>
+                        <td class="slot" data-start="840" data-end="870">14:00</td>
+                        <td class="slot" data-start="870" data-end="900">14:30</td>
+                    </tr>
+                    <tr>
+                        <td class="slot" data-start="900" data-end="930">15:00</td>
+                        <td class="slot" data-start="930" data-end="960">15:30</td>
+                        <td class="slot" data-start="960" data-end="990">16:00</td>
+                        <td class="slot" data-start="990" data-end="1020">16:30</td>
+                        <td class="slot" data-start="1020" data-end="1050">17:00</td>
+                        <td class="slot" data-start="1050" data-end="1080">17:30</td>
+                    </tr>
+                </table>
+            </div>
+
+            <div class="slot-picker end-time disabled pt-0">
+                <table class="table-condensed w-100">
+                    <thead>
+                    <tr>
+                        <th class="prev"></th>
+                        <th colspan="4" class="datepicker-switch text-center selected-date pb-1">End Time</th>
+                        <th class="next"></th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    <tr>
+                        <td class="slot" data-start="540" data-end="570">9:30</td>
+                        <td class="slot" data-start="570" data-end="600">10:00</td>
+                        <td class="slot" data-start="600" data-end="630">10:30</td>
+                        <td class="slot" data-start="630" data-end="660">11:00</td>
+                        <td class="slot" data-start="660" data-end="690">11:30</td>
+                        <td class="slot" data-start="690" data-end="720">12:00</td>
+                    </tr>
+                    <tr>
+                        <td class="slot" data-start="720" data-end="750">12:30</td>
+                        <td class="slot" data-start="750" data-end="780">13:00</td>
+                        <td class="slot" data-start="780" data-end="810">13:30</td>
+                        <td class="slot" data-start="810" data-end="840">14:00</td>
+                        <td class="slot" data-start="840" data-end="870">14:30</td>
+                        <td class="slot" data-start="870" data-end="900">15:00</td>
+                    </tr>
+                    <tr>
+                        <td class="slot" data-start="900" data-end="930">15:30</td>
+                        <td class="slot" data-start="930" data-end="960">16:00</td>
+                        <td class="slot" data-start="960" data-end="990">16:30</td>
+                        <td class="slot" data-start="990" data-end="1020">17:00</td>
+                        <td class="slot" data-start="1020" data-end="1050">17:30</td>
+                        <td class="slot" data-start="1050" data-end="1080">18:00</td>
+                    </tr>
+                </table>
+            </div>
+        </div>
+    </div>
+    <div class="mb-2">
+        <label class="text-secondary text-sm mb-1">Title</label>
+        <input type="text" name="title" class="form-control form-control-sm" value="{{ $appointment ? $appointment->title : '' }}">
+    </div>
+    <div class="mb-2">
+        <label class="text-secondary text-sm mb-1">Description</label>
+        <textarea name="description" class="form-control form-control-sm">{{ $appointment ? $appointment->description : '' }}</textarea>
+    </div>
+    <div>
+        <button submit class="btn btn-sm btn-primary mr-1">Submit</button>
+        <button cancel class="btn btn-sm btn-default border">Cancel</button>
+    </div>
+</form>

+ 58 - 204
resources/views/app/patient/partials/appointments.blade.php

@@ -4,128 +4,7 @@
         <span class="mx-2 text-secondary">|</span>
         <div moe center>
             <a start show>Add</a>
-            <form url="/api/appointment/create" class="mcp-theme-1 add-appt-form">
-                <input type="hidden" name="clientUid" value="{{$patient->uid}}">
-                <div class="row mb-3">
-                    <div class="col-6 pr-2">
-                        <label class="text-secondary text-sm mb-1">Pro *</label>
-                        <select name="proUid" class="form-control form-control-sm appointment-pro-select"
-                                required>
-                            <option value=""> --select-- </option>
-                            @foreach($pros as $iPro)
-                                <option
-                                    value="{{$iPro->uid}}" {{ $iPro->uid === $pro->uid ? 'selected' : '' }}>{{$iPro->displayName()}}</option>
-                            @endforeach
-                        </select>
-                    </div>
-                    <div class="col-6 pl-0">
-                        <label class="text-secondary text-sm mb-1">Timezone *</label>
-                        <select name="timeZone" class="form-control form-control-sm" required>
-                            <option value=""> --select-- </option>
-                            <option value="EASTERN">Eastern</option>
-                            <option value="CENTRAL">Central</option>
-                            <option value="MOUNTAIN">Mountain</option>
-                            <option value="PACIFIC">Pacific</option>
-                            <option value="ALASKA">Alaska</option>
-                            <option value="HAWAII">Hawaii</option>
-                            <option value="PUERTO_RICO">Puerto Rico</option>
-                        </select>
-                    </div>
-                </div>
-                <input type="hidden" name="date" min="{{ date('Y-m-d') }}" value="{{ date('Y-m-d') }}">
-                <input type="hidden" name="startTime" class="form-control form-control-sm">
-                <input type="hidden" name="endTime" class="form-control form-control-sm">
-                <div class="mb-2 d-flex align-items-start">
-                    <div class="pro-appointment-calendar disabled flex-grow-0 d-inline-flex justify-content-center"></div>
-                    <div class="pro-appointment-time-selector pl-2 flex-grow-1 border-left">
-                        <div class="slot-picker start-time disabled mb-2">
-                            <table class="table-condensed w-100">
-                                <thead>
-                                <tr>
-                                    <th class="prev"></th>
-                                    <th colspan="4" class="datepicker-switch text-center selected-date pb-1">Start Time</th>
-                                    <th class="next"></th>
-                                </tr>
-                                </thead>
-                                <tbody>
-                                <tr>
-                                    <td class="slot" data-start="540" data-end="570">9:00</td>
-                                    <td class="slot" data-start="570" data-end="600">9:30</td>
-                                    <td class="slot" data-start="600" data-end="630">10:00</td>
-                                    <td class="slot" data-start="630" data-end="660">10:30</td>
-                                    <td class="slot" data-start="660" data-end="690">11:00</td>
-                                    <td class="slot" data-start="690" data-end="720">11:30</td>
-                                </tr>
-                                <tr>
-                                    <td class="slot" data-start="720" data-end="750">12:00</td>
-                                    <td class="slot" data-start="750" data-end="780">12:30</td>
-                                    <td class="slot" data-start="780" data-end="810">13:00</td>
-                                    <td class="slot" data-start="810" data-end="840">13:30</td>
-                                    <td class="slot" data-start="840" data-end="870">14:00</td>
-                                    <td class="slot" data-start="870" data-end="900">14:30</td>
-                                </tr>
-                                <tr>
-                                    <td class="slot" data-start="900" data-end="930">15:00</td>
-                                    <td class="slot" data-start="930" data-end="960">15:30</td>
-                                    <td class="slot" data-start="960" data-end="990">16:00</td>
-                                    <td class="slot" data-start="990" data-end="1020">16:30</td>
-                                    <td class="slot" data-start="1020" data-end="1050">17:00</td>
-                                    <td class="slot" data-start="1050" data-end="1080">17:30</td>
-                                </tr>
-                            </table>
-                        </div>
-
-                        <div class="slot-picker end-time disabled">
-                            <table class="table-condensed w-100">
-                                <thead>
-                                <tr>
-                                    <th class="prev"></th>
-                                    <th colspan="4" class="datepicker-switch text-center selected-date pb-1">End Time</th>
-                                    <th class="next"></th>
-                                </tr>
-                                </thead>
-                                <tbody>
-                                <tr>
-                                    <td class="slot" data-start="540" data-end="570">9:30</td>
-                                    <td class="slot" data-start="570" data-end="600">10:00</td>
-                                    <td class="slot" data-start="600" data-end="630">10:30</td>
-                                    <td class="slot" data-start="630" data-end="660">11:00</td>
-                                    <td class="slot" data-start="660" data-end="690">11:30</td>
-                                    <td class="slot" data-start="690" data-end="720">12:00</td>
-                                </tr>
-                                <tr>
-                                    <td class="slot" data-start="720" data-end="750">12:30</td>
-                                    <td class="slot" data-start="750" data-end="780">13:00</td>
-                                    <td class="slot" data-start="780" data-end="810">13:30</td>
-                                    <td class="slot" data-start="810" data-end="840">14:00</td>
-                                    <td class="slot" data-start="840" data-end="870">14:30</td>
-                                    <td class="slot" data-start="870" data-end="900">15:00</td>
-                                </tr>
-                                <tr>
-                                    <td class="slot" data-start="900" data-end="930">15:30</td>
-                                    <td class="slot" data-start="930" data-end="960">16:00</td>
-                                    <td class="slot" data-start="960" data-end="990">16:30</td>
-                                    <td class="slot" data-start="990" data-end="1020">17:00</td>
-                                    <td class="slot" data-start="1020" data-end="1050">17:30</td>
-                                    <td class="slot" data-start="1050" data-end="1080">18:00</td>
-                                </tr>
-                            </table>
-                        </div>
-                    </div>
-                </div>
-                <div class="mb-2">
-                    <label class="text-secondary text-sm mb-1">Title</label>
-                    <input type="text" name="title" class="form-control form-control-sm">
-                </div>
-                <div class="mb-2">
-                    <label class="text-secondary text-sm mb-1">Description</label>
-                    <textarea name="description" class="form-control form-control-sm"></textarea>
-                </div>
-                <div>
-                    <button submit class="btn btn-sm btn-primary mr-1">Submit</button>
-                    <button cancel class="btn btn-sm btn-default border">Cancel</button>
-                </div>
-            </form>
+            @include('app/patient/partials/_appointment-form', ['appointment' => false])
         </div>
     </div>
     <table class="table table-sm border-0 my-0 mx-2">
@@ -134,81 +13,15 @@
             <tr>
                 <td class="text-black p-0 border-0">
                     <div class="pb-0">
-                        <div relative moe>
+                        <div relative moe center>
                             <a class="on-hover-opaque" start show title="Update">
                                 <i class="font-size-11 fa fa-edit text-primary"></i>
                             </a>
-                            <form url="/api/appointment/update">
-                                <input type="hidden" name="uid" value="{{ $appointment->uid }}">
-                                <div class="mb-2">
-                                    <label class="text-secondary text-sm">Pro</label>
-                                    <select name="proUid" class="form-control form-control-sm">
-                                        <option value=""> --select-- </option>
-                                        @foreach($pros as $iPro)
-                                            <option
-                                                <?= $appointment->pro->uid === $iPro->uid ? 'selected' : '' ?>
-                                                value="{{$iPro->uid}}">{{$iPro->displayName()}}</option>
-                                        @endforeach
-                                    </select>
-                                </div>
-                                <div class="mb-2">
-                                    <label class="text-secondary text-sm">Date</label>
-                                    <input autofocus type="date" name="date" min="{{ date('Y-m-d') }}"
-                                           value="{{ date("Y-m-d", strtotime($appointment->raw_date)) }}"
-                                           class="form-control form-control-sm">
-                                </div>
-                                <div class="mb-2">
-                                    <label class="text-secondary text-sm">Start Time</label>
-                                    <input type="time" name="startTime"
-                                           class="form-control form-control-sm"
-                                           value="{{ date("H:i", strtotime($appointment->raw_start_time)) }}">
-                                </div>
-                                <div class="mb-2">
-                                    <label class="text-secondary text-sm">End Time</label>
-                                    <input type="time" name="endTime"
-                                           class="form-control form-control-sm"
-                                           value="{{ date("H:i", strtotime($appointment->raw_end_time)) }}">
-                                </div>
-                                <div class="mb-2">
-                                    <label class="text-secondary text-sm">Timezone *</label>
-                                    <select name="timeZone" class="form-control form-control-sm"
-                                            required>
-                                        <option value=""> --select-- </option>
-                                        <option
-                                            {{ $appointment->timezone === 'EASTERN' ? 'selected' : '' }} value="EASTERN">Eastern</option>
-                                        <option
-                                            {{ $appointment->timezone === 'CENTRAL' ? 'selected' : '' }} value="CENTRAL">Central</option>
-                                        <option
-                                            {{ $appointment->timezone === 'MOUNTAIN' ? 'selected' : '' }} value="MOUNTAIN">Mountain</option>
-                                        <option
-                                            {{ $appointment->timezone === 'PACIFIC' ? 'selected' : '' }} value="PACIFIC">Pacific</option>
-                                        <option
-                                            {{ $appointment->timezone === 'ALASKA' ? 'selected' : '' }} value="ALASKA">Alaska</option>
-                                        <option
-                                            {{ $appointment->timezone === 'HAWAII' ? 'selected' : '' }} value="HAWAII">Hawaii</option>
-                                        <option
-                                            {{ $appointment->timezone === 'PUERTO_RICO' ? 'selected' : '' }} value="PUERTO_RICO">Puerto Rico</option>
-                                    </select>
-                                </div>
-                                <div class="mb-2">
-                                    <label class="text-secondary text-sm">Title</label>
-                                    <input type="text" name="title" class="form-control form-control-sm"
-                                           value="{{ $appointment->title }}">
-                                </div>
-                                <div class="mb-2">
-                                    <label class="text-secondary text-sm">Description</label>
-                                    <textarea name="description"
-                                              class="form-control form-control-sm">{{ $appointment->description }}</textarea>
-                                </div>
-                                <div>
-                                    <button submit class="btn btn-sm btn-primary mr-1">Submit</button>
-                                    <button cancel class="btn btn-sm btn-default border">Cancel</button>
-                                </div>
-                            </form>
+                            @include('app/patient/partials/_appointment-form', ['appointment' => $appointment])
                         </div>
-                        {{ friendly_date_time($appointment->raw_date, false) }}
+                        {{ $appointment->raw_date }}
                         @if($appointment->raw_start_time)
-                            , {{ friendly_time($appointment->raw_start_time, false) }}
+                            &nbsp;{{ friendly_time($appointment->raw_start_time, false) }}
                         @endif
                         @if($appointment->timezone)
                             &nbsp;<span class="text-secondary text-sm">({{ $appointment->timezone }})</span>
@@ -263,7 +76,6 @@
                 }
             }
             if(_parent.is('.end-time')) {
-                let startSlot = _parent.find('.slot').first();
                 _parent.find('.slot').each(function() {
                     if(+$(this).attr('data-start') < selectedStart) {
                         $(this).addClass('blocked');
@@ -271,36 +83,69 @@
                 });
             }
         }
-        function initAppointmentCalendar() {
-            var calendarElem = $('.pro-appointment-calendar');
-            calendarElem.datepicker({
+        function initSingleCalendar(_elem) {
+            _elem.datepicker({
                 format: 'yyyy-mm-dd'
             });
-            calendarElem.on('changeDate', function () {
-                console.log(calendarElem.datepicker('getFormattedDate'));
+            _elem.on('changeDate', function () {
+                console.log(_elem.datepicker('getFormattedDate'));
                 let parentForm = $(this).closest('form');
-                parentForm.find('[name="date"]').val(calendarElem.datepicker('getFormattedDate'));
-                parentForm.find('[name="startTime"], [name="endTime"]').val('');
+                parentForm.find('[name="date"]').val(_elem.datepicker('getFormattedDate'));
+                // parentForm.find('[name="startTime"], [name="endTime"]').val('');
                 parentForm.find('.slot-picker.start-time').removeClass('disabled');
                 let params = 'proUid={{ $pro->uid }}&' +
                     'timeZone=' + parentForm.find('[name="timeZone"]').val() + '&' +
-                    'localDate=' + calendarElem.datepicker('getFormattedDate');
+                    'localDate=' + _elem.datepicker('getFormattedDate');
                 $.get('/api/appointment/getBookedTimesForProAndTimezone?' + params, function(_data) {
                     console.log(_data);
                     selectedStart = 0;
                     if(_data.success && _data.data) {
                         booked = _data.data;
+                        if(parentForm.is('[trigger-reload]')) {
+                            booked = booked.filter(function(_item) {
+                                return !(_item.startTime === parentForm.find('[name="startTime"]').val() &&
+                                    _item.endTime === parentForm.find('[name="endTime"]').val());
+                            });
+                        }
                         for(let i=0; i<booked.length; i++) {
                             booked[i].start = toMinutes(booked[i].startTime, true);
                             booked[i].end = toMinutes(booked[i].endTime);
                         }
-                        markBookedSlots($('.slot-picker.start-time'), booked);
-                        markBookedSlots($('.slot-picker.end-time'), booked);
+                        markBookedSlots(parentForm.find('.slot-picker.start-time'), booked);
+                        markBookedSlots(parentForm.find('.slot-picker.end-time'), booked);
                         parentForm.find('.slot-picker.end-time').addClass('disabled');
+
+                        // reload stuff!
+                        if(parentForm.is('[trigger-reload]')) {
+                            parentForm.find('.slot-picker.start-time td.selected').removeClass('selected');
+                            parentForm.find('.slot-picker.start-time td').each(function() {
+                                let minutes = toMinutes(parentForm.find('[name="startTime"]').val(), true);
+                                if(+$(this).attr('data-start') === minutes) {
+                                    console.log('Matched: ', $(this).text())
+                                    $(this).addClass('selected');
+                                    selectedStart = +$(this).attr('data-start');
+                                    return false;
+                                }
+                            });
+                            parentForm.find('.slot-picker.end-time td.selected').removeClass('selected');
+                            parentForm.find('.slot-picker.end-time td').each(function() {
+                                if($(this).text() === parentForm.find('[name="endTime"]').val()) {
+                                    $(this).addClass('selected');
+                                    return false;
+                                }
+                            });
+                            parentForm.find('.slot-picker.end-time').removeClass('disabled');
+
+                        }
                     }
 
                 }, 'json');
             });
+        }
+        function initAppointmentCalendar() {
+            $('.pro-appointment-calendar').each(function() {
+                initSingleCalendar($(this));
+            });
 
             $(document).on('click', '.slot-picker td:not(.blocked)', function() {
                 let parentForm = $(this).closest('form');
@@ -311,7 +156,7 @@
                     parentForm.find('.slot-picker.end-time td.selected').removeClass('selected');
                     parentForm.find('.slot-picker.end-time').removeClass('disabled');
                     parentForm.find('[name="startTime"]').val($(this).text());
-                    markBookedSlots($('.slot-picker.end-time'), booked);
+                    markBookedSlots(parentForm.find('.slot-picker.end-time'), booked);
                 }
                 else {
                     parentForm.find('[name="endTime"]').val($(this).text());
@@ -326,6 +171,15 @@
                     $(this).closest('form').find('.pro-appointment-calendar').addClass('disabled');
                 }
             });
+
+            $('form[trigger-reload]').each(function() {
+                let form = $(this);
+                form.find('[name="timeZone"]').trigger('change');
+                form.find('.pro-appointment-calendar').datepicker(
+                    'setDate',
+                    new Date(form.find('[name="date"]').val())
+                );
+            });
         }
         addMCInitializer('patient-single-appointment-calendar', initAppointmentCalendar);
     })();