diff --git a/src/application/views/appointments/book.php b/src/application/views/appointments/book.php index fba29d92..9d61e121 100644 --- a/src/application/views/appointments/book.php +++ b/src/application/views/appointments/book.php @@ -424,6 +424,9 @@ + diff --git a/src/assets/js/frontend_book.js b/src/assets/js/frontend_book.js index ed604b21..d568ac84 100644 --- a/src/assets/js/frontend_book.js +++ b/src/assets/js/frontend_book.js @@ -11,7 +11,6 @@ window.FrontendBook = window.FrontendBook || {}; - /** * Frontend Book * @@ -85,13 +84,13 @@ window.FrontendBook = window.FrontendBook || {}; closeText: EALang['close'], onSelect: function(dateText, instance) { - _getAvailableHours(dateText); + FrontendBookApi.getAvailableHours(dateText); _updateConfirmFrame(); }, onChangeMonthYear: function(year, month, instance) { var currentDate = new Date(year, month - 1, 1); - _getUnavailableDates($('#select-provider').val(), $('#select-service').val(), + FrontendBookApi.getUnavailableDates($('#select-provider').val(), $('#select-service').val(), currentDate.toString('yyyy-MM-dd')); } }); @@ -124,7 +123,7 @@ window.FrontendBook = window.FrontendBook || {}; * date - time periods must be updated. */ $('#select-provider').change(function() { - _getUnavailableDates($(this).val(), $('#select-service').val(), + FrontendBookApi.getUnavailableDates($(this).val(), $('#select-service').val(), $('#select-date').datepicker('getDate').toString('yyyy-MM-dd')); _updateConfirmFrame(); }); @@ -157,7 +156,7 @@ window.FrontendBook = window.FrontendBook || {}; $('#select-provider').append(new Option('- ' +EALang['any_provider'] + ' -', 'any-provider')); } - _getUnavailableDates($('#select-provider').val(), $(this).val(), + FrontendBookApi.getUnavailableDates($('#select-provider').val(), $(this).val(), $('#select-date').datepicker('getDate').toString('yyyy-MM-dd')); _updateConfirmFrame(); _updateServiceDescription($('#select-service').val(), $('#service-description')); @@ -280,7 +279,7 @@ window.FrontendBook = window.FrontendBook || {}; * another customer or event. */ $('#book-appointment-submit').click(function(event) { - _registerAppointment(); + FrontendBookApi.registerAppointment(); }); /** @@ -291,82 +290,6 @@ window.FrontendBook = window.FrontendBook || {}; }); }; - /** - * This function makes an ajax call and returns the available - * hours for the selected service, provider and date. - * - * @param {string} selDate The selected date of which the available - * hours we need to receive. - */ - function _getAvailableHours(selDate) { - $('#available-hours').empty(); - - // Find the selected service duration (it is going to be send within the "postData" object). - var selServiceDuration = 15; // Default value of duration (in minutes). - $.each(GlobalVariables.availableServices, function(index, service) { - if (service['id'] == $('#select-service').val()) { - selServiceDuration = service['duration']; - } - }); - - // If the manage mode is true then the appointment's start - // date should return as available too. - var appointmentId = (FrontendBook.manageMode) ? GlobalVariables.appointmentData['id'] : undefined; - - // Make ajax post request and get the available hours. - var postUrl = GlobalVariables.baseUrl + '/index.php/appointments/ajax_get_available_hours', - postData = { - csrfToken: GlobalVariables.csrfToken, - service_id: $('#select-service').val(), - provider_id: $('#select-provider').val(), - selected_date: selDate, - service_duration: selServiceDuration, - manage_mode: FrontendBook.manageMode, - appointment_id: appointmentId - }; - - $.post(postUrl, postData, function(response) { - if (!GeneralFunctions.handleAjaxExceptions(response)) { - return; - } - - // The response contains the available hours for the selected provider and - // service. Fill the available hours div with response data. - if (response.length > 0) { - var currColumn = 1; - $('#available-hours').html('
'); - - $.each(response, function(index, availableHour) { - if ((currColumn * 10) < (index + 1)) { - currColumn++; - $('#available-hours').append('
'); - } - - $('#available-hours div:eq(' + (currColumn - 1) + ')').append( - '' + availableHour + '
'); - }); - - if (FrontendBook.manageMode) { - // Set the appointment's start time as the default selection. - $('.available-hour').removeClass('selected-hour'); - $('.available-hour').filter(function() { - return $(this).text() === Date.parseExact( - GlobalVariables.appointmentData['start_datetime'], - 'yyyy-MM-dd HH:mm:ss').toString('HH:mm'); - }).addClass('selected-hour'); - } else { - // Set the first available hour as the default selection. - $('.available-hour:eq(0)').addClass('selected-hour'); - } - - _updateConfirmFrame(); - - } else { - $('#available-hours').text(EALang['no_available_hours']); - } - }, 'json').fail(GeneralFunctions.ajaxFailureHandler); - } - /** * This function validates the customer's data input. The user cannot contiue * without passing all the validation checks. @@ -549,7 +472,7 @@ window.FrontendBook = window.FrontendBook || {}; // Set Appointment Date $('#select-date').datepicker('setDate', Date.parseExact(appointment['start_datetime'], 'yyyy-MM-dd HH:mm:ss')); - _getAvailableHours($('#select-date').val()); + FrontendBookApi.getAvailableHours($('#select-date').val()); // Apply Customer's Data $('#last-name').val(customer['last_name']); @@ -615,150 +538,4 @@ window.FrontendBook = window.FrontendBook || {}; } } - /** - * Register an appointment to the database. - * - * This method will make an ajax call to the appointments controller that will register - * the appointment to the database. - */ - function _registerAppointment() { - var $captchaText = $('.captcha-text'); - - if ($captchaText.length > 0) { - $captchaText.css('border', ''); - if ($captchaText.val() === '') { - $captchaText.css('border', '1px solid #dc3b40'); - return; - } - } - - var formData = jQuery.parseJSON($('input[name="post_data"]').val()); - - var postData = { - 'csrfToken': GlobalVariables.csrfToken, - 'post_data': formData - }; - - if ($captchaText.length > 0) { - postData.captcha = $captchaText.val(); - } - - if (GlobalVariables.manageMode) { - postData.exclude_appointment_id = GlobalVariables.appointmentData.id; - } - - var postUrl = GlobalVariables.baseUrl + '/index.php/appointments/ajax_register_appointment', - $layer = $('
'); - - $.ajax({ - url: postUrl, - method: 'post', - data: postData, - dataType: 'json', - beforeSend: function(jqxhr, settings) { - $layer - .appendTo('body') - .css({ - background: 'white', - position: 'fixed', - top: '0', - left: '0', - height: '100vh', - width: '100vw', - opacity: '0.5' - }); - } - }) - .done(function(response) { - if (!GeneralFunctions.handleAjaxExceptions(response)) { - $('.captcha-title small').trigger('click'); - return false; - } - - if (response.captcha_verification === false) { - $('#captcha-hint') - .text(EALang['captcha_is_wrong'] + '(' + response.expected_phrase + ')') - .fadeTo(400, 1); - - setTimeout(function() { - $('#captcha-hint').fadeTo(400, 0); - }, 3000); - - $('.captcha-title small').trigger('click'); - - $captchaText.css('border', '1px solid #dc3b40'); - - return false; - } - - window.location.replace(GlobalVariables.baseUrl - + '/index.php/appointments/book_success/' + response.appointment_id); - }) - .fail(function(jqxhr, textStatus, errorThrown) { - $('.captcha-title small').trigger('click'); - GeneralFunctions.ajaxFailureHandler(jqxhr, textStatus, errorThrown); - }) - .always(function() { - $layer.remove(); - }); - } - - /** - * Get the unavailable dates of a provider. - * - * This method will fetch the unavailable dates of the selected provider and service and then it will - * select the first available date (if any). It uses the "_getAvailableHours" method to fetch the appointment - * hours of the selected date. - * - * @param {int} providerId The selected provider ID. - * @param {int} serviceId The selected service ID. - * @param {string} selectedDateString Y-m-d value of the selected date. - */ - function _getUnavailableDates(providerId, serviceId, selectedDateString) { - var url = GlobalVariables.baseUrl + '/index.php/appointments/ajax_get_unavailable_dates', - data = { - provider_id: providerId, - service_id: serviceId, - selected_date: encodeURIComponent(selectedDateString), - csrfToken: GlobalVariables.csrfToken - }; - - $.ajax({ - url: url, - type: 'GET', - data: data, - dataType: 'json' - }) - .done(function(response) { - // Select first enabled date. - var selectedDate = Date.parse(selectedDateString), - numberOfDays = new Date(selectedDate.getFullYear(), selectedDate.getMonth() + 1, 0).getDate(); - - for (var i=1; i<=numberOfDays; i++) { - var currentDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), i); - if ($.inArray(currentDate.toString('yyyy-MM-dd'), response) === -1) { - $('#select-date').datepicker('setDate', currentDate); - _getAvailableHours(currentDate.toString('yyyy-MM-dd')); - break; - } - } - - // If all the days are unavailable then hide the appointments hours. - if (response.length === numberOfDays) { - $('#available-hours').text(EALang['no_available_hours']); - } - - // Apply the new beforeShowDayHandler method to the #select-date datepicker. - var beforeShowDayHandler = function(date) { - if ($.inArray(date.toString('yyyy-MM-dd'), response) != -1) { - return [false]; - } - return [true]; - }; - - $('#select-date').datepicker('option', 'beforeShowDay', beforeShowDayHandler); - }) - .fail(GeneralFunctions.ajaxFailureHandler); - } - })(window.FrontendBook); diff --git a/src/assets/js/frontend_book_api.js b/src/assets/js/frontend_book_api.js new file mode 100644 index 00000000..6d0d3855 --- /dev/null +++ b/src/assets/js/frontend_book_api.js @@ -0,0 +1,247 @@ +/* ---------------------------------------------------------------------------- + * 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.0.0 + * ---------------------------------------------------------------------------- */ + +window.FrontendBookApi = window.FrontendBookApi || {}; + +/** + * Frontend Book API + * + * This module serves as the API consumer for the booking wizard of the app. + * + * @module FrontendBookApi + */ +(function(exports) { + + 'use strict'; + + /** + * This function makes an ajax call and returns the available + * hours for the selected service, provider and date. + * + * @param {string} selDate The selected date of which the available + * hours we need to receive. + */ + exports.getAvailableHours = function(selDate) { + $('#available-hours').empty(); + + // Find the selected service duration (it is going to be send within the "postData" object). + var selServiceDuration = 15; // Default value of duration (in minutes). + $.each(GlobalVariables.availableServices, function(index, service) { + if (service['id'] == $('#select-service').val()) { + selServiceDuration = service['duration']; + } + }); + + // If the manage mode is true then the appointment's start + // date should return as available too. + var appointmentId = (FrontendBook.manageMode) ? GlobalVariables.appointmentData['id'] : undefined; + + // Make ajax post request and get the available hours. + var postUrl = GlobalVariables.baseUrl + '/index.php/appointments/ajax_get_available_hours', + postData = { + csrfToken: GlobalVariables.csrfToken, + service_id: $('#select-service').val(), + provider_id: $('#select-provider').val(), + selected_date: selDate, + service_duration: selServiceDuration, + manage_mode: FrontendBook.manageMode, + appointment_id: appointmentId + }; + + $.post(postUrl, postData, function(response) { + if (!GeneralFunctions.handleAjaxExceptions(response)) { + return; + } + + // The response contains the available hours for the selected provider and + // service. Fill the available hours div with response data. + if (response.length > 0) { + var currColumn = 1; + $('#available-hours').html('
'); + + $.each(response, function(index, availableHour) { + if ((currColumn * 10) < (index + 1)) { + currColumn++; + $('#available-hours').append('
'); + } + + $('#available-hours div:eq(' + (currColumn - 1) + ')').append( + '' + availableHour + '
'); + }); + + if (FrontendBook.manageMode) { + // Set the appointment's start time as the default selection. + $('.available-hour').removeClass('selected-hour'); + $('.available-hour').filter(function() { + return $(this).text() === Date.parseExact( + GlobalVariables.appointmentData['start_datetime'], + 'yyyy-MM-dd HH:mm:ss').toString('HH:mm'); + }).addClass('selected-hour'); + } else { + // Set the first available hour as the default selection. + $('.available-hour:eq(0)').addClass('selected-hour'); + } + + _updateConfirmFrame(); + + } else { + $('#available-hours').text(EALang['no_available_hours']); + } + }, 'json').fail(GeneralFunctions.ajaxFailureHandler); + }; + + /** + * Register an appointment to the database. + * + * This method will make an ajax call to the appointments controller that will register + * the appointment to the database. + */ + exports.registerAppointment = function() { + var $captchaText = $('.captcha-text'); + + if ($captchaText.length > 0) { + $captchaText.css('border', ''); + if ($captchaText.val() === '') { + $captchaText.css('border', '1px solid #dc3b40'); + return; + } + } + + var formData = jQuery.parseJSON($('input[name="post_data"]').val()); + + var postData = { + 'csrfToken': GlobalVariables.csrfToken, + 'post_data': formData + }; + + if ($captchaText.length > 0) { + postData.captcha = $captchaText.val(); + } + + if (GlobalVariables.manageMode) { + postData.exclude_appointment_id = GlobalVariables.appointmentData.id; + } + + var postUrl = GlobalVariables.baseUrl + '/index.php/appointments/ajax_register_appointment', + $layer = $('
'); + + $.ajax({ + url: postUrl, + method: 'post', + data: postData, + dataType: 'json', + beforeSend: function(jqxhr, settings) { + $layer + .appendTo('body') + .css({ + background: 'white', + position: 'fixed', + top: '0', + left: '0', + height: '100vh', + width: '100vw', + opacity: '0.5' + }); + } + }) + .done(function(response) { + if (!GeneralFunctions.handleAjaxExceptions(response)) { + $('.captcha-title small').trigger('click'); + return false; + } + + if (response.captcha_verification === false) { + $('#captcha-hint') + .text(EALang['captcha_is_wrong'] + '(' + response.expected_phrase + ')') + .fadeTo(400, 1); + + setTimeout(function() { + $('#captcha-hint').fadeTo(400, 0); + }, 3000); + + $('.captcha-title small').trigger('click'); + + $captchaText.css('border', '1px solid #dc3b40'); + + return false; + } + + window.location.replace(GlobalVariables.baseUrl + + '/index.php/appointments/book_success/' + response.appointment_id); + }) + .fail(function(jqxhr, textStatus, errorThrown) { + $('.captcha-title small').trigger('click'); + GeneralFunctions.ajaxFailureHandler(jqxhr, textStatus, errorThrown); + }) + .always(function() { + $layer.remove(); + }); + }; + + /** + * Get the unavailable dates of a provider. + * + * This method will fetch the unavailable dates of the selected provider and service and then it will + * select the first available date (if any). It uses the "FrontendBookApi.getAvailableHours" method to fetch the appointment + * hours of the selected date. + * + * @param {int} providerId The selected provider ID. + * @param {int} serviceId The selected service ID. + * @param {string} selectedDateString Y-m-d value of the selected date. + */ + exports.getUnavailableDates = function(providerId, serviceId, selectedDateString) { + var url = GlobalVariables.baseUrl + '/index.php/appointments/ajax_get_unavailable_dates', + data = { + provider_id: providerId, + service_id: serviceId, + selected_date: encodeURIComponent(selectedDateString), + csrfToken: GlobalVariables.csrfToken + }; + + $.ajax({ + url: url, + type: 'GET', + data: data, + dataType: 'json' + }) + .done(function(response) { + // Select first enabled date. + var selectedDate = Date.parse(selectedDateString), + numberOfDays = new Date(selectedDate.getFullYear(), selectedDate.getMonth() + 1, 0).getDate(); + + for (var i=1; i<=numberOfDays; i++) { + var currentDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), i); + if ($.inArray(currentDate.toString('yyyy-MM-dd'), response) === -1) { + $('#select-date').datepicker('setDate', currentDate); + FrontendBookApi.getAvailableHours(currentDate.toString('yyyy-MM-dd')); + break; + } + } + + // If all the days are unavailable then hide the appointments hours. + if (response.length === numberOfDays) { + $('#available-hours').text(EALang['no_available_hours']); + } + + // Apply the new beforeShowDayHandler method to the #select-date datepicker. + var beforeShowDayHandler = function(date) { + if ($.inArray(date.toString('yyyy-MM-dd'), response) != -1) { + return [false]; + } + return [true]; + }; + + $('#select-date').datepicker('option', 'beforeShowDay', beforeShowDayHandler); + }) + .fail(GeneralFunctions.ajaxFailureHandler); + }; + +})(window.FrontendBookApi);