Αλλαγές στα υπάρχον αρχεία που σχετίζονται με την κράτηση ραντεβού έτσι ώστε να είναι εφικτή η δημιουργία link, τα οποία θα επιτρέπουν στους πελάτες να πραγματοποιούν αλλαγές στα ραντεβού που έχουν καταχωρήσει.

This commit is contained in:
alextselegidis@gmail.com 2013-06-03 14:42:19 +00:00
parent 2112164b4a
commit f9a6b20052
16 changed files with 3552 additions and 180 deletions

View file

@ -1,53 +1,146 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Appointments extends CI_Controller { class Appointments extends CI_Controller {
/** /**
* This page displays the book appointment wizard * Default callback method of the application.
* for the customers. *
*/ * This method creates the appointment book wizard. If an appointment hash
public function index() { * is provided then it means that the customer followed the appointment
if (strtoupper($_SERVER['REQUEST_METHOD']) != 'POST') { * manage link that was send with the book success email.
// Display the appointment booking page to the customer. *
// Get business name. * @param string $appointment_hash The db appointment hash of an existing
* record.
*/
public function index($appointment_hash = '') {
if (strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST') {
$this->load->model('Settings_Model'); $this->load->model('Settings_Model');
$view_data['company_name'] = $this->Settings_Model->get_setting('company_name');
// Get the available services and providers.
$this->load->model('Services_Model'); $this->load->model('Services_Model');
$view_data['available_services'] = $this->Services_Model->get_available_services();
$this->load->model('Providers_Model'); $this->load->model('Providers_Model');
$view_data['available_providers'] = $this->Providers_Model->get_available_providers();
$company_name = $this->Settings_Model->get_setting('company_name');
$available_services = $this->Services_Model->get_available_services();
$available_providers = $this->Providers_Model->get_available_providers();
// If an appointment hash is provided then it means that the customer
// is trying to edit a registered record.
if ($appointment_hash !== ''){
// Load the appointments data and set the manage mode of the page.
$this->load->model('Appointments_Model');
$this->load->model('Customers_Model');
$manage_mode = TRUE;
$appointment_data = $this->Appointments_Model
->get_batch(array('hash' => $appointment_hash))[0];
$provider_data = $this->Providers_Model
->get_row($appointment_data['id_users_provider']);
$customer_data = $this->Customer_Model
->get_row($appointment_data['id_users_customer']);
} else {
// The customer is going to book an appointment so there is no
// need for the manage functionality to be initialized.
$manage_mode = false;
$appointment_data = array();
$provider_data = array();
$customer_data = array();
}
// Load the book appointment view. // Load the book appointment view.
$view_data = array (
'available_services' => $available_services,
'available_providers' => $available_providers,
'company_name' => $company_name,
'manage_mode' => $manage_mode,
'appointment_data' => $appointment_data,
'provider_data' => $provider_data,
'customer_data' => $customer_data
);
$this->load->view('appointments/book', $view_data); $this->load->view('appointments/book', $view_data);
} else { } else {
$post_data = json_decode($_POST['post_data'], true); // The page is a post-back. Register the appointment and send
// notification emails to the provider and the customer that are
// Add customer // related to the appointment.
$post_data = json_decode($_POST['post_data'], true);
$appointment_data = $post_data['appointment'];
$customer_data = $post_data['customer'];
$this->load->model('Customers_Model'); $this->load->model('Customers_Model');
$customer_id = $this->Customers_Model->add($post_data['customer']);
// Add appointment
$post_data['appointment']['id_users_customer'] = $customer_id;
$this->load->model('Appointments_Model'); $this->load->model('Appointments_Model');
$view_data['appointment_id'] = $this->Appointments_Model->add($post_data['appointment']);
$customer_id = $this->Customers_Model->add($customer_data);
$appointment_data['id_users_customer'] = $customer_id;
$appointment_data['id'] = $this->Appointments_Model->add($appointment_data);
$appointment_data['hash'] = $this->Appointments_Model
->get_value('hash', $appointment_data['id']);
// Send an email to the customer with the appointment info. // Send an email to the customer with the appointment info.
$this->load->library('Notifications'); $this->load->library('Notifications');
try { try {
$this->notifications->send_book_success($post_data['customer'], $post_data['appointment']); $this->notifications->send_book_success($customer_data, $appointment_data);
$this->notifications->send_new_appointment($post_data['customer'], $post_data['appointment']); $this->notifications->send_new_appointment($customer_data, $appointment_data);
} catch (NotificationException $not_exc) { } catch (NotificationException $not_exc) {
$view_data['notification_error'] = '<br><br><pre>An unexpected error occured while sending ' $view_data['notification_error'] = '<br><br>'
. 'you an email. Please backup the appointment details so that you can restore them ' . '<pre>An unexpected error occured while sending you an '
. 'later. <br><br>Error:<br>' . $not_exc->getMessage() . '</pre>'; . 'email. Please backup the appointment details so that '
. 'you can restore them later. <br><br>Error: <br>'
. $not_exc->getMessage() . '</pre>';
} }
// Load the book appointment view. // Load the book appointment view.
$view_data['appointment_id'] = $appointment_data['id'];
$this->load->view('appointments/book_success', $view_data); $this->load->view('appointments/book_success', $view_data);
}
}
/**
* Display the view - manage screen of an external
* appointment link.
*
* This method loads the page that is going to be displayed
* whenever a customer, or a provider clicks on the email link
* that enables him to preview and make changes to the selected
* appointment.
*
* @param string $user_type Link user type (one of the
* DB_SLUG_CUSTOMER, ... constants).
* @param string $appointment_hash the appointment db hash. This
* is used to identify the appointment record.
*
*/
public function external_link($user_type, $appointment_hash) {
if (strtoupper($_SERVER['REQUEST_METHOD']) != 'POST') {
// Prepare and display the external manage view page.
$this->load->model('Appointments_Model');
$this->load->model('Providers_Model');
$this->load->model('Customers_Model');
$this->load->model('Services_Model');
$appointment_data = $this->Appointments_Model
->get_batch(array('hash' => $appointment_hash))[0];
$provider_data = $this->Providers_Model
->get_row($appointment_data['id_users_provider']);
$customer_data = $this->Customers_Model
->get_row($appointment_data['id_users_customer']);
$available_providers = $this->Providers_Model->get_available_providers();
$available_services = $this->Services_Model->get_available_services();
$view_data = array(
'appointment_data' => $appointment_data,
'customer_data' => $customer_data,
'provider_data' => $provider_data,
'user_type' => $user_type,
'available_providers' => $available_providers,
'available_services' => $available_services
);
$this->load->view('appointments/external_manage', $view_data);
} else {
// The external manage page was posted back. Save the
// changes of the user.
// @task Save user changes.
} }
} }
/** /**
* [AJAX] Get the available appointment hours for the given date. * [AJAX] Get the available appointment hours for the given date.
@ -69,12 +162,20 @@ class Appointments extends CI_Controller {
$working_plan = json_decode($this->Providers_Model $working_plan = json_decode($this->Providers_Model
->get_value('working_plan', $_POST['provider_id']), true); ->get_value('working_plan', $_POST['provider_id']), true);
$reserved_appointments = $this->Appointments_Model->get_batch( $where_clause = array(
array( 'DATE(start_datetime)' => date('Y-m-d', strtotime($_POST['selected_date'])),
'DATE(start_datetime)' => date('Y-m-d', strtotime($_POST['selected_date'])), 'id_users_provider' => $_POST['provider_id'],
'id_users_provider' => $_POST['provider_id'], 'id_services' => $_POST['service_id']
'id_services' => $_POST['service_id'] );
));
if ($_POST['manage_mode']) {
// Current record id shouldn't be included as reserved time,
// whent the manage mode is true.
$where_clause['id !='] = $_POST['appointment_id'];
}
$reserved_appointments = $this->Appointments_Model->get_batch($where_clause);
// Find the empty spaces on the plan. The first split between // Find the empty spaces on the plan. The first split between
// the plan is due to a break (if exist). After that every reserved // the plan is due to a break (if exist). After that every reserved
@ -109,7 +210,7 @@ class Appointments extends CI_Controller {
'end' => $sel_date_working_plan['end'] 'end' => $sel_date_working_plan['end']
); );
} }
// PROBLEM
// Break the empty spaces with the reserved appointments. // Break the empty spaces with the reserved appointments.
$empty_spaces_with_appointments = array(); $empty_spaces_with_appointments = array();
if (count($reserved_appointments) > 0) { if (count($reserved_appointments) > 0) {
@ -133,10 +234,27 @@ class Appointments extends CI_Controller {
'end' => $space_end 'end' => $space_end
); );
} else { } else {
$empty_spaces_with_appointments[] = array( // Check if there are any other appointments between this
'start' => $space_start, // time space. If not, it is going to be added as it is.
'end' => $space_end $found = FALSE;
); foreach($reserved_appointments as $appt) {
$appt_start = date('H:i', strtotime($appt['start_datetime']));
$appt_end = date('H:i', strtotime($appt['end_datetime']));
if ($space_start < $appt_start && $space_end > $appt_end) {
$found = TRUE;
}
}
// It is also necessary to check that this time period doesn't
// already exist in the "$empty_spaces_with_appointments" array.
$empty_space = array(
'start' => $space_start,
'end' => $space_end
);
$already_exist = in_array($empty_space, $empty_spaces_with_appointments);
if ($found === FALSE && $already_exist === FALSE) {
$empty_spaces_with_appointments[] = $empty_space;
}
} }
} }
} }

View file

@ -69,7 +69,7 @@ class Unit_tests extends CI_Driver_Library {
*/ */
public function run_library_tests($output_report = true) { public function run_library_tests($output_report = true) {
// @task Implement unit tests for the libraries. // @task Implement unit tests for the libraries.
if ($output_report) { if ($output_report) {
$this->CI->output->append_output($this->CI->unit->report()); $this->CI->output->append_output($this->CI->unit->report());
} }

View file

@ -74,8 +74,9 @@ class Unit_tests_appointments_model extends CI_Driver {
// Check if the record is the one that was inserted. // Check if the record is the one that was inserted.
$db_data = $this->CI->db->get_where('ea_appointments', array('id' => $appointment_data['id']))->row_array(); $db_data = $this->CI->db->get_where('ea_appointments', array('id' => $appointment_data['id']))->row_array();
unset($db_data['hash']); // This should not be included because is generate when the record is inserted.
$this->CI->unit->run($appointment_data, $db_data, 'Test if add() appointment (insert operation) has successfully inserted a record.'); $this->CI->unit->run($appointment_data, $db_data, 'Test if add() appointment (insert operation) has successfully inserted a record.');
// Delete inserted record. // Delete inserted record.
$this->CI->db->delete('ea_appointments', array('id' => $appointment_data['id'])); $this->CI->db->delete('ea_appointments', array('id' => $appointment_data['id']));
} }
@ -355,7 +356,7 @@ class Unit_tests_appointments_model extends CI_Driver {
$appointment_data = array( $appointment_data = array(
'start_datetime' => '2013-05-01 12:30:00', 'start_datetime' => '2013-05-01 12:30:00',
'end_datetime' => '2013-05-01 13:00:00', 'end_datetime' => '2013-05-01 13:00:00',
'notes' => 'Some notes right here...', 'notes' => 'Some notes right here...',
'id_users_provider' => $this->provider_id, 'id_users_provider' => $this->provider_id,
'id_users_customer' => $this->customer_id, 'id_users_customer' => $this->customer_id,
'id_services' => $this->service_id 'id_services' => $this->service_id
@ -407,6 +408,7 @@ class Unit_tests_appointments_model extends CI_Driver {
'start_datetime' => '2013-05-01 12:30:00', 'start_datetime' => '2013-05-01 12:30:00',
'end_datetime' => '2013-05-01 13:00:00', 'end_datetime' => '2013-05-01 13:00:00',
'notes' => 'Some notes right here...', 'notes' => 'Some notes right here...',
'hash' => '91de2d31f5cbb6d26a5b1b3e710d38d1',
'id_users_provider' => $this->provider_id, 'id_users_provider' => $this->provider_id,
'id_users_customer' => $this->customer_id, 'id_users_customer' => $this->customer_id,
'id_services' => $this->service_id 'id_services' => $this->service_id

View file

@ -120,7 +120,7 @@ class Unit_tests_customers_model extends CI_Driver {
$has_thrown_exception = TRUE; $has_thrown_exception = TRUE;
} }
$this->CI->unit->run($has_thrown_exception, TRUE, 'Test add() customer with invalid email address'); $this->CI->unit->run($has_thrown_exception, TRUE, 'Test add() customer with invalid email address.');
} }
private function test_add_missing_no_last_name() { private function test_add_missing_no_last_name() {

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@ require_once dirname(__FILE__) . '/external/class.phpmailer.php';
* on the system. * on the system.
* *
* Custom system settings for the notification section are loaded * Custom system settings for the notification section are loaded
* during the execution of the class methods. * during the execution of each class methods.
*/ */
class Notifications { class Notifications {
private $CI; private $CI;
@ -29,8 +29,8 @@ class Notifications {
* @param array $replace_array Array that contains the variables * @param array $replace_array Array that contains the variables
* to be replaced. * to be replaced.
* @param string $email_html The email template hmtl. * @param string $email_html The email template hmtl.
* @return string Returns the new email html that contain the variables * @return string Returns the new email html that contain the
* of the $replace_array. * variables of the $replace_array.
*/ */
private function replace_template_variables($replace_array, $email_html) { private function replace_template_variables($replace_array, $email_html) {
foreach($replace_array as $var=>$value) { foreach($replace_array as $var=>$value) {
@ -58,17 +58,20 @@ class Notifications {
$this->CI->load->model('Services_Model'); $this->CI->load->model('Services_Model');
$this->CI->load->model('Settings_Model'); $this->CI->load->model('Settings_Model');
$provider_data = $this->CI->Providers_Model->get_row($appointment_data['id_users_provider']); $provider_data = $this->CI->Providers_Model
$service_data = $this->CI->Services_Model->get_row($appointment_data['id_services']); ->get_row($appointment_data['id_users_provider']);
$service_data = $this->CI->Services_Model
->get_row($appointment_data['id_services']);
$replace_array = array( $replace_array = array(
'$appointment_service' => $service_data['name'], '$appointment_service' => $service_data['name'],
'$appointment_provider' => $provider_data['first_name'] . ' ' . $provider_data['last_name'], '$appointment_provider' => $provider_data['first_name'] . ' ' . $provider_data['last_name'],
'$appointment_date' => date('d/m/Y H:i', strtotime($appointment_data['start_datetime'])), '$appointment_date' => date('d/m/Y H:i', strtotime($appointment_data['start_datetime'])),
'$appointment_duration' => $service_data['duration'] . ' minutes', '$appointment_duration' => $service_data['duration'] . ' minutes',
'$company_link' => $this->CI->Settings_Model->get_setting('company_link'), '$appointment_link' => $this->CI->config->item('base_url') . $appointment_data['hash'],
'$company_name' => $this->CI->Settings_Model->get_setting('company_name'), '$company_link' => $this->CI->Settings_Model->get_setting('company_link'),
'$customer_name' => $customer_data['first_name'] . ' ' . $customer_data['last_name'] '$company_name' => $this->CI->Settings_Model->get_setting('company_name'),
'$customer_name' => $customer_data['first_name'] . ' ' . $customer_data['last_name']
); );
$email_html = file_get_contents(dirname(dirname(__FILE__)) . '/views/emails/book_success.php'); $email_html = file_get_contents(dirname(dirname(__FILE__)) . '/views/emails/book_success.php');
@ -105,7 +108,6 @@ class Notifications {
* @return bool Returns the operation result. * @return bool Returns the operation result.
*/ */
public function send_new_appointment($customer_data, $appointment_data) { public function send_new_appointment($customer_data, $appointment_data) {
$this->CI =& get_instance();
$this->CI->load->model('Providers_Model'); $this->CI->load->model('Providers_Model');
$this->CI->load->model('Services_Model'); $this->CI->load->model('Services_Model');
$this->CI->load->model('Settings_Model'); $this->CI->load->model('Settings_Model');
@ -114,31 +116,33 @@ class Notifications {
$service_data = $this->CI->Services_Model->get_row($appointment_data['id_services']); $service_data = $this->CI->Services_Model->get_row($appointment_data['id_services']);
$replace_array = array( $replace_array = array(
'$appointment_service' => $service_data['name'], '$appointment_service' => $service_data['name'],
'$appointment_provider' => $provider_data['first_name'] . ' ' . $provider_data['last_name'], '$appointment_provider' => $provider_data['first_name'] . ' ' . $provider_data['last_name'],
'$appointment_date' => date('d/m/Y H:i', strtotime($appointment_data['start_datetime'])), '$appointment_date' => date('d/m/Y H:i', strtotime($appointment_data['start_datetime'])),
'$appointment_duration' => $service_data['duration'] . ' minutes', '$appointment_duration' => $service_data['duration'] . ' minutes',
'$company_link' => $this->CI->Settings_Model->get_setting('company_link'), '$appointment_link' => $this->CI->config->item('base_url') . 'appointments/admin/' . $appointment_data['hash'],
'$company_name' => $this->CI->Settings_Model->get_setting('company_name'), '$company_link' => $this->CI->Settings_Model->get_setting('company_link'),
'$customer_name' => $customer_data['first_name'] . ' ' . $customer_data['last_name'], '$company_name' => $this->CI->Settings_Model->get_setting('company_name'),
'$customer_email' => $customer_data['email'], '$customer_name' => $customer_data['first_name'] . ' ' . $customer_data['last_name'],
'$customer_phone' => $customer_data['phone_number'], '$customer_email' => $customer_data['email'],
'$customer_address' => $customer_data['address'] '$customer_phone' => $customer_data['phone_number'],
'$customer_address' => $customer_data['address']
); );
$email_html = file_get_contents(dirname(dirname(__FILE__)) . '/views/emails/new_appointment.php'); $email_html = file_get_contents(dirname(dirname(__FILE__))
. '/views/emails/new_appointment.php');
$email_html = $this->replace_template_variables($replace_array, $email_html); $email_html = $this->replace_template_variables($replace_array, $email_html);
$mail = new PHPMailer(); $mail = new PHPMailer();
$mail->From = $this->CI->Settings_Model->get_setting('company_email'); $mail->From = $this->CI->Settings_Model->get_setting('company_email');
$mail->FromName = $this->CI->Settings_Model->get_setting('company_name');; $mail->FromName = $this->CI->Settings_Model->get_setting('company_name');;
$mail->AddAddress($provider_data['email']); // Do not use the name argument, phpmailer crushes. $mail->AddAddress($provider_data['email']); // "Name" argument crushes the phpmailer class.
$mail->IsHTML(true); $mail->IsHTML(true);
$mail->CharSet = 'UTF-8'; $mail->CharSet = 'UTF-8';
$mail->Subject = 'New Appointment'; $mail->Subject = 'New Appointment';
$mail->Body = $email_html; $mail->Body = $email_html;
if(!$mail->Send()) { if (!$mail->Send()) {
throw new NotificationException('Email could not been sent. ' throw new NotificationException('Email could not been sent. '
. 'Mailer Error (Line ' . __LINE__ . '): ' . $mail->ErrorInfo); . 'Mailer Error (Line ' . __LINE__ . '): ' . $mail->ErrorInfo);
} }

View file

@ -83,6 +83,7 @@ class Appointments_Model extends CI_Model {
* @return int Returns the id of the new record. * @return int Returns the id of the new record.
*/ */
private function insert($appointment_data) { private function insert($appointment_data) {
$appointment_data['hash'] = $this->generate_hash();
if (!$this->db->insert('ea_appointments', $appointment_data)) { if (!$this->db->insert('ea_appointments', $appointment_data)) {
throw new DatabaseException('Could not insert appointment record.'); throw new DatabaseException('Could not insert appointment record.');
} }
@ -287,6 +288,21 @@ class Appointments_Model extends CI_Model {
return $this->db->get('ea_appointments')->result_array(); return $this->db->get('ea_appointments')->result_array();
} }
/**
* Generate a unique hash for the given appointment data.
*
* This method uses the current date-time to generate a unique
* hash string that is later used to identify this appointment.
* Hash is needed when the email is send to the user with an
* edit link.
*
* @return string Returns the unique appointment hash.
*/
public function generate_hash() {
$current_date = new DateTime();
return md5($current_date->getTimestamp());
}
} }
/* End of file appointments_model.php */ /* End of file appointments_model.php */

View file

@ -179,7 +179,6 @@ class Customers_Model extends CI_Model {
return TRUE; return TRUE;
} catch (Exception $exc) { } catch (Exception $exc) {
echo $exc->getMessage();
return FALSE; return FALSE;
} }
} }

View file

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta http-equiv="content-type" content="text/html; charset=UTF-8">
<?php // INCLUDE CSS FILES ?> <?php
// ------------------------------------------------------------
// INCLUDE CSS FILES
// ------------------------------------------------------------ ?>
<link <link
rel="stylesheet" rel="stylesheet"
type="text/css" type="text/css"
@ -25,7 +28,10 @@
type="text/css" type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/style.css"> href="<?php echo $this->config->base_url(); ?>assets/css/style.css">
<?php // INCLUDE JS FILES ?> <?php
// ------------------------------------------------------------
// INCLUDE JAVASCRIPT FILES
// ------------------------------------------------------------ ?>
<script <script
type="text/javascript" type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/libs/jquery/jquery.min.js"> src="<?php echo $this->config->base_url(); ?>assets/js/libs/jquery/jquery.min.js">
@ -55,37 +61,50 @@
src="<?php echo $this->config->base_url(); ?>assets/js/general_functions.js"> src="<?php echo $this->config->base_url(); ?>assets/js/general_functions.js">
</script> </script>
<?php // SET FAVICON FOR PAGE ?> <?php
// ------------------------------------------------------------
// WEBPAGE FAVICON
// ------------------------------------------------------------ ?>
<link <link
rel="icon" rel="icon"
type="image/x-icon" type="image/x-icon"
href="<?php echo $this->config->base_url(); ?>assets/images/favicon.ico"> href="<?php echo $this->config->base_url(); ?>assets/images/favicon.ico">
<?php // JS GLOBAL VARIABLE DECLARATION ?> <?php
// ------------------------------------------------------------
// VIEW FILE JAVASCRIPT CODE
// ------------------------------------------------------------ ?>
<script type="text/javascript"> <script type="text/javascript">
// Define some global variables.
GlobalVariables = { GlobalVariables = {
services : <?php echo json_encode($available_services); ?>, availableServices : <?php echo json_encode($available_services); ?>,
providers : <?php echo json_encode($available_providers); ?>, availableProviders : <?php echo json_encode($available_providers); ?>,
baseUrl : <?php echo '"' . $this->config->base_url() . '"'; ?> baseUrl : <?php echo '"' . $this->config->base_url() . '"'; ?>,
} manageMode : <?php echo ($manage_mode) ? 'true' : 'false'; ?>,
</script> appointmentData : <?php echo json_encode($appointment_data); ?>,
providerData : <?php echo json_encode($provider_data); ?>,
<?php // JQUERY PAGE STUFF ?> customerData : <?php echo json_encode($customer_data); ?>
<script type="text/javascript"> };
$(document).ready(function() { $(document).ready(function() {
bookAppointment.initialize(true); bookAppointment.initialize(true, GlobalVariables.manageMode);
GeneralFunctions.centerElementOnPage($('#book-appointment')); GeneralFunctions.centerElementOnPage($('#book-appointment-wizard'));
}); });
</script> </script>
</head> </head>
<body> <body>
<div id="main" class="container"> <div id="main" class="container">
<div id="book-appointment">
<div id="top-bar"> <div id="book-appointment-wizard">
<span id="business-name"><?php echo $company_name; ?></span>
<div id="book-steps"> <?php
// ------------------------------------------------------
// FRAME TOP BAR
// ------------------------------------------------------ ?>
<div id="header">
<span id="company-name"><?php echo $company_name; ?></span>
<div id="steps">
<div id="step-1" class="book-step active-step" title="Select Service & Provider"> <div id="step-1" class="book-step active-step" title="Select Service & Provider">
<strong>1</strong> <strong>1</strong>
</div> </div>
@ -101,13 +120,36 @@
</div> </div>
</div> </div>
</div> </div>
<?php // SELECT SERVICE AND PROVIDER ?> <?php
<div id="book-appointment-1" class="book-appoinment-step"> // ------------------------------------------------------
<div class="step-frame"> // CANCEL APPOINTMENT BUTTON
<h2 class="step-title">Select Service & Provider</h2> // ------------------------------------------------------
<div class="step-content" style="width:270px"> if ($manage_mode === TRUE) {
<label for="select-service"><strong>Select Service</strong></label> echo '
<div id="cancel-appointment-frame">
<p>
Press the "Cancel" button to remove the appointment
from the company schedule.
</p>
<button id="cancel-appointment" class="button">Cancel</button>
</div>';
}
?>
<?php
// ------------------------------------------------------
// SELECT SERVICE AND PROVIDER
// ------------------------------------------------------ ?>
<div id="wizard-frame-1" class="wizard-frame">
<div class="frame-container">
<h2 class="frame-title">Select Service & Provider</h2>
<div class="frame-content" style="width:270px">
<label for="select-service">
<strong>Select Service</strong>
</label>
<select id="select-service"> <select id="select-service">
<?php <?php
foreach($available_services as $service) { foreach($available_services as $service) {
@ -117,7 +159,10 @@
?> ?>
</select> </select>
<label for="select-provider"><strong>Select Provider</strong></label> <label for="select-provider">
<strong>Select Provider</strong>
</label>
<select id="select-provider"></select> <select id="select-provider"></select>
</div> </div>
</div> </div>
@ -128,11 +173,16 @@
</div> </div>
</div> </div>
<?php // APPOINTMENT DATE ?> <?php
<div id="book-appointment-2" class="book-appoinment-step" style="display:none;"> // ------------------------------------------------------
<div class="step-frame"> // SELECT APPOINTMENT DATE
<h2 class="step-title">Select Appointment Date And Time</h2> // ------------------------------------------------------ ?>
<div class="step-content" style="width:600px"> <div id="wizard-frame-2" class="wizard-frame" style="display:none;">
<div class="frame-container">
<h2 class="frame-title">Select Appointment Date And Time</h2>
<div class="frame-content" style="width:600px">
<div class="span3"> <div class="span3">
<div id="select-date"></div> <div id="select-date"></div>
</div> </div>
@ -152,11 +202,16 @@
</div> </div>
</div> </div>
<?php // CUSTOMER'S INFO ?> <?php
<div id="book-appointment-3" class="book-appoinment-step" style="display:none;"> // ------------------------------------------------------
<div class="step-frame"> // ENTER CUSTOMER DATA
<h2 class="step-title">Fill In Your Information</h2> // ------------------------------------------------------ ?>
<div class="step-content" style="width:600px"> <div id="wizard-frame-3" class="wizard-frame" style="display:none;">
<div class="frame-container">
<h2 class="frame-title">Fill In Your Information</h2>
<div class="frame-content" style="width:600px">
<div class="span3"> <div class="span3">
<label for="last-name">Last Name *</label> <label for="last-name">Last Name *</label>
<input type="text" id="last-name" class="required" maxlength="250" /> <input type="text" id="last-name" class="required" maxlength="250" />
@ -198,11 +253,14 @@
</div> </div>
</div> </div>
<?php // CONFIRMATION STEP ?> <?php
<div id="book-appointment-4" class="book-appoinment-step" style="display:none;"> // ------------------------------------------------------
<div class="step-frame"> // APPOINTMENT DATA CONFIRMATION
<h2 class="step-title">Confirm Appointment</h2> // ------------------------------------------------------ ?>
<div class="step-content" style="width:600px"> <div id="wizard-frame-4" class="wizard-frame" style="display:none;">
<div class="frame-container">
<h2 class="frame-title">Confirm Appointment</h2>
<div class="frame-content" style="width:600px">
<div id="appointment-info" class="span3"></div> <div id="appointment-info" class="span3"></div>
<div id="customer-info" class="span3"></div> <div id="customer-info" class="span3"></div>
</div> </div>
@ -213,14 +271,25 @@
data-step_index="4"><i class="icon-backward"></i> Back</button> data-step_index="4"><i class="icon-backward"></i> Back</button>
<form id="book-appointment-form" style="display:inline-block" method="post"> <form id="book-appointment-form" style="display:inline-block" method="post">
<button type="submit" class="btn btn-success"> <button type="submit" class="btn btn-success">
<i class="icon-ok icon-white"></i>Confirm</button> <i class="icon-ok icon-white"></i>
<?php
echo (!$manage_mode) ? "Confirm" : "Update";
?>
</button>
<input type="hidden" name="post_data" /> <input type="hidden" name="post_data" />
</form> </form>
</div> </div>
</div> </div>
<?php
// ------------------------------------------------------
// FRAME FOOTER
// ------------------------------------------------------ ?>
<div id="frame-footer"> <div id="frame-footer">
Powered By <a href="https://code.google.com/p/easy-appointments/">Easy!Appointments</a> Powered By
<a href="https://code.google.com/p/easy-appointments/">
Easy!Appointments
</a>
</div> </div>
</div> </div>
</div> </div>

View file

@ -47,7 +47,7 @@
</style> </style>
</head> </head>
<body> <body>
<div id="success-frame" class="container"> <div id="success-frame" class="frame-container">
<img id="success-icon" src="<?php echo $this->config->base_url(); ?>assets/images/success.png" /> <img id="success-icon" src="<?php echo $this->config->base_url(); ?>assets/images/success.png" />
<h2>Your appointment has been successfully registered.</h2> <h2>Your appointment has been successfully registered.</h2>

View file

@ -41,7 +41,7 @@
</style> </style>
</head> </head>
<body> <body>
<div id="message-frame" class="container"> <div id="message-frame" class="frame-container">
<img <img
id="message-icon" id="message-icon"
src="<?php echo $this->config->base_url(); ?>assets/images/<?php echo $image; ?>" /> src="<?php echo $this->config->base_url(); ?>assets/images/<?php echo $image; ?>" />

View file

@ -0,0 +1,56 @@
<html>
<head>
<title>Appointment Book Success</title>
</head>
<body style="font: 13px arial, helvetica, tahoma;">
<div class="email-container" style="width: 650px;border: 1px solid #eee;">
<div id="header" style="background-color: #3DD481; border-bottom: 4px solid #1A865F;
height: 40px;padding: 10px 15px;">
<strong id="logo" style="color: white; font-size: 31px;
text-shadow: 1px 1px 1px #8F8888;">$company_name</strong>
</div>
<div id="content" style="padding: 10px 15px;">
<h2>Your appointment has been successfully booked!</h2>
<p>
Thank you $customer_name for arranging an appointment with us.
Below you can see the appointment details. Click on the edit
link to make changes to your appointment.
</p>
<h2>Appointment Details</h2>
<table id="appointment-details">
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Service</td>
<td style="padding: 3px;">$appointment_service</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Provider</td>
<td style="padding: 3px;">$appointment_provider</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Date</td>
<td style="padding: 3px;">$appointment_date</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Duration</td>
<td style="padding: 3px;">$appointment_duration</td>
</tr>
</table>
<h2>Edit Link</h2>
<p>
Press the following link to make changes to your appointment reservation.
You are able to change the appointment details three hours before
the appointment.
</p>
<a href="$appointment_link">$appointment_link</a>
</div>
<div id="footer" style="padding: 10px; text-align: center;
border-top: 1px solid #EEE;background: #FAFAFA;">
<a href="$company_link">$company_name</a> | Powered by Easy!Appointments
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,67 @@
<html>
<head>
<title>New Appointment</title>
</head>
<body style="font: 13px arial, helvetica, tahoma;">
<div class="email-container" style="width: 650px;border: 1px solid #eee;">
<div id="header" style="background-color: #3DD481; border-bottom: 4px solid #1A865F;
height: 40px; padding: 10px 15px;">
<strong id="logo" style="color: white; font-size: 31px;
text-shadow: 1px 1px 1px #8F8888;">$company_name</strong>
</div>
<div id="content" style="padding: 10px 15px;">
<h2>A new appointment has been added to your plan.</h2>
<h2>Appointment Details</h2>
<table id="appointment-details">
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Service</td>
<td style="padding: 3px;">$appointment_service</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Provider</td>
<td style="padding: 3px;">$appointment_provider</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Date</td>
<td style="padding: 3px;">$appointment_date</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Duration</td>
<td style="padding: 3px;">$appointment_duration</td>
</tr>
</table>
<h2>Customer Details</h2>
<table id="appointment-details">
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Name</td>
<td style="padding: 3px;">$customer_name</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Email</td>
<td style="padding: 3px;">$customer_email</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Phone</td>
<td style="padding: 3px;">$customer_phone</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Address</td>
<td style="padding: 3px;">$customer_address</td>
</tr>
</table>
<h2>Appointment Link</h2>
<p>You can make more actions by pressing the following link.</p>
<a href="$appointment_link">$appointment_link</a>
</div>
<div id="footer" style="padding: 10px; text-align: center;
border-top: 1px solid #EEE; background: #FAFAFA;">
<a href="$company_link">$company_name</a> | Powered by Easy!Appointments
</div>
</div>
</body>
</html>

View file

@ -10,23 +10,23 @@ body {
} }
/* REGISTER APPOINTMENT /* BOOK APPOINTMENT WIZARD
------------------------------------------------------------------------------ */ ------------------------------------------------------------------------------ */
#book-appointment { #book-appointment-wizard {
width: 660px; width: 660px;
background: #FFF; background: #FFF;
box-shadow: 0px 1px 1px #B6B6B6; box-shadow: 0px 1px 1px #B6B6B6;
min-height: 480px; min-height: 480px;
} }
#book-appointment #top-bar { #book-appointment-wizard #header {
padding: 5px; padding: 5px;
height: 70px; height: 70px;
background: #3DD481; background: #3DD481;
border-bottom: 4px solid #1A865F; border-bottom: 4px solid #1A865F;
} }
#book-appointment #business-name { #book-appointment-wizard #company-name {
font-weight: bold; font-weight: bold;
color: #FFF; color: #FFF;
font-size: 27px; font-size: 27px;
@ -36,43 +36,43 @@ body {
float: left; float: left;
} }
#book-appointment #book-steps { #book-appointment-wizard #steps {
width: 204px; width: 204px;
display: inline-block; display: inline-block;
float: right; float: right;
margin-top: 15px; margin-top: 15px;
} }
#book-appointment .book-appoinment-step { #book-appointment-wizard .wizard-frame {
padding: 10px 20px; padding: 10px 20px;
height: 434px; height: 434px;
} }
#book-appointment .book-appoinment-step .step-frame { #book-appointment-wizard .wizard-frame .frame-container {
height: 370px; height: 370px;
margin-bottom: 10px; margin-bottom: 10px;
} }
#book-appointment .step-frame .step-title { #book-appointment-wizard .frame-container .frame-title {
text-align: center; text-align: center;
margin-bottom: 28px; margin-bottom: 28px;
} }
#book-appointment .step-frame .step-content { #book-appointment-wizard .frame-container .frame-content {
margin: auto; margin: auto;
float: none; float: none;
} }
#book-appointment .command-buttons { #book-appointment-wizard .wizard-frame .command-buttons {
float: right; float: right;
} }
#book-appointment .command-buttons .btn { #book-appointment-wizard .wizard-frame .command-buttons .btn {
min-width: 80px; min-width: 80px;
margin-right: 10px; margin-right: 10px;
} }
#book-appointment .book-step { #book-appointment-wizard .book-step {
display: inline-block; display: inline-block;
height: 20px; height: 20px;
width: 20px; width: 20px;
@ -84,14 +84,14 @@ body {
border: 3px solid #38A07A; border: 3px solid #38A07A;
} }
#book-appointment .book-step strong { #book-appointment-wizard .book-step strong {
font-size: 18px; font-size: 18px;
display: block; display: block;
text-align: center; text-align: center;
color: #B6DFC6; color: #B6DFC6;
} }
#book-appointment .active-step { #book-appointment-wizard .active-step {
display: inline-block; display: inline-block;
height: 20px; height: 20px;
width: 20px; width: 20px;
@ -103,40 +103,49 @@ body {
border: 3px solid #38A07A; border: 3px solid #38A07A;
} }
#book-appointment .active-step strong { #book-appointment-wizard .active-step strong {
color: #396946; color: #396946;
font-size: 25px; font-size: 25px;
} }
#book-appointment #frame-footer { #book-appointment-wizard #frame-footer {
padding: 10px; padding: 10px;
text-align: center; text-align: center;
border-top: 1px solid #EEE; border-top: 1px solid #EEE;
background: #FAFAFA; background: #FAFAFA;
} }
.custom-qtip { #book-appointment-wizard #steps .custom-qtip {
border-width: 2px; border-width: 2px;
} }
#available-hours .available-hour { #book-appointment-wizard #available-hours .available-hour {
font-size: 15px; font-size: 15px;
padding: 1px; padding: 1px;
display: inline-block; display: inline-block;
} }
#available-hours .available-hour:hover { #book-appointment-wizard #available-hours .available-hour:hover {
font-weight: bold; font-weight: bold;
background-color: #CAEDF3; background-color: #CAEDF3;
cursor: pointer; cursor: pointer;
} }
#available-hours .selected-hour { #book-appointment-wizard #available-hours .selected-hour {
color: #0088cc; color: #0088cc;
font-weight: bold; font-weight: bold;
text-decoration: underline; text-decoration: underline;
} }
#book-appointment .span3 { #book-appointment-wizard .span3 {
min-width: 270px; /* This is especially needed for ie8 */ min-width: 270px; /* This is especially needed for ie8 */
} }
#cancel-appointment-frame {
}

