- Χρήση της κλάσης phpmailer για την αποστολή email
- Δημιουργία email templates για τις τρέχουσες ειδοποιήσεις.
This commit is contained in:
parent
8f573725b9
commit
deab8b490d
80 changed files with 273 additions and 216 deletions
|
@ -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
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
||||
|
|
|
@ -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.';
|
||||
}
|
||||
|
|
|
@ -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 */
|
|
@ -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'])));
|
||||
|
|
|
@ -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() {
|
||||
$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;
|
||||
|
||||
return mail($to, $subject, $html, $headers);
|
||||
}
|
||||
if(!$mail->Send()) {
|
||||
throw new NotificationException('Email could not been sent. '
|
||||
. 'Mailer Error (' . __LINE__ . '): ' . $mail->ErrorInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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']);
|
||||
|
||||
// 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']);
|
||||
$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']
|
||||
);
|
||||
|
||||
$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/new_appointment.php');
|
||||
$email_html = $this->replace_template_variables($replace_array, $email_html);
|
||||
|
||||
$subject = 'A new appointment has been added to your plan.';
|
||||
$headers = $this->get_email_headers($provider_nicename, $provider_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($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;
|
||||
|
||||
return mail($provider_email, $subject, $html, $headers);
|
||||
if(!$mail->Send()) {
|
||||
throw new NotificationException('Email could not been sent. '
|
||||
. 'Mailer Error (Line ' . __LINE__ . '): ' . $mail->ErrorInfo);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue