Răsfoiți Sursa

Convert calendar to vue app

Vijayakrishnan 4 ani în urmă
părinte
comite
b3eae4e18e
1 a modificat fișierele cu 197 adăugiri și 304 ștergeri
  1. 197 304
      resources/views/app/patient/appointment-calendar.blade.php

+ 197 - 304
resources/views/app/patient/appointment-calendar.blade.php

@@ -35,118 +35,45 @@
     <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-beta.1/dist/js/select2.min.js"></script>
     <link href='/fullcalendar-5.3.2/lib/main.css' rel='stylesheet' />
     <script src='/fullcalendar-5.3.2/lib/main.js'></script>
-    <div class="d-flex align-items-center mb-2">
-        <h4 class="font-weight-bold m-0 font-size-16">
-            Appointments for patient {{ $patient->displayName() }}
-        </h4>
-        <div class="ml-auto">
-            <label class="mr-2 my-0 text-secondary">Show appointments in</label>
-            <select id="eventTz" name="timeZone" class="form-control form-control-sm" required>
-                <option value="EASTERN" selected>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>
-    <div class="d-block appt-form">
-        {{--<form action="/api/appointment/{{ $appointment && $appointment->uid ? 'update' : 'create' }}" method="post" class="appt-form-col pr-2">
-            @if($appointment && $appointment->uid)
-                <input name="uid" type="hidden" value="{{ $appointment->uid }}">
-            @else
-                <input name="clientUid" type="hidden" value="{{ $patient->uid }}">
-            @endif
-            <div class="mb-3">
-                <label class="text-secondary mb-1">Patient</label>
-                <div class="font-weight-bold">{{ $patient->displayName() }}</div>
-            </div>
-            <div class="mb-3">
-                <label class="text-secondary mb-1">Pro *</label>
-                <select name="proUid" class="form-control form-control-sm">
-                    <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="mb-3">
-                <label class="text-secondary mb-1">Timezone *</label>
-                <select name="timeZone" class="form-control form-control-sm" required>
-                    <option value=""> --select-- </option>
-                    <option {{ ($appointment && $appointment->timezone === 'EASTERN') || (!$appointment || !$appointment->uid) ? '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>
+
+    <div id="calendarApp">
+        <div class="d-flex align-items-center mb-2">
+            <h4 class="font-weight-bold m-0 font-size-16">
+                Appointments for patient {{ $patient->displayName() }}
+            </h4>
+            <div class="ml-auto">
+                <label class="mr-2 my-0 text-secondary">Show appointments in</label>
+                <select id="eventTz" name="timeZone"
+                        class="form-control form-control-sm"
+                        v-model="timezone">
+                    <option value="EASTERN" selected>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 class="mb-3">
-                <label class="text-secondary mb-1">Date *</label>
-                <input name="date" class="form-control form-control-sm" type="date"
-                       value="{{ $appointment && $appointment->raw_date ? $appointment->raw_date : date('Y-m-d') }}"
-                       required>
-            </div>
-            <div class="mb-3">
-                <label class="text-secondary mb-1">Start Time *</label>
-                <input name="startTime" class="form-control form-control-sm" type="time"
-                       value="{{ $appointment && $appointment->raw_start_time ? $appointment->raw_start_time : '' }}"
-                       required>
-            </div>
-            <div class="mb-3">
-                <label class="text-secondary mb-1">End Time</label>
-                <input name="endTime" class="form-control form-control-sm" type="time"
-                       value="{{ $appointment && $appointment->raw_end_time ? $appointment->raw_end_time : '' }}">
-            </div>
-            <div class="mb-3">
-                <label class="text-secondary mb-1">Title</label>
-                <input name="title" class="form-control form-control-sm" type="text"
-                       value="{{ $appointment && $appointment->title ? $appointment->title : '' }}"
-                       placeholder="(optional)">
-            </div>
-            <div class="mb-3">
-                <label class="text-secondary mb-1">Description</label>
-                <textarea name="description" class="form-control form-control-sm"
-                          type="text"
-                          placeholder="(optional)"
-                >{{ $appointment && $appointment->description ? $appointment->description : '' }}</textarea>
-            </div>
-            <div class="mb-3">
-                <button class="btn btn-sm btn-primary d-block w-100 font-weight-bold apply-appt-button" disabled>
-                    @if($appointment && $appointment->uid)
-                        Update Appointment
-                    @else
-                        Book Appointment
-                    @endif
-                </button>
-            </div>
-        </form>--}}
-        <form class="appt-form-col w-100 d-flex align-items-center mb-2">
-            <label class="mr-2 my-0 text-secondary text-nowrap">Show appointments by</label>
-            <select id="eventPros" name="proUid" class="form-control form-control-sm flex-grow-1" multiple>
-                <?php
-                $proIndex = 0;
-                $proMeta = [];
-                ?>
-                @foreach($pros as $iPro)
-                    <option value="{{$iPro->id}}" {{ $iPro->uid === $pro->uid ? 'selected' : '' }}
-                            data-bc="{{$palette[$proIndex]["bc"]}}"
-                            data-fc="{{$palette[$proIndex]["fc"]}}"
-                            data-initials="{{$iPro->initials()}}">
-                        {{$iPro->displayName()}}
-                    </option>
+        </div>
+        <div class="d-block appt-form">
+            <form class="appt-form-col w-100 d-flex align-items-center mb-2">
+                <label class="mr-2 my-0 text-secondary text-nowrap">Show appointments by</label>
+                <select id="eventPros" name="proUid"
+                        class="form-control form-control-sm flex-grow-1" multiple
+                        v-model="proIds">
                     <?php
+                    $proIndex = 0;
+                    $proMeta = [];
+                    ?>
+                    @foreach($pros as $iPro)
+                        <option value="{{$iPro->id}}"
+                                data-bc="{{$palette[$proIndex]["bc"]}}"
+                                data-fc="{{$palette[$proIndex]["fc"]}}"
+                                data-initials="{{$iPro->initials()}}">
+                            {{$iPro->displayName()}}
+                        </option>
+                        <?php
                         $proMeta[$iPro->uid] = [
                             "bc" => $palette[$proIndex]["bc"],
                             "fc" => $palette[$proIndex]["fc"],
@@ -154,217 +81,183 @@
                         ];
                         $proIndex++;
                         if($proIndex >= count($palette)) $proIndex = 0;
-                    ?>
-                @endforeach
-            </select>
-        </form>
-        <hr class="my-2">
-        <div class="appt-calendar-col">
-            <div class="stag-fc-container">
+                        ?>
+                    @endforeach
+                </select>
+            </form>
+            <hr class="my-2">
+            <div class="appt-calendar-col">
+                <div class="stag-fc-container">
 
+                </div>
             </div>
         </div>
     </div>
     <script>
         (function() {
-            let calendarObject = null;
-            let proMeta = <?= json_encode($proMeta) ?>;
-            function initSelect2() {
-                $('#eventTz').select2({
-                    templateResult: function(_state) {
-                        return $('<span class="mcp-theme-1"><span>' + _state.text + '</span></span>');
-                    }
-                });
-                $('#eventPros').select2({
-
-                    closeOnSelect: false,
-
-                    // dropdown options
-                    templateResult: function(_state) {
-                        let element = _state.element;
-                        if(!element || !element.value) {
-                            return $('<span class="mcp-theme-1"><span>' + _state.text + '</span></span>');
-                        }
-                        element = $(element);
-                        return $('<span class="mcp-theme-1 pro-option" ' +
-                            'data-initials="' + element.attr('data-initials') + '" ' +
-                            'data-bc="' + element.attr('data-bc') + '" ' +
-                            'data-fc="' + element.attr('data-fc') + '"><span>' +
-                            '<span class="pro-option-initials" ' +
-                            'style="background: ' + element.attr('data-bc') + '; color: ' + element.attr('data-fc') + '">' +
-                            element.attr('data-initials') + '</span>' +
-                            _state.text +
-                            '</span></span>');
-                    },
 
-                    // selected items
-                    templateSelection: function(_state) {
-                        let element = _state.element;
-                        if(!element || !element.value) {
-                            return $('<span class="mcp-theme-1"><span>' + _state.text + '</span></span>');
-                        }
-                        element = $(element);
-                        return $('<span class="pro-selection" style="background: ' + element.attr('data-bc') + '; color: ' + element.attr('data-fc') + '">' +
-                            _state.text + '</span>');
-                    }
-                });
-            }
-            function initCalendar() {
-                calendarObject = new FullCalendar.Calendar($('.stag-fc-container')[0], {
-                    headerToolbar: {
-                        left: 'prev,next today',
-                        center: 'title',
-                        right: 'dayGridMonth,timeGridWeek,timeGridDay'
+            function init() {
+                window.calendarApp = new Vue({
+                    el: '#calendarApp',
+                    data: {
+                        calendar: null,
+                        proMeta: {!! json_encode($proMeta) !!},
+                        proIds: ['{{ $pro->id }}'],
+                        timezone: 'EASTERN',
+                        clickedDate: null,
                     },
-                    initialDate: '{{ date('Y-m-d') }}',
-                    editable: true,
-                    navLinks: true,
-                    dayMaxEvents: false,
-                    events: function(info, successCallback, failureCallback) {
-                        let proIds = $('#eventPros').val();
-                        if(!proIds || !proIds.length) {
-                            successCallback([]); // no events if no pro selected
-                            return;
-                        }
-                        let timeZone = $('#eventTz').val();
-                        if(!timeZone) {
-                            successCallback([]); // no events if no tz selected
-                            return;
-                        }
-                        console.log(proIds)
-                        $.get('/appointment/getAllAppointmentsForPros' +
-                            '?proIds=' + proIds +
-                            '&start=' + info.startStr.substr(0, 10) +
-                            '&end=' + info.endStr.substr(0, 10) +
-                            '&timeZone=' + timeZone, function(_data) {
-                            // $.get('/api/appointment/getAllAppointmentsForPro?start=1990-01-01&end=2025-01-01&timeZone=CENTRAL', function(_data) {
-                            if(_data && Array.isArray(_data)) {
-                                let events = _data;
-                                for(let e in events) {
-                                    if(events.hasOwnProperty(e) && proMeta[events[e].proUid]) {
-                                        let ev = events[e], meta = proMeta[ev.proUid];
-                                        ev.backgroundColor =  meta.bc;
-                                        ev.borderColor = meta.bc;
-                                        ev.textColor = meta.fc;
-                                        ev.initials = meta.initials;
-                                        ev.display = 'block';
+                    methods: {
+                        // init
+                        init: function() {
+                            this.initSelect2();
+                            this.initCalendar();
+                        },
+                        initSelect2: function () {
+                            let self = this;
+                            $('#eventTz')
+                                .select2({
+                                    templateResult: function(_state) {
+                                        return $('<span class="mcp-theme-1"><span>' + _state.text + '</span></span>');
                                     }
-                                }
-                                successCallback(events);
-                            }
-                            else {
-                                failureCallback(_data);
-                            }
-                        }, 'json');
-                    },
-                    loading: function(bool) {
-
-                    },
-                    dateClick: function(info) {
-                        $('.appt-form td.stag-selected').removeClass('stag-selected');
-                        $(info.dayEl).addClass('stag-selected');
-                        $('.appt-form [name="date"]').val(info.dateStr.substr(0, 10));
-                        $('.apply-appt-button').prop('disabled', false);
-                    },
-                    eventDrop: updateEvent,
-                    eventResize: updateEvent
-                });
-                calendarObject.render();
+                                })
+                                .on('change', function() {
+                                    self.timezone = $(this).val();
+                                    self.refreshEvents();
+                                });
+                            $('#eventPros')
+                                .select2({
+                                    closeOnSelect: false,
 
-            }
-            function updateEvent(info) {
-                let date = info.event.start.getFullYear() + "-" +
-                    ("0"+(info.event.start.getMonth()+1)).slice(-2) + "-" +
-                    ("0" + info.event.start.getDate()).slice(-2);
-                let startTime = ("0" + info.event.start.getHours()).slice(-2) + ":" +
-                    ("0" + info.event.start.getMinutes()).slice(-2);
-                let endTime = null;
-                if(info.event.end) {
-                    endTime = ("0" + info.event.end.getHours()).slice(-2) + ":" +
-                        ("0" + info.event.end.getMinutes()).slice(-2);
-                }
-                $.post('/api/appointment/updateDateAndTime', {
-                    uid: info.event.extendedProps.appointmentUid,
-                    date: date,
-                    startTime: startTime,
-                    endTime: endTime,
-                    timeZone: $('#eventTz').val(),
-                }, function(_data) {
-                    console.log(_data)
-                }, 'json');
-            }
-            function init() {
-
-                initSelect2();
-                initCalendar();
-
-                $(document).on('change', '#eventPros, #eventTz', function() {
-                    calendarObject.refetchEvents();
-                });
-
-                $(document).on('change', '.appt-form [name="date"]', function() {
-                    $('.appt-form td.stag-selected').removeClass('stag-selected');
-                    if(!$(this).val()) return;
-                    calendarObject.gotoDate($(this).val());
-                    $('.fc-day[data-date="' + $(this).val() + '"]').addClass('stag-selected');
-                });
+                                    // dropdown options
+                                    templateResult: function(_state) {
+                                        let element = _state.element;
+                                        if(!element || !element.value) {
+                                            return $('<span class="mcp-theme-1"><span>' + _state.text + '</span></span>');
+                                        }
+                                        element = $(element);
+                                        return $('<span class="mcp-theme-1 pro-option" ' +
+                                            'data-initials="' + element.attr('data-initials') + '" ' +
+                                            'data-bc="' + element.attr('data-bc') + '" ' +
+                                            'data-fc="' + element.attr('data-fc') + '"><span>' +
+                                            '<span class="pro-option-initials" ' +
+                                            'style="background: ' + element.attr('data-bc') + '; color: ' + element.attr('data-fc') + '">' +
+                                            element.attr('data-initials') + '</span>' +
+                                            _state.text +
+                                            '</span></span>');
+                                    },
 
-                $('.appt-form [name="date"]').trigger('change');
+                                    // selected items
+                                    templateSelection: function(_state) {
+                                        let element = _state.element;
+                                        if(!element || !element.value) {
+                                            return $('<span class="mcp-theme-1"><span>' + _state.text + '</span></span>');
+                                        }
+                                        element = $(element);
+                                        return $('<span class="pro-selection" style="background: ' + element.attr('data-bc') + '; color: ' + element.attr('data-fc') + '">' +
+                                            _state.text + '</span>');
+                                    }
+                                })
+                                .on('change', function() {
+                                    self.proIds = $(this).val();
+                                    self.refreshEvents();
+                                });
+                        },
+                        initCalendar: function () {
+                            let self = this;
+                            this.calendar = new FullCalendar.Calendar($('.stag-fc-container')[0], {
+                                headerToolbar: {
+                                    left: 'prev,next today',
+                                    center: 'title',
+                                    right: 'dayGridMonth,timeGridWeek,timeGridDay'
+                                },
+                                initialDate: '{{ date('Y-m-d') }}',
+                                editable: true,
+                                navLinks: true,
+                                dayMaxEvents: false,
+                                events: function(info, successCallback, failureCallback) {
+                                    if(!self.proIds || !self.proIds.length) {
+                                        successCallback([]); // no events if no pro selected
+                                        return;
+                                    }
+                                    if(!self.timezone) {
+                                        successCallback([]); // no events if no tz selected
+                                        return;
+                                    }
+                                    $.get('/appointment/getAllAppointmentsForPros' +
+                                        '?proIds=' + self.proIds +
+                                        '&start=' + info.startStr.substr(0, 10) +
+                                        '&end=' + info.endStr.substr(0, 10) +
+                                        '&timeZone=' + self.timezone, function(_data) {
+                                        // $.get('/api/appointment/getAllAppointmentsForPro?start=1990-01-01&end=2025-01-01&timeZone=CENTRAL', function(_data) {
+                                        if(_data && Array.isArray(_data)) {
+                                            let events = _data;
+                                            for(let e in events) {
+                                                if(events.hasOwnProperty(e) && self.proMeta[events[e].proUid]) {
+                                                    let ev = events[e], meta = self.proMeta[ev.proUid];
+                                                    ev.backgroundColor =  meta.bc;
+                                                    ev.borderColor = meta.bc;
+                                                    ev.textColor = meta.fc;
+                                                    ev.initials = meta.initials;
+                                                    ev.display = 'block';
+                                                }
+                                            }
+                                            successCallback(events);
+                                        }
+                                        else {
+                                            failureCallback(_data);
+                                        }
+                                    }, 'json');
+                                },
+                                loading: function(bool) {
 
-                $('form.appt-form-col').on('submit', function() {
-                    let form = $(this);
-                    if(!form[0].checkValidity()) {
-                        form[0].reportValidity();
-                        return false;
-                    }
-                    $('.apply-appt-button').prop('disabled', true);
-                    $('.appt-form [name="startTime"]').val($('.appt-form [name="startTime"]').val().substr(0, 5));
-                    $('.appt-form [name="endTime"]').val($('.appt-form [name="endTime"]').val().substr(0, 5));
-                    $.post(form.attr('action'), form.serialize(), function(_data) {
-                        if(_data && _data.success) {
-                            toastr.success('Appointment updated successfully');
-                            $('.apply-appt-button').prop('disabled', true);
-                            calendarObject.refetchEvents();
-                        }
-                        else {
-                            if(_data && _data.message) {
-                                toastr.error(_data.message);
-                            }
-                            else {
-                                toastr.error('Unable to update appointment!');
+                                },
+                                dateClick: function(info) {
+                                    this.clickedDate = {
+                                        allDay: info.allDay,
+                                        date: info.date,
+                                        dateStr: info.dateStr,
+                                        dayEl: info.dayEl,
+                                    };
+                                    $('.appt-form td.stag-selected').removeClass('stag-selected');
+                                    $(info.dayEl).addClass('stag-selected');
+                                },
+                                eventDrop: self.eventMovedOrResized,
+                                eventResize: self.eventMovedOrResized
+                            });
+                            this.calendar.render();
+                        },
+                        eventMovedOrResized: function (info) {
+                            let date = info.event.start.getFullYear() + "-" +
+                                ("0"+(info.event.start.getMonth()+1)).slice(-2) + "-" +
+                                ("0" + info.event.start.getDate()).slice(-2);
+                            let startTime = ("0" + info.event.start.getHours()).slice(-2) + ":" +
+                                ("0" + info.event.start.getMinutes()).slice(-2);
+                            let endTime = null;
+                            if(info.event.end) {
+                                endTime = ("0" + info.event.end.getHours()).slice(-2) + ":" +
+                                    ("0" + info.event.end.getMinutes()).slice(-2);
                             }
+                            $.post('/api/appointment/updateDateAndTime', {
+                                uid: info.event.extendedProps.appointmentUid,
+                                date: date,
+                                startTime: startTime,
+                                endTime: endTime,
+                                timeZone: this.timezone,
+                            }, function(_data) {
+                                console.log(_data)
+                            }, 'json');
+                        },
+                        refreshEvents: function() {
+                            this.calendar.refetchEvents();
                         }
-                    }, 'json');
-                    return false;
-                });
-
-                $(document).on('change input paste', '.appt-form-col *', function() {
-                    updateCalendarTitle();
-                    $('.apply-appt-button').prop('disabled', false);
-                });
-
-                function updateCalendarTitle() {
-                    if(1) return;
-                    $('.stag-calendar-header-extra').remove();
-                    if(!$('.appt-form [name="proUid"]').val() || !$('.appt-form [name="timeZone"]').val()) {
-                        $('.fc-toolbar-title').parent().addClass('mb-3').removeClass('text-center');
-                        return;
-                    }
-                    else {
-                        $('.fc-toolbar-title').parent().removeClass('mb-3').addClass('text-center');
+                    },
+                    mounted: function() {
+                        this.init();
                     }
-                    let html = '<div class="stag-calendar-header-extra d-inline-flex">' +
-                        '<span class="text-secondary">Pro:</span>&nbsp;' +
-                        '<span class="font-weight-bold mr-4">' + $('.appt-form [name="proUid"] option:selected').text() + '</span>' +
-                        '<span class="text-secondary">Times in</span>&nbsp;' +
-                        '<span class="font-weight-bold">' + $('.appt-form [name="timeZone"] option:selected').text() + '</span>' +
-                        '</div>';
-                    $(html).insertAfter('.fc-toolbar-title');
-                }
-
-                updateCalendarTitle();
+                });
             }
-            addMCInitializer('patient-manage-appointment', init);
+
+            addMCInitializer('patient-calendar', init);
         })();
     </script>
 @endsection