View file

@ -1,20 +1,34 @@
/** /**
* This class implements the book appointment page functionality. * This class implements the book appointment page functionality. Once
* Once the initialize() method is called the page is fully functional * the initialize() method is called the page is fully functional and
* and can serve the appointment booking process. * can serve the appointment booking process.
* *
* @class Implelements the js part of the appointment booking page. * @class Implements the js part of the appointment booking page.
*/ */
var bookAppointment = { var bookAppointment = {
/**
* Determines the functionality of the page.
*
* @type Boolean
*/
manageMode : false,
/** /**
* This method initializes the book appointment page. * This method initializes the book appointment page.
* *
* @param {bool} bindEventHandlers (OPTIONAL) Determines wether * @param {bool} bindEventHandlers (OPTIONAL) Determines whether
* the default event handlers will be binded to the dom elements. * the default event handlers will be binded to the dom elements.
* @param {bool} manageMode (OPTIONAL) Determines whether the customer
* is going to make changes to an existing appointment rather than
* booking a new one.
*/ */
initialize : function(bindEventHandlers) { initialize : function(bindEventHandlers, manageMode) {
if (bindEventHandlers == undefined) { if (bindEventHandlers === undefined) {
bindEventHandlers = true; // Default value bindEventHandlers = true; // Default Value
}
if (manageMode === undefined) {
bookAppointment.manageMode = false; // Default Value
} }
// Initialize page's components (tooltips, datepickers etc). // Initialize page's components (tooltips, datepickers etc).
@ -34,7 +48,7 @@ var bookAppointment = {
defaultDate : Date.today(), defaultDate : Date.today(),
onSelect : function(dateText, instance) { onSelect : function(dateText, instance) {
bookAppointment.getAvailableHours(dateText); bookAppointment.getAvailableHours(dateText);
bookAppointment.updateConfirmData(); bookAppointment.updateConfirmFrame();
} }
}); });
@ -43,22 +57,31 @@ var bookAppointment = {
if (bindEventHandlers) { if (bindEventHandlers) {
bookAppointment.bindEventHandlers(); bookAppointment.bindEventHandlers();
} }
// Execute other necessary operations on startup. // If the manage mode is true, the appointments data should be
$('#select-service').trigger('change'); // loaded by default.
if (bookAppointment.manageMode) {
bookAppointment.applyAppointmentData(GlobalVariables.appointmentData,
GlobalVariables.providerData, GlobalVariables.customerData);
} else {
$('#select-service').trigger('change'); // Load the available hours.
}
}, },
/** /**
* This method binds the necessary event handlers * This method binds the necessary event handlers for the book
* for the book appointments page. * appointments page.
*/ */
bindEventHandlers : function() { bindEventHandlers : function() {
/** /**
* Event : Selected Provider "Changed" * Event : Selected Provider "Changed"
*
* Whenever the provider changes the available appointment
* date - time periods must be updated.
*/ */
$('#select-provider').change(function() { $('#select-provider').change(function() {
bookAppointment.getAvailableHours(Date.today().toString('dd-MM-yyyy')); bookAppointment.getAvailableHours(Date.today().toString('dd-MM-yyyy'));
bookAppointment.updateConfirmData(); bookAppointment.updateConfirmFrame();
}); });
/** /**
@ -71,21 +94,21 @@ var bookAppointment = {
var currServiceId = $('#select-service').val(); var currServiceId = $('#select-service').val();
$('#select-provider').empty(); $('#select-provider').empty();
$.each(GlobalVariables.providers, function(indexProvider, provider) { $.each(GlobalVariables.availableProviders, function(indexProvider, provider) {
$.each(provider['services'], function(indexService, serviceId) { $.each(provider['services'], function(indexService, serviceId) {
// If the current provider is able to provide the selected // If the current provider is able to provide the selected service,
// service, add him to the listbox. // add him to the listbox.
if (serviceId == currServiceId) { if (serviceId == currServiceId) {
var optionHtml = '<option value="' + provider['id'] + '">' var optionHtml = '<option value="' + provider['id'] + '">'
+ provider['last_name'] + ' ' + provider['first_name'] + provider['last_name'] + ' ' + provider['first_name']
+ '</option>'; + '</option>';
$('#select-provider').append(optionHtml); $('#select-provider').append(optionHtml);
} }
}); });
}); });
bookAppointment.getAvailableHours(Date.today().toString('dd-MM-yyyy')); bookAppointment.getAvailableHours(Date.today().toString('dd-MM-yyyy'));
bookAppointment.updateConfirmData(); bookAppointment.updateConfirmFrame();
}); });
/** /**
@ -101,9 +124,10 @@ var bookAppointment = {
if ($(this).attr('data-step_index') === '2') { if ($(this).attr('data-step_index') === '2') {
if ($('.selected-hour').length == 0) { if ($('.selected-hour').length == 0) {
if ($('#select-hour-prompt').length == 0) { if ($('#select-hour-prompt').length == 0) {
$('#available-hours').append('<br><br><strong id="select-hour-prompt"' $('#available-hours').append('<br><br>'
+ ' class="text-error">Please select an appointment hour before ' + '<strong id="select-hour-prompt" class="text-error">'
+ 'continuing!</strong>'); + 'Please select an appointment hour before continuing!'
+ '</strong>');
} }
return; return;
} }
@ -112,10 +136,10 @@ var bookAppointment = {
// If we are on the 3rd tab then we will need to validate the user's // If we are on the 3rd tab then we will need to validate the user's
// input before proceeding to the next step. // input before proceeding to the next step.
if ($(this).attr('data-step_index') === '3') { if ($(this).attr('data-step_index') === '3') {
if (!bookAppointment.validateCustomerDataForm()) { if (!bookAppointment.validateCustomerForm()) {
return; // Validation failed, do not continue. return; // Validation failed, do not continue.
} else { } else {
bookAppointment.updateConfirmData(); bookAppointment.updateConfirmFrame();
} }
} }
@ -125,7 +149,7 @@ var bookAppointment = {
$(this).parents().eq(1).hide('fade', function() { $(this).parents().eq(1).hide('fade', function() {
$('.active-step').removeClass('active-step'); $('.active-step').removeClass('active-step');
$('#step-' + nextTabIndex).addClass('active-step'); $('#step-' + nextTabIndex).addClass('active-step');
$('#book-appointment-' + nextTabIndex).show('fade'); $('#wizard-frame-' + nextTabIndex).show('fade');
}); });
}); });
@ -141,7 +165,7 @@ var bookAppointment = {
$(this).parents().eq(1).hide('fade', function() { $(this).parents().eq(1).hide('fade', function() {
$('.active-step').removeClass('active-step'); $('.active-step').removeClass('active-step');
$('#step-' + prevTabIndex).addClass('active-step'); $('#step-' + prevTabIndex).addClass('active-step');
$('#book-appointment-' + prevTabIndex).show('fade'); $('#wizard-frame-' + prevTabIndex).show('fade');
}); });
}); });
@ -154,7 +178,7 @@ var bookAppointment = {
$('#available-hours').on('click', '.available-hour', function() { $('#available-hours').on('click', '.available-hour', function() {
$('.selected-hour').removeClass('selected-hour'); $('.selected-hour').removeClass('selected-hour');
$(this).addClass('selected-hour'); $(this).addClass('selected-hour');
bookAppointment.updateConfirmData(); bookAppointment.updateConfirmFrame();
}); });
}, },
@ -169,24 +193,31 @@ var bookAppointment = {
// Find the selected service duration (it is going to // Find the selected service duration (it is going to
// be send within the "postData" object. // be send within the "postData" object.
var selServiceDuration = 15; // Default value of duration (in minutes). var selServiceDuration = 15; // Default value of duration (in minutes).
$.each(GlobalVariables.services, function(index, service) { $.each(GlobalVariables.availableServices, function(index, service) {
if (service['id'] == $('#select-service').val()) { if (service['id'] == $('#select-service').val()) {
selServiceDuration = service['duration']; selServiceDuration = service['duration'];
} }
}); });
// If the manage mode is true then the appointment's start
// date should return as available too.
var appointmentId = (bookAppointment.manageMode)
? GlobalVariables.appointmentData['id'] : undefined;
var postData = { var postData = {
'service_id' : $('#select-service').val(), 'service_id' : $('#select-service').val(),
'provider_id' : $('#select-provider').val(), 'provider_id' : $('#select-provider').val(),
'selected_date' : selDate, 'selected_date' : selDate,
'service_duration' : selServiceDuration 'service_duration' : selServiceDuration,
'manage_mode' : bookAppointment.manageMode,
'appointment_id' : appointmentId
}; };
// Make ajax post request and get the available hours. // Make ajax post request and get the available hours.
var ajaxurl = GlobalVariables.baseUrl + 'appointments/ajax_get_available_hours'; var ajaxurl = GlobalVariables.baseUrl + 'appointments/ajax_get_available_hours';
jQuery.post(ajaxurl, postData, function(postResponse) { jQuery.post(ajaxurl, postData, function(postResponse) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
console.log('\n\n Get Available Hours Post Response :', postResponse, '\n\n'); //console.log('\n\n Get Available Hours Post Response :', postResponse, '\n\n');
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
try { try {
@ -199,27 +230,32 @@ var bookAppointment = {
// Fill the available time div // Fill the available time div
var currColumn = 1; var currColumn = 1;
$('#available-hours').html('<div style="width:50px; float:left;"></div>'); $('#available-hours').html('<div style="width:50px; float:left;"></div>');
$.each(jsonResponse, function(index, availableHour) { $.each(jsonResponse, function(index, availableHour) {
if ((currColumn * 10) < (index + 1)) { if ((currColumn * 10) < (index + 1)) {
currColumn++; currColumn++;
$('#available-hours').append('<div style="width:50px; float:left;"></div>'); $('#available-hours')
.append('<div style="width:50px; float:left;"></div>');
} }
$('#available-hours div:eq(' + (currColumn - 1) + ')') $('#available-hours div:eq(' + (currColumn - 1) + ')')
.append('<span class="available-hour">' + availableHour + '</span><br/>'); .append('<span class="available-hour">' + availableHour
+ '</span><br/>');
}); });
// Set the first item as selected. // Set the first item as selected.
$('.available-hour:eq(0)').addClass('selected-hour'); $('.available-hour:eq(0)').addClass('selected-hour');
bookAppointment.updateConfirmData(); bookAppointment.updateConfirmFrame();
} else { } else {
$('#available-hours').text('There are not available appointment hours for ' $('#available-hours').text('There are no available appointment'
+ 'the selected date. Please choose another date.'); + 'hours for the selected date. Please choose another '
+ 'date.');
} }
} catch(exception) { } catch(exception) {
GeneralFunctions.displayMessageBox('Unexpected Error', 'An unexpected error occured ' GeneralFunctions.displayMessageBox('Unexpected Error', 'An unexpected'
+ 'during the available hours calculation. Please refresh the page and try again.'); + 'error occured during the available hours calculation. Please'
+ 'refresh the page and try again.');
} }
}); });
}, },
@ -230,7 +266,7 @@ var bookAppointment = {
* *
* @return {bool} Returns the validation result. * @return {bool} Returns the validation result.
*/ */
validateCustomerDataForm : function() { validateCustomerForm : function() {
var validationResult = true; var validationResult = true;
$('.required').css('border', ''); $('.required').css('border', '');
@ -249,7 +285,7 @@ var bookAppointment = {
* page with the latest customer settigns and input for the appointment * page with the latest customer settigns and input for the appointment
* booking. * booking.
*/ */
updateConfirmData : function() { updateConfirmFrame : function() {
/*** SET APPOINTMENT INFO ***/ /*** SET APPOINTMENT INFO ***/
var selectedDate = $('#select-date').datepicker('getDate'); var selectedDate = $('#select-date').datepicker('getDate');
if (selectedDate !== null) { if (selectedDate !== null) {
@ -308,7 +344,7 @@ var bookAppointment = {
// Find selected service duration. // Find selected service duration.
var selServiceDuration = undefined; var selServiceDuration = undefined;
$.each(GlobalVariables.services, function(index, service) { $.each(GlobalVariables.availableServices, function(index, service) {
if (service.id == $('#select-service').val()) { if (service.id == $('#select-service').val()) {
selServiceDuration = service.duration; selServiceDuration = service.duration;
return; // Stop searching ... return; // Stop searching ...
@ -328,5 +364,47 @@ var bookAppointment = {
} }
return endDatetime.toString('yyyy-MM-dd HH:mm:ss'); return endDatetime.toString('yyyy-MM-dd HH:mm:ss');
},
/**
* This method applies the appointment's data to the wizard so
* that the user can start making changes on an existing record.
*
* @param {object} appointmentData Selected appointment's data.
* @param {object} providerData Selected provider's data.
* @param {object} customerData Selected customer's data.
* @returns {bool} Returns the operation result.
*/
applyAppointmentData : function(appointmentData, providerData, customerData) {
try {
// Select Service & Provider
$('#select-service').val(appointmentData['id_services']);
$('#select-provider').val(appointmentData['id_users_provider']);
// Set Appointment Date
$('.available-hour').removeClass('selected-hour');
$('.available-hour').filter(function() {
return $(this).text() === Date.parseExact(appointmentData['start_datetime'],
'yyyy-MM-dd HH:mm').toString('HH:mm');
}).addClass('selected-hour');
// Apply Customer's Data
$('last-name').val(customerData['last_name']);
$('first-name').val(customerData['first_name']);
$('email').val(customerData['email']);
$('phone-number').val(customerData['phone_number']);
$('address').val(customerData['address']);
$('city').val(customerData['city']);
$('zip-code').val(customerData['zip_code']);
$('notes').text(customerData['notes']);
bookAppointment.updateConfirmFrame();
return true;
} catch(exc) {
console.log(exc);
return false;
}
} }
} }

View file

@ -82,4 +82,24 @@ GeneralFunctions.centerElementOnPage = function(elementHandle) {
}); });
}); });
$(window).resize(); $(window).resize();
}
/**
* This function retrieves a parameter from a "GET" formed url.
*
* @link http://www.netlobo.com/url_query_string_javascript.html
*
* @param {string} url The selected url.
* @param {string} name The parameter name.
* @returns {String} Returns the parameter value.
*/
GeneralFunctions.getUrlParameter = function(url, parameterName) {
parameterName = parameterName.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\#&]"+parameterName+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( url );
if( results == null )
return "";
else
return results[1];
} }