- Χρήση της κλάσης phpmailer για την αποστολή email

- Δημιουργία email templates για τις τρέχουσες ειδοποιήσεις.
This commit is contained in:
alextselegidis@gmail.com 2013-05-17 13:09:10 +00:00
parent 8f573725b9
commit deab8b490d
80 changed files with 273 additions and 216 deletions

View file

@ -1,5 +1,8 @@
Vesrion 0.1
VERSION 0.2
===========
Includes an implementation of the basic flow for
the appointment reservation use case and unit testing
for the model classes of the system.
- Use the PHPMailer class for sending HTML emails.
- Includes complete Google Sync protocol.
- Customers can book appointments only for the available hours.
- Generation of code documentation.
- Unit test the controller classes.
- Minor Fixes

View file

@ -10,14 +10,14 @@ class Appointments extends CI_Controller {
// Display the appointment booking page to the customer.
// Get business name.
$this->load->model('Settings_Model');
$view_data['business_name'] = $this->Settings_Model->get_setting('business_name');
$view_data['company_name'] = $this->Settings_Model->get_setting('company_name');
// Get the available services and providers.
$this->load->model('Services_Model');
$view_data['available_services'] = $this->Services_Model->get_available_services();
$this->load->model('Providers_Model');
$view_data['available_providers'] = $this->Providers_Model->get_available_providers(); // Provider rows contain an array of which services they can provide.
$view_data['available_providers'] = $this->Providers_Model->get_available_providers();
// Load the book appointment view.
$this->load->view('appointments/book', $view_data);
@ -35,8 +35,15 @@ class Appointments extends CI_Controller {
// Send an email to the customer with the appointment info.
$this->load->library('Notifications');
$this->notifications->send_book_success($post_data['customer'], $post_data['appointment']);
$this->notifications->send_new_appointment($post_data['customer'], $post_data['appointment']);
try {
$this->notifications->send_book_success($post_data['customer'], $post_data['appointment']);
$this->notifications->send_new_appointment($post_data['customer'], $post_data['appointment']);
} catch (NotificationException $not_exc) {
$view_data['notification_error'] = '<br><br><pre>An unexpected error occured while sending '
. 'you an 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.
$this->load->view('appointments/book_success', $view_data);
@ -100,8 +107,9 @@ class Appointments extends CI_Controller {
$view_data['message'] = 'Your appointment has been successfully added to Google Calendar!';
$view_data['image'] = 'success.png';
} catch (Exception $exc) {
$view_data['message'] = 'An unexpected error occured during the sync operation: <br/><pre>' . $exc->getMessage()
. '<br/>' . $exc->getTraceAsString() . '</pre>';
$view_data['message'] = 'An unexpected error occured during the sync '
. 'operation: <br/><pre>' . $exc->getMessage() . '<br/>'
. $exc->getTraceAsString() . '</pre>';
$view_data['image'] = 'error.png';
}

View file

@ -22,7 +22,8 @@ class Google extends CI_Controller {
session_start();
if (isset($_SESSION['sync_appointment_id'])) {
header('Location: ' . $this->config->base_url() . 'appointments/google_sync/' . $_SESSION['sync_appointment_id'] . '?code=' . $_GET['code']);
header('Location: ' . $this->config->base_url() . 'appointments/google_sync/'
. $_SESSION['sync_appointment_id'] . '?code=' . $_GET['code']);
} else {
echo 'An error occured during the Google Calendar API authorization process.';
}

View file

@ -10,5 +10,10 @@ class DatabaseException extends Exception {}
*/
class ValidationException extends Exception {}
/**
* Notification Exception Class
*/
class NotificationException extends Exception {}
/* End of file exception_types_helper.php */
/* Location: ./application/helpers/exception_types_helper.php */

View file

@ -1,8 +1,8 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
// Google API PHP Client is necessary to perform sync operations.
require_once dirname(__FILE__) . '/google-api-php-client/Google_Client.php';
require_once dirname(__FILE__) . '/google-api-php-client/contrib/Google_CalendarService.php';
require_once dirname(__FILE__) . '/external/google-api-php-client/Google_Client.php';
require_once dirname(__FILE__) . '/external/google-api-php-client/contrib/Google_CalendarService.php';
require_once dirname(dirname(dirname(__FILE__))) . '/configuration.php';
class Google_Sync {
@ -55,7 +55,8 @@ class Google_Sync {
if (isset($_GET['code'])) {
$this->client->authenticate($_GET['code']);
$_SESSION['google_api_token'] = $this->client->getAccessToken();
header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']); // refreshes current url
header('Location: http://' . $_SERVER['HTTP_HOST']
. $_SERVER['PHP_SELF']); // refreshes current url
}
// If there is an active token then assign it to the client object.
@ -109,7 +110,7 @@ class Google_Sync {
$event = new Google_Event();
$event->setSummary($service['name']);
$event->setLocation($CI->Settings_Model->get_setting('business_name'));
$event->setLocation($CI->Settings_Model->get_setting('company_name'));
$start = new Google_EventDateTime();
$start->setDateTime(date3339(strtotime($appointment['start_datetime'])));

View file

@ -1,7 +1,6 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
define('EMAIL_HEADER_MIME_VERSION', 'MIME-Version: 1.0' . "\r\n");
define('EMAIL_HEADER_CONTENT_TYPE', 'Content-type: text/html; charset=utf-8' . "\r\n");
require_once dirname(__FILE__) . '/external/class.phpmailer.php';
/**
* This library handles all the notification email deliveries
@ -11,17 +10,43 @@ define('EMAIL_HEADER_CONTENT_TYPE', 'Content-type: text/html; charset=utf-8' . "
* during the execution of the class methods.
*/
class Notifications {
private $CI;
/**
* Class Constructor
*/
public function __construct() {
public function __construct() {
$this->CI =& get_instance();
}
/**
* Replace the email template variables.
*
* This method finds and replaces the html variables of an email
* template. It is used to generate dynamic HTML emails that are
* send as notifications to the system users.
*
* @param array $replace_array Array that contains the variables
* to be replaced.
* @param string $email_html The email template hmtl.
* @return string Returns the new email html that contain the variables
* of the $replace_array.
*/
private function replace_template_variables($replace_array, $email_html) {
foreach($replace_array as $var=>$value) {
$email_html = str_replace($var, $value, $email_html);
}
return $email_html;
}
/**
* Send a success email to the customer that booked
* a new appointment.
*
* @expectedException NotificationException Raises when an unexpected
* error has occured when the email is send.
*
* @param array $customer_data Associative array with the customer's
* data. Each key has the same name as the corresponding field in db.
* @param array $appointment_data Associative array with the appointment's
@ -29,96 +54,50 @@ class Notifications {
* @return bool Returns the operation result.
*/
public function send_book_success($customer_data, $appointment_data) {
$CI =& get_instance();
$CI->load->model('Providers_Model');
$CI->load->model('Services_Model');
$this->CI->load->model('Providers_Model');
$this->CI->load->model('Services_Model');
$this->CI->load->model('Settings_Model');
$html = '
<html>
<head>
<title>Appointment Book Success!</title>
</head>
<body>
<h2>Your appointment has been successfully booked!</h2>
<strong>Appointment Details</strong>
<table>
<tr>
<td>Service</td>
<td>: ' . $CI->Services_Model->get_value('name', $appointment_data['id_services']) . '</td>
</tr>
<tr>
<td>Provider</td>
<td>: ' . $CI->Providers_Model->get_value('last_name', $appointment_data['id_users_provider']) . ' ' . $CI->Providers_Model->get_value('first_name', $appointment_data['id_users_provider']) . '</td>
</tr>
<tr>
<td>Start Date</td>
<td>: ' . date('d/m/Y H:i', strtotime($appointment_data['start_datetime'])) . '</td>
</tr>
<tr>
<td>Duration</td>
<td>: ' . $CI->Services_Model->get_value('duration', $appointment_data['id_services']) . ' minutes</td>
</tr>
</table>
<br/><br/>
<strong>Customer Details</strong>
<table>
<tr>
<td>Name</td>
<td>: ' . $customer_data['last_name'] . ' ' . $customer_data['first_name'] . '</td>
</tr>
<tr>
<td>Email</td>
<td>: ' . $customer_data['email'] . '</td>
</tr>
<tr>
<td>Phone</td>
<td>: ' . $customer_data['phone_number'] . '</td>
</tr>
<tr>
<td>Address</td>
<td>: ' . $customer_data['address'] . ', ' . $customer_data['city'] . ', ' . $customer_data['zip_code'] . '</td>
</tr>
</table>
</body>
</html>';
$provider_data = $this->CI->Providers_Model->get_row($appointment_data['id_users_provider']);
$service_data = $this->CI->Services_Model->get_row($appointment_data['id_services']);
// Send email to the customer
$to = $customer_data['email'];
$replace_array = array(
'$appointment_service' => $service_data['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_duration' => $service_data['duration'] . ' minutes',
'$company_link' => $this->CI->Settings_Model->get_setting('company_link'),
'$company_name' => $this->CI->Settings_Model->get_setting('company_name'),
'$customer_name' => $customer_data['first_name'] . ' ' . $customer_data['last_name']
);
$CI->load->model('Settings_Model');
$from_email = $CI->Settings_Model->get_setting('business_email');
$from_name = $CI->Settings_Model->get_setting('business_name');
$email_html = file_get_contents(dirname(dirname(__FILE__)) . '/views/emails/book_success.php');
$email_html = $this->replace_template_variables($replace_array, $email_html);
$subject = 'Appointment Book Success!';
$headers = $this->get_email_headers($customer_data['last_name'] . ' ' . $customer_data['first_name'], $customer_data['email'], $from_name, $from_email);
$mail = new PHPMailer();
$mail->From = $this->CI->Settings_Model->get_setting('company_email');
$mail->FromName = $this->CI->Settings_Model->get_setting('company_name');
$mail->AddAddress($customer_data['email']); // Do not use the name argument, phpmailer crushes.
$mail->IsHTML(true);
$mail->CharSet = 'UTF-8';
$mail->Subject = 'Appointment Book Success!';
$mail->Body = $email_html;
if(!$mail->Send()) {
throw new NotificationException('Email could not been sent. '
. 'Mailer Error (' . __LINE__ . '): ' . $mail->ErrorInfo);
}
return mail($to, $subject, $html, $headers);
}
/**
* Create the email headers.
*
* This method cretes the email header depending the sender and
* the receiver.
*
* @param type $to_name Receiver's name
* @param type $to_email Receiver's email address
* @param type $from_name Sender's name
* @param type $from_email Sender's email
* @return string Returns the email headers.
*/
private function get_email_headers($to_name, $to_email, $from_name, $from_email) {
$headers = EMAIL_HEADER_MIME_VERSION;
$headers .= EMAIL_HEADER_CONTENT_TYPE;
$headers .= 'To: ' . $to_name . ' <' . $to_email . '>' . "\r\n";
$headers .= 'From: ' . $from_name . ' <' . $from_email . '>' . "\r\n";
return $headers;
return TRUE;
}
/**
* Send an email notification to a provider that
* a new appointment has been added to his plan.
*
* @expectedException NotificationException Raises when an unexpected
* error has occured when the email is send.
*
* @param array $customer_data Associative array with the customer's
* data. Each key has the same name as the corresponding field in db.
* @param array $appointment_data Associative array with the appointment's
@ -126,71 +105,45 @@ class Notifications {
* @return bool Returns the operation result.
*/
public function send_new_appointment($customer_data, $appointment_data) {
$CI =& get_instance();
$CI->load->model('Providers_Model');
$CI->load->model('Services_Model');
$this->CI =& get_instance();
$this->CI->load->model('Providers_Model');
$this->CI->load->model('Services_Model');
$this->CI->load->model('Settings_Model');
$html = '
<html>
<head>
<title>A new appointment has been added to your plan.</title>
</head>
<body>
<h2>A new appointment has been added to your plan.</h2>
<strong>Appointment Details</strong>
<table>
<tr>
<td>Service</td>
<td>: ' . $CI->Services_Model->get_value('name', $appointment_data['id_services']) . '</td>
</tr>
<tr>
<td>Provider</td>
<td>: ' . $CI->Providers_Model->get_value('last_name', $appointment_data['id_users_provider']) . ' ' . $CI->Providers_Model->get_value('first_name', $appointment_data['id_users_provider']) . '</td>
</tr>
<tr>
<td>Start Date</td>
<td>: ' . date('d/m/Y H:i', strtotime($appointment_data['start_datetime'])) . '</td>
</tr>
<tr>
<td>Duration</td>
<td>: ' . $CI->Services_Model->get_value('duration', $appointment_data['id_services']) . ' minutes</td>
</tr>
</table>
<br/><br/>
<strong>Customer Details</strong>
<table>
<tr>
<td>Name</td>
<td>: ' . $customer_data['last_name'] . ' ' . $customer_data['first_name'] . '</td>
</tr>
<tr>
<td>Email</td>
<td>: ' . $customer_data['email'] . '</td>
</tr>
<tr>
<td>Phone</td>
<td>: ' . $customer_data['phone_number'] . '</td>
</tr>
<tr>
<td>Address</td>
<td>: ' . $customer_data['address'] . ', ' . $customer_data['city'] . ', ' . $customer_data['zip_code'] . '</td>
</tr>
</table>
</body>
</html>';
$provider_data = $this->CI->Providers_Model->get_row($appointment_data['id_users_provider']);
$service_data = $this->CI->Services_Model->get_row($appointment_data['id_services']);
$replace_array = array(
'$appointment_service' => $service_data['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_duration' => $service_data['duration'] . ' minutes',
'$company_link' => $this->CI->Settings_Model->get_setting('company_link'),
'$company_name' => $this->CI->Settings_Model->get_setting('company_name'),
'$customer_name' => $customer_data['first_name'] . ' ' . $customer_data['last_name'],
'$customer_email' => $customer_data['email'],
'$customer_phone' => $customer_data['phone_number'],
'$customer_address' => $customer_data['address']
);
// Send email to the customer
$provider_email = $CI->Providers_Model->get_value('email', $appointment_data['id_users_provider']);
$provider_nicename = $CI->Providers_Model->get_value('last_name', $appointment_data['id_users_provider']) . ' ' . $CI->Providers_Model->get_value('first_name', $appointment_data['id_users_provider']);
$email_html = file_get_contents(dirname(dirname(__FILE__)) . '/views/emails/new_appointment.php');
$email_html = $this->replace_template_variables($replace_array, $email_html);
$CI->load->model('Settings_Model');
$from_email = $CI->Settings_Model->get_setting('business_email');
$from_name = $CI->Settings_Model->get_setting('business_name');
$mail = new PHPMailer();
$mail->From = $this->CI->Settings_Model->get_setting('company_email');
$mail->FromName = $this->CI->Settings_Model->get_setting('company_name');;
$mail->AddAddress($provider_data['email']); // Do not use the name argument, phpmailer crushes.
$mail->IsHTML(true);
$mail->CharSet = 'UTF-8';
$mail->Subject = 'New Appointment';
$mail->Body = $email_html;
if(!$mail->Send()) {
throw new NotificationException('Email could not been sent. '
. 'Mailer Error (Line ' . __LINE__ . '): ' . $mail->ErrorInfo);
}
$subject = 'A new appointment has been added to your plan.';
$headers = $this->get_email_headers($provider_nicename, $provider_email, $from_name, $from_email);
return mail($provider_email, $subject, $html, $headers);
return TRUE;
}
}

View file

@ -212,7 +212,7 @@ class Appointments_Model extends CI_Model {
* @return bool Returns the delete operation result.
*/
public function delete($appointment_id) {
if (!is_int($appointment_id)) {
if (!is_numeric($appointment_id)) {
throw new InvalidArgumentException('Invalid argument type $appointment_id : ' . $appointment_id);
}
@ -235,7 +235,7 @@ class Appointments_Model extends CI_Model {
* field names.
*/
public function get_row($appointment_id) {
if (!is_int($appointment_id)) {
if (!is_numeric($appointment_id)) {
throw new InvalidArgumentException('Invalid argument given. Expected integer for the $appointment_id : ' . $appointment_id);
}
return $this->db->get_where('ea_appointments', array('id' => $appointment_id))->row_array();
@ -250,7 +250,7 @@ class Appointments_Model extends CI_Model {
* @return string Returns the records value from the database.
*/
public function get_value($field_name, $appointment_id) {
if (!is_int($appointment_id)) {
if (!is_numeric($appointment_id)) {
throw new InvalidArgumentException('Invalid argument given, expected integer for the $appointment_id : ' . $appointment_id);
}

View file

@ -193,7 +193,7 @@ class Customers_Model extends CI_Model {
* @return bool Returns the delete operation result.
*/
public function delete($customer_id) {
if (!is_int($customer_id)) {
if (!is_numeric($customer_id)) {
throw new InvalidArgumentException('Invalid argument type $customer_id : ' . $customer_id);
}
@ -215,7 +215,7 @@ class Customers_Model extends CI_Model {
* field names.
*/
public function get_row($customer_id) {
if (!is_int($customer_id)) {
if (!is_numeric($customer_id)) {
throw new InvalidArgumentException('Invalid argument provided as $customer_id : ' . $customer_id);
}
return $this->db->get_where('ea_users', array('id' => $customer_id))->row_array();
@ -230,7 +230,7 @@ class Customers_Model extends CI_Model {
* @return string Returns the records value from the database.
*/
public function get_value($field_name, $customer_id) {
if (!is_int($customer_id)) {
if (!is_numeric($customer_id)) {
throw new InvalidArgumentException('Invalid argument provided as $customer_id : ' . $customer_id);
}

View file

@ -17,7 +17,7 @@ class Providers_Model extends CI_Model {
* field names.
*/
public function get_row($provider_id) {
if (!is_int($provider_id)) {
if (!is_numeric($provider_id)) {
throw new InvalidArgumentException('$provider_id argument is not an integer : ' . $provider_id);
}
return $this->db->get_where('ea_users', array('id' => $provider_id))->row_array();
@ -32,7 +32,7 @@ class Providers_Model extends CI_Model {
* @return string Returns the records value from the database.
*/
public function get_value($field_name, $provider_id) {
if (!is_int($provider_id)) {
if (!is_numeric($provider_id)) {
throw new InvalidArgumentException('Invalid argument provided as $customer_id : ' . $provider_id);
}

View file

@ -16,7 +16,7 @@ class Services_Model extends CI_Model {
* field names.
*/
public function get_row($service_id) {
if (!is_int($service_id)) {
if (!is_numeric($service_id)) {
throw new InvalidArgumentException('$service_id argument is not an integer : ' . $service_id);
}
return $this->db->get_where('ea_services', array('id' => $service_id))->row_array();
@ -31,7 +31,7 @@ class Services_Model extends CI_Model {
* @return string Returns the records value from the database.
*/
public function get_value($field_name, $service_id) {
if (!is_int($service_id)) {
if (!is_numeric($service_id)) {
throw new InvalidArgumentException('Invalid argument provided as $service_id : ' . $service_id);
}

View file

@ -4,23 +4,62 @@
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<?php // INCLUDE CSS FILES ?>
<link rel="stylesheet" type="text/css" href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap.css">
<link rel="stylesheet" type="text/css" href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap-responsive.css">
<link rel="stylesheet" type="text/css" href="<?php echo $this->config->base_url(); ?>assets/css/libs/jquery/jquery-ui.min.css">
<link rel="stylesheet" type="text/css" href="<?php echo $this->config->base_url(); ?>assets/css/libs/jquery/jquery.qtip.min.css">
<link rel="stylesheet" type="text/css" href="<?php echo $this->config->base_url(); ?>assets/css/style.css">
<link
rel="stylesheet"
type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap.css">
<link
rel="stylesheet"
type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap-responsive.css">
<link
rel="stylesheet"
type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/libs/jquery/jquery-ui.min.css">
<link
rel="stylesheet"
type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/libs/jquery/jquery.qtip.min.css">
<link
rel="stylesheet"
type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/style.css">
<?php // INCLUDE JS FILES ?>
<script type="text/javascript" src="<?php echo $this->config->base_url(); ?>assets/js/libs/jquery/jquery.min.js"></script>
<script type="text/javascript" src="<?php echo $this->config->base_url(); ?>assets/js/libs/jquery/jquery-ui.min.js"></script>
<script type="text/javascript" src="<?php echo $this->config->base_url(); ?>assets/js/libs/jquery/jquery.qtip.min.js"></script>
<script type="text/javascript" src="<?php echo $this->config->base_url(); ?>assets/js/libs/bootstrap/bootstrap.min.js"></script>
<script type="text/javascript" src="<?php echo $this->config->base_url(); ?>assets/js/libs/date.js"></script>
<script type="text/javascript" src="<?php echo $this->config->base_url(); ?>assets/js/frontend/book_appointment.js"></script>
<script type="text/javascript" src="<?php echo $this->config->base_url(); ?>assets/js/general_functions.js"></script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/libs/jquery/jquery.min.js">
</script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/libs/jquery/jquery-ui.min.js">
</script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/libs/jquery/jquery.qtip.min.js">
</script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/libs/bootstrap/bootstrap.min.js">
</script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/libs/date.js">
</script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/frontend/book_appointment.js">
</script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/general_functions.js">
</script>
<?php // SET FAVICON FOR PAGE ?>
<link rel="icon" type="image/x-icon" href="<?php echo $this->config->base_url(); ?>assets/images/favicon.ico">
<link
rel="icon"
type="image/x-icon"
href="<?php echo $this->config->base_url(); ?>assets/images/favicon.ico">
<?php // JS GLOBAL VARIABLE DECLARATION ?>
<script type="text/javascript">
@ -45,7 +84,7 @@
<div id="main" class="container">
<div id="book-appointment">
<div id="top-bar">
<span id="business-name"><?php echo $business_name; ?></span>
<span id="business-name"><?php echo $company_name; ?></span>
<div id="book-steps">
<div id="step-1" class="book-step active-step" title="Select Service & Provider">
<strong>1</strong>
@ -72,7 +111,8 @@
<select id="select-service">
<?php
foreach($available_services as $service) {
echo '<option value="' . $service['id'] . '">' . $service['name'] . '</option>';
echo '<option value="' . $service['id'] . '">'
. $service['name'] . '</option>';
}
?>
</select>
@ -83,7 +123,8 @@
</div>
<div class="command-buttons">
<button type="button" id="button-next-1" class="btn button-next btn-primary" data-step_index="1">Next <i class="icon-forward icon-white"></i></button>
<button type="button" id="button-next-1" class="btn button-next btn-primary"
data-step_index="1">Next <i class="icon-forward icon-white"></i></button>
</div>
</div>
@ -102,8 +143,10 @@
</div>
<div class="command-buttons">
<button type="button" id="button-back-2" class="btn button-back" data-step_index="2"><i class="icon-backward"></i> Back</button>
<button type="button" id="button-next-2" class="btn button-next btn-primary" data-step_index="2">Next <i class="icon-forward icon-white"></i></button>
<button type="button" id="button-back-2" class="btn button-back"
data-step_index="2"><i class="icon-backward"></i> Back</button>
<button type="button" id="button-next-2" class="btn button-next btn-primary"
data-step_index="2">Next <i class="icon-forward icon-white"></i></button>
</div>
</div>
@ -146,8 +189,10 @@
</div>
<div class="command-buttons">
<button type="button" id="button-back-3" class="btn button-back" data-step_index="3"><i class="icon-backward"></i> Back</button>
<button type="button" id="button-next-3" class="btn button-next btn-primary" data-step_index="3">Next <i class="icon-forward icon-white"></i></button>
<button type="button" id="button-back-3" class="btn button-back"
data-step_index="3"><i class="icon-backward"></i> Back</button>
<button type="button" id="button-next-3" class="btn button-next btn-primary"
data-step_index="3">Next <i class="icon-forward icon-white"></i></button>
</div>
</div>
@ -161,16 +206,18 @@
</div>
<div class="command-buttons">
<button type="button" id="button-back-4" class="btn button-back" data-step_index="4"><i class="icon-backward"></i> Back</button>
<button type="button" id="button-back-4" class="btn button-back"
data-step_index="4"><i class="icon-backward"></i> Back</button>
<form id="book-appointment-form" style="display:inline-block" method="post">
<button type="submit" class="btn btn-success"><i class="icon-ok icon-white"></i> Confirm</button>
<button type="submit" class="btn btn-success">
<i class="icon-ok icon-white"></i>Confirm</button>
<input type="hidden" name="post_data" />
</form>
</div>
</div>
<div id="frame-footer">
<em>Powered By <a href="https://code.google.com/p/easy-appointments/">Easy!Appointments</a></em>
Powered By <a href="https://code.google.com/p/easy-appointments/">Easy!Appointments</a>
</div>
</div>
</div>

View file

@ -4,14 +4,26 @@
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<?php // INCLUDE JS FILES ?>
<script type="text/javascript" src="<?php echo $this->config->base_url(); ?>assets/js/libs/jquery/jquery.min.js"></script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/libs/jquery/jquery.min.js">
</script>
<?php // INCLUDE CSS FILES ?>
<link rel="stylesheet" type="text/css" href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap.css">
<link rel="stylesheet" type="text/css" href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap-responsive.css">
<link
rel="stylesheet"
type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap.css">
<link
rel="stylesheet"
type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap-responsive.css">
<?php // SET FAVICON FOR PAGE ?>
<link rel="icon" type="image/x-icon" href="<?php echo $this->config->base_url(); ?>assets/images/favicon.ico">
<link
rel="icon"
type="image/x-icon"
href="<?php echo $this->config->base_url(); ?>assets/images/favicon.ico">
<style>
body {
@ -37,9 +49,21 @@
<body>
<div id="success-frame" class="container">
<img id="success-icon" src="<?php echo $this->config->base_url(); ?>assets/images/success.png" />
<h2>Your appointment has been successfully registered.</h2>
<p>An email with the appointment details has been sented to you.</p>
<a id="google-sync" href="<?php echo $this->config->base_url() . 'appointments/google_sync/' . $appointment_id; ?>">Sync with Google Calendar</a>
<a id="google-sync"
href="<?php echo $this->config->base_url() . 'appointments/google_sync/' . $appointment_id; ?>">
Sync with Google Calendar
</a>
<?php
// Display exception message (if any).
if (isset($notification_error)) {
echo $notification_error;
}
?>
</div>
</body>
</html>

View file

@ -4,11 +4,20 @@
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<?php // INCLUDE CSS FILES ?>
<link rel="stylesheet" type="text/css" href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap.css">
<link rel="stylesheet" type="text/css" href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap-responsive.css">
<link
rel="stylesheet"
type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap.css">
<link
rel="stylesheet"
type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap-responsive.css">
<?php // SET FAVICON FOR PAGE ?>
<link rel="icon" type="image/x-icon" href="<?php echo $this->config->base_url(); ?>assets/images/favicon.ico">
<link
rel="icon"
type="image/x-icon"
href="<?php echo $this->config->base_url(); ?>assets/images/favicon.ico">
<style>
body {
@ -33,7 +42,9 @@
</head>
<body>
<div id="message-frame" class="container">
<img id="message-icon" src="<?php echo $this->config->base_url(); ?>assets/images/<?php echo $image; ?>" />
<img
id="message-icon"
src="<?php echo $this->config->base_url(); ?>assets/images/<?php echo $image; ?>" />
<h2>Google Calendar Sync</h2>
<p><?php echo $message; ?></p>
</div>

View file

@ -63,11 +63,12 @@ var bookAppointment = {
$.each(GlobalVariables.providers, function(indexProvider, provider) {
$.each(provider['services'], function(indexService, serviceId) {
if (serviceId == currServiceId) {
if (serviceId === currServiceId) {
// This provider can provide the selected service.
// Add him to the list box.
var optionHtml = '<option value="' + provider['id'] + '">' + provider['last_name']
+ ' ' + provider['first_name'] + '</option>';
var optionHtml = '<option value="' + provider['id'] + '">'
+ provider['last_name'] + ' ' + provider['first_name']
+ '</option>';
$('#select-provider').append(optionHtml);
}
});
@ -83,7 +84,7 @@ var bookAppointment = {
$('.button-next').click(function() {
// If we are on the 3rd tab then we will need to validate the user's
// input.
if ($(this).attr('data-step_index') == 3) {
if ($(this).attr('data-step_index') === 3) {
if (!bookAppointment.validateCustomerDataForm()) {
return; // Do not continue.
} else {
@ -135,7 +136,7 @@ var bookAppointment = {
// for the chosen service and provider.
var selServiceDuration = 15; // Default duration.
$.each(GlobalVariables.services, function(index, service) {
if (service['id'] == $('#select-service').val()) {
if (service['id'] === $('#select-service').val()) {
selServiceDuration = service['duration'];
}
})
@ -177,8 +178,8 @@ var bookAppointment = {
$('.available-hour:eq(0)').addClass('selected-hour');
bookAppointment.updateConfirmData();
} catch(exception) {
GeneralFunctions.displayMessageBox('Unexpected Error', 'An unexpected error occured during '
+ 'the available hours calculation. Please refresh the page and try again.');
GeneralFunctions.displayMessageBox('Unexpected Error', 'An unexpected error occured '
+ 'during the available hours calculation. Please refresh the page and try again.');
}
});
},
@ -194,7 +195,7 @@ var bookAppointment = {
$('.required').css('border', '');
$('.required').each(function() {
if ($(this).val() == '') {
if ($(this).val() === '') {
validationResult = false;
$(this).css('border', '2px solid red');
}
@ -211,14 +212,15 @@ var bookAppointment = {
updateConfirmData : function() {
/*** SET APPOINTMENT INFO ***/
var selectedDate = $('#select-date').datepicker('getDate');
if (selectedDate != null) {
if (selectedDate !== null) {
selectedDate = Date.parse(selectedDate).toString('dd/MM/yyyy');
}
$('#appointment-info').html(
'<h4>' + $('#select-service option:selected').text() + '</h4>' +
$('#select-provider option:selected').text() + '<br/>' +
'<strong class="text-info">' + selectedDate + ' ' + $('.selected-hour').text() + '</strong>'
'<strong class="text-info">' + selectedDate + ' '
+ $('.selected-hour').text() + '</strong>'
);
/*** SET CUSTOMER'S INFO ***/
@ -245,7 +247,8 @@ var bookAppointment = {
};
postData['appointment'] = {
'start_datetime' : $('#select-date').datepicker('getDate').toString('yyyy-MM-dd') + ' ' + $('.selected-hour').text(),
'start_datetime' : $('#select-date').datepicker('getDate').toString('yyyy-MM-dd')
+ ' ' + $('.selected-hour').text() + ':00',
'end_datetime' : bookAppointment.getEndDatetime(),
'notes' : $('#notes').val(),
'id_users_provider' : $('#select-provider').val(),
@ -266,23 +269,24 @@ var bookAppointment = {
var selServiceDuration = undefined;
$.each(GlobalVariables.services, function(index, service) {
if (service.id == $('#select-service').val()) {
if (service.id === $('#select-service').val()) {
selServiceDuration = service.duration;
return; // Stop searching ...
}
});
// Add the duration to the start datetime.
var startDatetime = $('#select-date').datepicker('getDate').toString('MM/dd/yyyy') + ' ' + $('.selected-hour').text();
var startDatetime = $('#select-date').datepicker('getDate').toString('MM/dd/yyyy')
+ ' ' + $('.selected-hour').text();
startDatetime = Date.parseExact(startDatetime, 'MM/dd/yyyy HH:mm');
var endDatetime = undefined;
if (selServiceDuration != undefined && startDatetime != null) {
endDatetime = startDatetime.add({ minutstartDatetimees : parseInt(selServiceDuration) });
if (selServiceDuration !== undefined && startDatetime !== null) {
endDatetime = startDatetime.add({ 'minutes' : parseInt(selServiceDuration) });
} else {
endDatetime = new Date();
}
return endDatetime.toString('yyyy-MM-dd HH:mm');
return endDatetime.toString('yyyy-MM-dd HH:mm:ss');
}
}