/* ---------------------------------------------------------------------------- * Easy!Appointments - Open Source Web Scheduler * * @package EasyAppointments * @author A.Tselegidis * @copyright Copyright (c) 2013 - 2016, Alex Tselegidis * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 * @link http://easyappointments.org * @since v1.2.0 * ---------------------------------------------------------------------------- */ /** * Backend Calendar * * This module implements the table calendar view of backend. * * @module BackendCalendarTableView */ 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); }); $calendarToolbar.on('change', '#select-filter-item', function() { var startDate = new Date($('.calendar-view .date-column:first').data('date')); var endDate = new Date(startDate.getTime()).add({days: parseInt($(this).val()) - 1}); _createView(startDate, endDate); }); $calendarToolbar.on('click', '#reload-appointments', function() { var startDate = new Date($('.calendar-view .date-column:first').data('date')); var endDate = new Date($('.calendar-view .date-column:last').data('date')); _createView(startDate, endDate); }); $calendar.on('click', '.calendar-view table td', function() { if ($(this).index() === 0) { return; // Clicked on an hour slot. } // Open the appointments modal in the selected hour. var hour = $(this).parent().find('td:first').text().split(':'); var date = new Date($(this).parents('.date-column').data('date')); date.set({hour: parseInt(hour[0]), minute: parseInt(hour[1])}); // Open the appointments dialog. $('#insert-appointment').trigger('click'); // Update start date field. $('#start-datetime').datepicker('setDate', date); // Select Service and provider. var $providerColumn = $(this).parents('.provider-column'); var serviceId = $providerColumn.find('thead tr:last th').eq($(this).index()).data('id'); var providerId = $providerColumn.data('provider').id; $('#select-service').val(serviceId).trigger('change'); $('#select-provider').val(providerId).trigger('change'); }); $(window).on('resize', _setCalendarSize); } function _createHeader() { var $calendarFilter = $('#calendar-filter'); $calendarFilter .find('select') .empty() .append(new Option('1 ' + EALang['day'] , 1)) .append(new Option('4 ' + EALang['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') }); var $wrapper = $('
').appendTo($calendarView); _getCalendarEvents(startDate, endDate) .done(function(response) { if (!GeneralFunctions.handleAjaxExceptions(response)) { return; } var currentDate = startDate; while(currentDate <= endDate) { _createDateColumn($wrapper, currentDate, response); currentDate.add({days: 1}); } _setCalendarSize(); }) .fail(GeneralFunctions.ajaxFailureHandler); } function _createDateColumn($wrapper, date, events) { var $dateColumn = $('
').appendTo($wrapper); $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('
' + (provider.first_name + ' ' + provider.last_name).trim() +'
' + EALang['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() + '
' + EALang['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; } var currentDate = new Date($providerColumn.parents('.date-column').data('date')); var $tbody = $providerColumn.find('table tbody'); for (var index in unavailabilities) { var unavailability = unavailabilities[index]; if (unavailability.id_users_provider !== $providerColumn.data('provider').id) { continue; } var eventDate = Date.parse(unavailability.start_datetime); var $event = $('
'); $event.html(unavailability.notes || EALang['unavailable']); $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) { $event.appendTo($(tr).prev().find('td').eq(1)); return false; } }); } } function _setCalendarSize() { var height = window.innerHeight - $('#header').outerHeight() - $('#footer').outerHeight() - $('#calendar-toolbar').outerHeight() - $('.calendar-header').outerHeight() - 50; $('.calendar-view').height(height); $('.calendar-view > div').css('min-width', '1000%'); var width = 0; $('.date-column').each(function(index, dateColumn) { width += $(dateColumn).outerWidth(); }); $('.calendar-view > div').css('min-width', width + 50); $('.calendar-view .not-working').outerHeight(height - 70); } /** * 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);