From 8f6cfb2dd29699aee5164598367425b22a896c76 Mon Sep 17 00:00:00 2001 From: Alex Tselegidis Date: Sun, 17 Jul 2016 18:51:46 +0200 Subject: [PATCH] Created the codebase for the new table view (#182). --- src/application/controllers/Backend_api.php | 43 ++++ .../js/backend_calendar_default_view.js | 4 +- src/assets/js/backend_calendar_table_view.js | 229 +++++++++++++++++- 3 files changed, 272 insertions(+), 4 deletions(-) diff --git a/src/application/controllers/Backend_api.php b/src/application/controllers/Backend_api.php index cac378fc..d2e05eff 100644 --- a/src/application/controllers/Backend_api.php +++ b/src/application/controllers/Backend_api.php @@ -52,6 +52,49 @@ class Backend_api extends CI_Controller { } } + /** + * Get Calendar Events + * + * This method will return all the calendar events within a specified period. + */ + public function ajax_get_calendar_events() { + try { + $this->output->set_content_type('application/json'); + $this->load->model('appointments_model'); + $this->load->model('customers_model'); + $this->load->model('services_model'); + $this->load->model('providers_model'); + + $startDate = $_POST['startDate'] . ' 00:00:00'; + $endDate = $_POST['endDate'] . ' 23:59:59'; + + $response = [ + 'appointments' => $this->appointments_model->get_batch([ + 'is_unavailable' => false, + 'start_datetime >=' => $startDate, + 'end_datetime <=' => $endDate + ]), + 'unavailabilities' => $this->appointments_model->get_batch([ + 'is_unavailable' => true, + 'start_datetime >=' => $startDate, + 'end_datetime <=' => $endDate + ]) + ]; + + foreach($response['appointments'] as &$appointment) { + $appointment['provider'] = $this->providers_model->get_row($appointment['id_users_provider']); + $appointment['service'] = $this->services_model->get_row($appointment['id_services']); + $appointment['customer'] = $this->customers_model->get_row($appointment['id_users_customer']); + } + + $this->output->set_output(json_encode($response)); + } catch(Exception $exc) { + $this->output->set_output(json_encode([ + 'exceptions' => [exceptionToJavaScript($exc)] + ])); + } + } + /** * [AJAX] Get the registered appointments for the given date period and record. * diff --git a/src/assets/js/backend_calendar_default_view.js b/src/assets/js/backend_calendar_default_view.js index e8e6e99c..8f137986 100644 --- a/src/assets/js/backend_calendar_default_view.js +++ b/src/assets/js/backend_calendar_default_view.js @@ -1064,9 +1064,7 @@ window.BackendCalendarDefaultView = window.BackendCalendarDefaultView || {}; eventClick: _calendarEventClick, eventResize: _calendarEventResize, eventDrop: _calendarEventDrop, - eventAfterAllRender: function() { - _convertTitlesToHtml(); - } + eventAfterAllRender: _convertTitlesToHtml }); // Trigger once to set the proper footer position after calendar initialization. diff --git a/src/assets/js/backend_calendar_table_view.js b/src/assets/js/backend_calendar_table_view.js index 1307c923..c34deef2 100644 --- a/src/assets/js/backend_calendar_table_view.js +++ b/src/assets/js/backend_calendar_table_view.js @@ -19,14 +19,241 @@ window.BackendCalendarTableView = window.BackendCalendarTableView || {}; (function(exports) { + 'use strict'; function _bindEventHandlers() { + var $calendarToolbar = $('#calendar-toolbar'); + var $calendar = $('#calendar'); + + $calendar.on('click', '.calendar-header .btn.previous', function() { + var endDate = new Date($('#calendar .date-column:first').data('date')).add({days: -1}); + var startDate = new Date(endDate.getTime()).add({days: -1 * (parseInt($('#select-filter-item').val()) - 1)}); + _createView(startDate, endDate); + }); + + $calendar.on('click', '.calendar-header .btn.next', function() { + var startDate = new Date($('#calendar .date-column:last').data('date')).add({days: 1}); + var endDate = new Date(startDate.getTime()).add({days: parseInt($('#select-filter-item').val()) - 1}); + _createView(startDate, endDate); + }); + + // @todo reload appts event + + // @todo click slot shows appointments modal + } + + function _createHeader() { + var $calendarFilter = $('#calendar-filter'); + + $calendarFilter + .find('select') + .empty() + .append(new Option('1 Days', 1)) + .append(new Option('4 Days', 4)); + + var $calendarHeader = $('
').appendTo('#calendar'); + + $calendarHeader + .html( + '' + + '' + ); + } + + /** + * Create table schedule view. + * + * This method will destroy any previous instances and create a new view for displaying the appointments in + * a table format. + * + * @param {Date} startDate Start date to be displayed. + * @param {Date} endDate End date to be displayed. + */ + function _createView(startDate, endDate) { + $('#calendar .calendar-view').remove(); + + var $calendarView = $('
').appendTo('#calendar'); + + $calendarView.data({ + startDate: startDate.toString('yyyy-MM-dd'), + endDate: endDate.toString('yyyy-MM-dd') + }); + + _getCalendarEvents(startDate, endDate) + .done(function(response) { + if (!GeneralFunctions.handleAjaxExceptions(response)) { + return; + } + + var currentDate = startDate; + + while(currentDate <= endDate) { + _createDateColumn($calendarView, currentDate, response); + currentDate.add({days: 1}); + } + }) + .fail(GeneralFunctions.ajaxFailureHandler); + } - exports.initialize = function() { + function _createDateColumn($calendarView, date, events) { + var $dateColumn = $('
').appendTo($calendarView); + $dateColumn + .data('date', date.getTime()) + .append('

' + GeneralFunctions.formatDate(date, GlobalVariables.dateFormat) + '

'); + + for (var index in GlobalVariables.availableProviders) { + var provider = GlobalVariables.availableProviders[index]; + _createProviderColumn($dateColumn, date, provider, events); + } + } + + function _createProviderColumn($dateColumn, date, provider, events) { + var $providerColumn = $('
').appendTo($dateColumn); + + $providerColumn.data('provider', provider); + + // Create the table slots. + _createSlots($providerColumn, date, provider); + + // Add the appointments to the column. + _createAppointments($providerColumn, events.appointments); + + // Add the unavailabilities to the column. + _createUnavailabilities($providerColumn, events.unavailabilities); + } + + function _createSlots($providerColumn, date, provider) { + var day = date.toString('dddd').toLowerCase(); + var plan = JSON.parse(provider.settings.working_plan)[day]; + + if (!plan) { + $providerColumn.append('
Not Working
'); + return; + } + + var $table = $('') + .appendTo($providerColumn) + .addClass('table table-condensed table-responsive table-hover table-striped') + .html( + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ); + + for (var index in GlobalVariables.availableServices) { + var service = GlobalVariables.availableServices[index]; + + if (provider.services.indexOf(service.id) > -1) { + $table.find('thead tr:last').append(''); + } + } + + var start = parseInt(plan.start.split(':')[0]); + var end = parseInt(plan.end.split(':')[0]) + 1; + var current = start; + var $tbody = $table.find('tbody'); + + while(current <= end) { + var $tr = $('').appendTo($tbody); + + var time = (current < 10 ? '0' + parseInt(current) : parseInt(current)) + (current % 1 === 0 ? ':00' : ':30'); + + $tr + .append('') + .append('
' + + (provider.first_name + ' ' + provider.last_name).trim() + + '
Time
' + service.name + '
' + time + ''.repeat(provider.services.length)); + + current += 0.5; + } + } + + function _createAppointments($providerColumn, appointments) { + if (appointments.length === 0) { + return; + } + + var currentDate = new Date($providerColumn.parents('.date-column').data('date')); + var $tbody = $providerColumn.find('table tbody'); + + for (var index in appointments) { + var appointment = appointments[index]; + + if (appointment.id_users_provider !== $providerColumn.data('provider').id) { + continue; + } + + var eventDate = Date.parse(appointment.start_datetime); + var $event = $('
'); + + $event.html( + appointment.service.name + ' - ' + + (appointment.customer.first_name + ' ' + appointment.customer.last_name).trim() + ); + + $tbody.find('tr').each(function(index, tr) { + var $td = $(tr).find('td:first'); + + var cellDate = new Date(currentDate.getTime()).set({ + hour: parseInt($td.text().split(':')[0]), + minute: parseInt($td.text().split(':')[1]) + }); + + if (eventDate < cellDate) { + var cellIndex = $providerColumn + .find('thead tr:last th[data-id="' + appointment.service.id + '"]') + .index(); + + $event.appendTo($(tr).prev().find('td').eq(cellIndex)); + return false; + } + }); + } + } + + function _createUnavailabilities($providerColumn, unavailabilities) { + if (unavailabilities.length === 0) { + return; + } + } + + /** + * Get the calendar events. + * + * @param {Date} startDate + * @param {Date} endDate + * + * @return {jQuery.jqXHR} + */ + function _getCalendarEvents(startDate, endDate) { + var url = GlobalVariables.baseUrl + '/index.php/backend_api/ajax_get_calendar_events'; + var data = { + csrfToken: GlobalVariables.csrfToken, + startDate: startDate.toString('yyyy-MM-dd'), + endDate: endDate.toString('yyyy-MM-dd') + }; + + return $.post(url, data); + } + + exports.initialize = function() { + _createHeader(); + _createView(Date.today(), Date.today().add({days: parseInt($('#select-filter-item').val() - 1)})); + _bindEventHandlers(); }; })(window.BackendCalendarTableView);