Ολοκλήρωση της βασικής ροής της περίπτωσης χρήσης 'Κράτηση Ραντεβού'.
|
@ -3,7 +3,7 @@
|
|||
-- http://www.phpmyadmin.net
|
||||
--
|
||||
-- Φιλοξενητής: localhost
|
||||
-- Χρόνος δημιουργίας: 14 Απρ 2013 στις 19:41:00
|
||||
-- Χρόνος δημιουργίας: 20 Απρ 2013 στις 20:18:59
|
||||
-- Έκδοση διακομιστή: 5.5.24-log
|
||||
-- Έκδοση PHP: 5.4.3
|
||||
|
||||
|
@ -30,7 +30,7 @@ CREATE TABLE IF NOT EXISTS `ea_appointments` (
|
|||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`start_datetime` datetime DEFAULT NULL,
|
||||
`end_datetime` datetime DEFAULT NULL,
|
||||
`comments` text,
|
||||
`notes` text,
|
||||
`id_users_provider` bigint(20) unsigned NOT NULL,
|
||||
`id_users_customer` bigint(20) unsigned NOT NULL,
|
||||
`id_services` bigint(20) unsigned NOT NULL,
|
||||
|
@ -38,7 +38,7 @@ CREATE TABLE IF NOT EXISTS `ea_appointments` (
|
|||
KEY `id_users_customer` (`id_users_customer`),
|
||||
KEY `id_services` (`id_services`),
|
||||
KEY `id_users_provider` (`id_users_provider`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=18 ;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
|
@ -49,6 +49,7 @@ CREATE TABLE IF NOT EXISTS `ea_appointments` (
|
|||
CREATE TABLE IF NOT EXISTS `ea_roles` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(256) DEFAULT NULL,
|
||||
`slug` varchar(256) DEFAULT NULL,
|
||||
`is_admin` tinyint(4) DEFAULT NULL COMMENT '0',
|
||||
`services` int(4) DEFAULT NULL COMMENT '0',
|
||||
`providers` int(4) DEFAULT NULL COMMENT '0',
|
||||
|
@ -56,14 +57,16 @@ CREATE TABLE IF NOT EXISTS `ea_roles` (
|
|||
`notifications` int(4) DEFAULT NULL COMMENT '0',
|
||||
`appointments` int(4) DEFAULT NULL COMMENT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
|
||||
|
||||
--
|
||||
-- Άδειασμα δεδομένων του πίνακα `ea_roles`
|
||||
--
|
||||
|
||||
INSERT INTO `ea_roles` (`id`, `name`, `is_admin`, `services`, `providers`, `customers`, `notifications`, `appointments`) VALUES
|
||||
(1, 'Administrator', 1, 15, 15, 15, 15, 15);
|
||||
INSERT INTO `ea_roles` (`id`, `name`, `slug`, `is_admin`, `services`, `providers`, `customers`, `notifications`, `appointments`) VALUES
|
||||
(1, 'Administrator', 'administrator', 1, 15, 15, 15, 15, 15),
|
||||
(2, 'Provider', 'provider', 0, 0, 0, 15, 0, 15),
|
||||
(3, 'Customer', 'customer', 0, 0, 0, 0, 0, 0);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
|
@ -81,14 +84,43 @@ CREATE TABLE IF NOT EXISTS `ea_services` (
|
|||
`id_service_categories` bigint(20) unsigned DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `id_service_categories` (`id_service_categories`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
|
||||
|
||||
--
|
||||
-- Άδειασμα δεδομένων του πίνακα `ea_services`
|
||||
--
|
||||
|
||||
INSERT INTO `ea_services` (`id`, `name`, `duration`, `price`, `currency`, `description`, `id_service_categories`) VALUES
|
||||
(1, 'General Examination', 20, '50.00', 'euro', 'Sample Description ...', NULL);
|
||||
(1, 'Γενική Εξέταση', 20, '50.00', 'euro', 'Γενική εξέταση του ασθενή.', NULL),
|
||||
(2, 'Εξέταση Καρδιάς', 30, '40.00', 'euro', 'Εξέταση του ασθενή για νοσήματα καρδιάς.', NULL),
|
||||
(3, 'Νευρολογική Εξέταση', 20, '35.00', 'euro', 'Νευρολογική εξέταση του ασθενή.', NULL);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Δομή πίνακα για τον πίνακα `ea_services_providers`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `ea_services_providers` (
|
||||
`id_users` bigint(20) unsigned NOT NULL,
|
||||
`id_services` bigint(20) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id_users`,`id_services`),
|
||||
KEY `id_services` (`id_services`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Άδειασμα δεδομένων του πίνακα `ea_services_providers`
|
||||
--
|
||||
|
||||
INSERT INTO `ea_services_providers` (`id_users`, `id_services`) VALUES
|
||||
(1, 1),
|
||||
(2, 1),
|
||||
(3, 1),
|
||||
(4, 1),
|
||||
(3, 2),
|
||||
(4, 2),
|
||||
(2, 3),
|
||||
(3, 3);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
|
@ -114,14 +146,16 @@ CREATE TABLE IF NOT EXISTS `ea_settings` (
|
|||
`name` varchar(512) DEFAULT NULL,
|
||||
`value` longtext,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
|
||||
|
||||
--
|
||||
-- Άδειασμα δεδομένων του πίνακα `ea_settings`
|
||||
--
|
||||
|
||||
INSERT INTO `ea_settings` (`id`, `name`, `value`) VALUES
|
||||
(1, 'business_name', 'Javation & Co');
|
||||
(1, 'business_name', 'Javation & Co'),
|
||||
(2, 'business_working_hours', '{}'),
|
||||
(3, NULL, NULL);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
|
@ -146,14 +180,17 @@ CREATE TABLE IF NOT EXISTS `ea_users` (
|
|||
`id_roles` bigint(20) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `id_roles` (`id_roles`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=35 ;
|
||||
|
||||
--
|
||||
-- Άδειασμα δεδομένων του πίνακα `ea_users`
|
||||
--
|
||||
|
||||
INSERT INTO `ea_users` (`id`, `username`, `password`, `first_name`, `last_name`, `email`, `mobile_number`, `phone_number`, `address`, `city`, `state`, `zip_code`, `notes`, `id_roles`) VALUES
|
||||
(1, 'admin', 'admin', 'Alex', 'Tselegidis', 'alextselegidis@gmail.com', '123456789', '987654321', 'Pantazopoulou 11', 'Thessaloniki', NULL, '56121', 'This is me making Easy!Appointments', 1);
|
||||
(1, 'admin', 'admin', 'Alex', 'Tselegidis', 'alextselegidis@gmail.com', '123456789', '987654321', 'Pantazopoulou 11', 'Thessaloniki', NULL, '56121', 'This is me making Easy!Appointments', 1),
|
||||
(2, 'provider_1', 'provider_1', 'Γιώργος', 'Παπαδόπουλος', 'prov1@testing.gr', '1212121212', '2121212121', 'John Doe 23', 'Washington DC', NULL, '12345', 'This is a test provider', 2),
|
||||
(3, 'provider_2', 'provider_2', 'Νίκος', 'Αναστασίου', 'prov2@test.gr', '1313133113131', '32132165146', 'Some Street 3', NULL, NULL, NULL, NULL, 2),
|
||||
(4, 'provider_3', 'provider_3', 'Ηρώ', 'Καριοφύλη', 'prov3@test.gr', '239203490', '029340923', 'John Doe 3 ', NULL, NULL, NULL, NULL, 2);
|
||||
|
||||
--
|
||||
-- Περιορισμοί για άχρηστους πίνακες
|
||||
|
@ -173,6 +210,13 @@ ALTER TABLE `ea_appointments`
|
|||
ALTER TABLE `ea_services`
|
||||
ADD CONSTRAINT `ea_services_ibfk_1` FOREIGN KEY (`id_service_categories`) REFERENCES `ea_service_categories` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
--
|
||||
-- Περιορισμοί για πίνακα `ea_services_providers`
|
||||
--
|
||||
ALTER TABLE `ea_services_providers`
|
||||
ADD CONSTRAINT `ea_services_providers_ibfk_1` FOREIGN KEY (`id_users`) REFERENCES `ea_users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
ADD CONSTRAINT `ea_services_providers_ibfk_2` FOREIGN KEY (`id_services`) REFERENCES `ea_services` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
--
|
||||
-- Περιορισμοί για πίνακα `ea_users`
|
||||
--
|
||||
|
|
|
@ -6,19 +6,62 @@ class Appointments extends CI_Controller {
|
|||
* for the customers.
|
||||
*/
|
||||
public function index() {
|
||||
// Get business name.
|
||||
$this->load->model('Settings');
|
||||
$viewData['businessName'] = $this->Settings->getSetting('business_name');
|
||||
if (strtoupper($_SERVER['REQUEST_METHOD']) != 'POST') {
|
||||
// Display the appointment booking page to the customer.
|
||||
// Get business name.
|
||||
$this->load->model('Settings_Model');
|
||||
$viewData['businessName'] = $this->Settings_Model->getSetting('business_name');
|
||||
|
||||
// Get the available services and providers.
|
||||
$this->load->model('Services');
|
||||
$viewData['availableServices'] = $this->Services->getAvailableServices();
|
||||
// Get the available services and providers.
|
||||
$this->load->model('Services_Model');
|
||||
$viewData['availableServices'] = $this->Services_Model->getAvailableServices();
|
||||
|
||||
$this->load->model('Providers');
|
||||
$viewData['availableProviders'] = $this->Providers->getAvailableProviders(); // Provider rows contain an array of which services they can provide.
|
||||
$this->load->model('Providers_Model');
|
||||
$viewData['availableProviders'] = $this->Providers_Model->getAvailableProviders(); // Provider rows contain an array of which services they can provide.
|
||||
|
||||
// Load the book appointment view.
|
||||
$this->load->view('appointments/book', $viewData);
|
||||
// Load the book appointment view.
|
||||
$this->load->view('appointments/book', $viewData);
|
||||
} else {
|
||||
// Add the appointment to the database and display the success
|
||||
// page to the customer.
|
||||
$customerData = array(
|
||||
'first_name' => $_POST['firstName'],
|
||||
'last_name' => $_POST['lastName'],
|
||||
'email' => $_POST['email'],
|
||||
'phone_number' => $_POST['phoneNumber'],
|
||||
'address' => $_POST['address'],
|
||||
'city' => $_POST['city'],
|
||||
'zip_code' => $_POST['zipCode']
|
||||
);
|
||||
|
||||
$this->load->model('Customers_Model');
|
||||
$customerId = $this->Customers_Model->add($customerData);
|
||||
|
||||
$appointmentData = array(
|
||||
'start_datetime' => $_POST['startDatetime'],
|
||||
'end_datetime' => $_POST['endDatetime'],
|
||||
'notes' => $_POST['notes'],
|
||||
'id_users_provider' => $_POST['providerId'],
|
||||
'id_users_customer' => $customerId,
|
||||
'id_services' => $_POST['serviceId'],
|
||||
);
|
||||
|
||||
$this->load->model('Appointments_Model');
|
||||
$this->Appointments_Model->add($appointmentData);
|
||||
|
||||
// Send an email to the customer with the appointment info.
|
||||
$to = $customerData['email'];
|
||||
$subject = 'Appointment Book Success';
|
||||
$message = 'Hi there! Your appointment has been successfully booked.';
|
||||
$headers = 'From: alextselegidis@gmail.com' . "\r\n" .
|
||||
'Reply-To: alextselegidis@gmail.com' . "\r\n" .
|
||||
'X-Mailer: PHP/' . phpversion();
|
||||
|
||||
mail($to, $subject, $message, $headers);
|
||||
|
||||
// Load the book appointment view.
|
||||
$this->load->view('appointments/book-success');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,12 +81,26 @@ class Appointments extends CI_Controller {
|
|||
// For now we just need to return a sample array. Dynamic calculation
|
||||
// will be adding in future development.
|
||||
$startTime = strtotime($_POST['selectedDate'] . ' 08:00') / 60; // Convert to minutes
|
||||
$endTime = strtotime($_POST['selectedDate'] . ' 16:00') / 60; // Convert to minutes
|
||||
$endTime = strtotime($_POST['selectedDate'] . ' 19:00') / 60; // Convert to minutes
|
||||
|
||||
for ($i=0; ($startTime*60 + $i*60)<=($endTime*60); $i+=intval($_POST['serviceDuration'])) {
|
||||
$availableHours[] = date('H:i', $startTime * 60 + $i * 60);
|
||||
}
|
||||
|
||||
// If the selected date is today, remove past hours.
|
||||
if (date('m/d/Y', strtotime($_POST['selectedDate'])) == date('m/d/Y')) {
|
||||
foreach($availableHours as $index=>$value) {
|
||||
$availableHour = date('m/d/Y H:i', strtotime($value));
|
||||
$currentHour = date('m/d/Y H:i');
|
||||
|
||||
if ($availableHour < $currentHour) {
|
||||
unset($availableHours[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$availableHours = array_values($availableHours);
|
||||
|
||||
echo json_encode($availableHours);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
?>
|
36
src/application/models/appointments_model.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
class Appointments_Model extends CI_Model {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function add($appointmentData) {
|
||||
try {
|
||||
if (!$this->exists($appointmentData)) {
|
||||
$this->insert($appointmentData);
|
||||
} else {
|
||||
$this->update($appointmentData);
|
||||
}
|
||||
} catch (Exception $exc) {
|
||||
echo $exc->getTraceAsString();
|
||||
}
|
||||
}
|
||||
|
||||
public function exists($appointmentData) {
|
||||
return false; // @task This check is going to be more complicated than just checking an email (customers model)
|
||||
}
|
||||
|
||||
private function insert($appointmentData) {
|
||||
$this->db->insert('ea_appointments', $appointmentData);
|
||||
}
|
||||
|
||||
private function update($appointmentData) {
|
||||
$this->db->where('id', $appointmentData['id']);
|
||||
$this->db->update('ea_appointments', $appointmentData);
|
||||
}
|
||||
|
||||
public function delete($appointmentId) {
|
||||
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -1,7 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
?>
|
84
src/application/models/customers_model.php
Normal file
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
class Customers_Model extends CI_Model {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method adds a customer to the database. If the customer
|
||||
* already exists then its data are going to be updated.
|
||||
*
|
||||
* @param array $customerData The customer data we want to add.
|
||||
*/
|
||||
public function add($customerData) {
|
||||
try {
|
||||
if (!$this->exists($customerData['email'])) {
|
||||
$this->insert($customerData);
|
||||
} else {
|
||||
$this->update($customerData);
|
||||
}
|
||||
} catch(Exception $exc) {
|
||||
// Send some info for the exception back to the browser.
|
||||
}
|
||||
|
||||
return $this->db->insert_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks if a customer exists on the database.
|
||||
* The unique identifier for a customer is his email.
|
||||
*
|
||||
* @param string $customerEmail The customers email.
|
||||
* @return bool Returns the operation result.
|
||||
*/
|
||||
public function exists($customerEmail) {
|
||||
return false; // @task This should be implemented soon.
|
||||
}
|
||||
|
||||
/**
|
||||
* This method inserts a customer into the database.
|
||||
*
|
||||
* @param array $customerData Associative array with the customers
|
||||
* data. The key of the array should be the same as the database
|
||||
* field names.
|
||||
*/
|
||||
private function insert($customerData) {
|
||||
$this->db
|
||||
->select('id')
|
||||
->from('ea_roles')
|
||||
->where('slug', 'customer');
|
||||
|
||||
$customerRoleId = $this->db->get()->row()->id;
|
||||
|
||||
if ($customerRoleId !== NULL) {
|
||||
$customerData['id_roles'] = $customerRoleId;
|
||||
}
|
||||
|
||||
if (!$this->db->insert('ea_users', $customerData)) {
|
||||
throw new Exception('Could not insert customer to the database.');
|
||||
}
|
||||
}
|
||||
|
||||
private function update($customerData) {
|
||||
$this->db->where('email', $customerData['email']);
|
||||
if (!$this->db->update('ea_users', $customerData)) {
|
||||
throw new Exception('Could not update customer to the database.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deletes a customers from the database.
|
||||
* All his appointmets will be deleted too (automatically
|
||||
* through the foreign key constraint).
|
||||
*
|
||||
* @param int $customerId The id of the customer to be
|
||||
* deleted.
|
||||
*/
|
||||
public function delete($customerId) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
?>
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
class Providers extends CI_Model {
|
||||
class Providers_Model extends CI_Model {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
@ -12,22 +12,21 @@ class Providers extends CI_Model {
|
|||
* data.
|
||||
*/
|
||||
public function getAvailableProviders() {
|
||||
$sql = '
|
||||
SELECT ea_users.*
|
||||
FROM ea_users
|
||||
INNER JOIN ea_roles
|
||||
ON ea_users.id_roles = ea_roles.id
|
||||
WHERE ea_roles.slug = "provider"';
|
||||
$this->db
|
||||
->select('ea_users.*')
|
||||
->from('ea_users')
|
||||
->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner')
|
||||
->where('ea_roles.slug', 'provider');
|
||||
|
||||
$providers = $this->db->query($sql)->result_array();
|
||||
$providers = $this->db->get()->result_array();
|
||||
|
||||
foreach($providers as &$provider) {
|
||||
$sql = '
|
||||
SELECT id_services
|
||||
FROM ea_services_providers
|
||||
WHERE id_users = ' . $this->db->escape($provider['id']);
|
||||
$this->db
|
||||
->select('id_services')
|
||||
->from('ea_services_providers')
|
||||
->where('id_users', $provider['id']);
|
||||
|
||||
$providerServices = $this->db->query($sql)->result_array();
|
||||
$providerServices = $this->db->get()->result_array();
|
||||
|
||||
if (!isset($provider['services'])) {
|
||||
$provider['services'] = array();
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
class Services extends CI_Model {
|
||||
class Services_Model extends CI_Model {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
<?php
|
||||
class Settings extends CI_Model {
|
||||
function __construct()
|
||||
{
|
||||
class Settings_Model extends CI_Model {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
@ -13,8 +12,7 @@ class Settings extends CI_Model {
|
|||
* @return string Returns the database value for
|
||||
* the selected setting.
|
||||
*/
|
||||
function getSetting($name)
|
||||
{
|
||||
function getSetting($name) {
|
||||
$query = $this->db->get_where('ea_settings', array('name' => $name));
|
||||
$setting = ($query->num_rows() > 0) ? $query->row() : '';
|
||||
return $setting->value;
|
||||
|
@ -30,8 +28,7 @@ class Settings extends CI_Model {
|
|||
* @return bool Returns the operation success - failure
|
||||
* result.
|
||||
*/
|
||||
function setSetting($name, $value)
|
||||
{
|
||||
function setSetting($name, $value) {
|
||||
$query = $this->db->get_where('ea_settings', array('name' => $name));
|
||||
if ($query->num_rows() > 0) {
|
||||
// Update setting
|
41
src/application/views/appointments/book-success.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<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">
|
||||
|
||||
<?php // SET FAVICON FOR PAGE ?>
|
||||
<link rel="icon" type="image/x-icon" href="<?php echo $this->config->base_url(); ?>assets/images/favicon.ico">
|
||||
|
||||
<style>
|
||||
body {
|
||||
background-color: #CAEDF3;
|
||||
}
|
||||
|
||||
#success-frame {
|
||||
width: 660px;
|
||||
margin: 150px auto 0 auto;
|
||||
background: #FFF;
|
||||
box-shadow: 0px 1px 1px #B6B6B6;
|
||||
min-height: 197px;
|
||||
padding: 108px 10px;
|
||||
}
|
||||
|
||||
#success-icon {
|
||||
float: left;
|
||||
margin: 0px 26px 0 20px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<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>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -16,150 +16,25 @@
|
|||
<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>
|
||||
|
||||
<?php // SET FAVICON FOR PAGE ?>
|
||||
<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">
|
||||
// Define some global variables.
|
||||
GlobalVariables = {
|
||||
services : <?php echo json_encode($availableServices); ?>,
|
||||
providers : <?php echo json_encode($availableProviders); ?>,
|
||||
baseUrl : '<?php echo $this->config->base_url(); ?>'
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php // JQUERY PAGE STUFF ?>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
var services = <?php echo json_encode($availableServices); ?>;
|
||||
var providers = <?php echo json_encode($availableProviders); ?>;
|
||||
|
||||
// When the user clicks on a service, its available providers should
|
||||
// become visible.
|
||||
$('#select-service').change(function() {
|
||||
var currServiceId = $('#select-service').val();
|
||||
$('#select-provider').empty();
|
||||
|
||||
$.each(providers, function(index, provider) {
|
||||
$.each(provider['services'], function(index, serviceId) {
|
||||
if (serviceId == currServiceId) {
|
||||
// This provider can provide the selected service.
|
||||
// Add him to the list box.
|
||||
var option = new Option(provider['last_name'] + ' ' + provider['first_name'], provider['id']);
|
||||
$('#select-provider').append(option);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
refreshAvailableHours(Date.today().toString('MM/dd/yyyy'));
|
||||
});
|
||||
|
||||
/**
|
||||
* Selected Provider Changed Event Handler
|
||||
*/
|
||||
$('#select-provider').change(function() {
|
||||
refreshAvailableHours(Date.today().toString('MM/dd/yyyy'));
|
||||
});
|
||||
|
||||
$('#select-service').trigger('change');
|
||||
|
||||
$('.book-step').qtip({
|
||||
position: {
|
||||
my: 'top center',
|
||||
at: 'bottom center'
|
||||
},
|
||||
style: {
|
||||
classes: 'qtip-green qtip-shadow custom-qtip'
|
||||
}
|
||||
});
|
||||
|
||||
$('#select-date').datepicker({
|
||||
//dateFormat : 'dd/mm/yy',
|
||||
onSelect : function(dateText, inst) {
|
||||
refreshAvailableHours(dateText);
|
||||
}
|
||||
});
|
||||
|
||||
refreshAvailableHours(Date.today().toString('MM/dd/yyyy'));
|
||||
|
||||
/**
|
||||
* Next Step Button Clicked
|
||||
*/
|
||||
$('.button-next').click(function() {
|
||||
var nextTabIndex = parseInt($(this).attr('data-step_index')) + 1;
|
||||
|
||||
$(this).parents().eq(1).hide('fade', function() {
|
||||
$('.active-step').removeClass('active-step');
|
||||
$('#step-' + nextTabIndex).addClass('active-step');
|
||||
$('#book-appointment-' + nextTabIndex).show('fade');
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Back Step Button Clicked
|
||||
*/
|
||||
$('.button-back').click(function() {
|
||||
var prevTabIndex = parseInt($(this).attr('data-step_index')) - 1;
|
||||
|
||||
$(this).parents().eq(1).hide('fade', function() {
|
||||
$('.active-step').removeClass('active-step');
|
||||
$('#step-' + prevTabIndex).addClass('active-step');
|
||||
$('#book-appointment-' + prevTabIndex).show('fade');
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Available Hour Click Event Handler
|
||||
*/
|
||||
$('#available-hours').on('click', '.available-hour', function() {
|
||||
$('.selected-hour').removeClass('selected-hour');
|
||||
$(this).addClass('selected-hour');
|
||||
});
|
||||
|
||||
/**
|
||||
* This function makes an ajax call and returns the available
|
||||
* hours for the selected service, provider and date.
|
||||
*/
|
||||
function refreshAvailableHours(selDate) {
|
||||
// Fetch the available hours of the current date
|
||||
// for the chosen service and provider.
|
||||
var selServiceDuration = 15; // Default duration.
|
||||
$.each(services, function(index, service) {
|
||||
if (service['id'] == $('#select-service').val()) {
|
||||
selServiceDuration = service['duration'];
|
||||
}
|
||||
})
|
||||
|
||||
var postData = {
|
||||
'serviceId' : $('#select-service').val(),
|
||||
'providerId' : $('#select-provider').val(),
|
||||
'selectedDate' : selDate,
|
||||
'serviceDuration' : selServiceDuration
|
||||
};
|
||||
|
||||
console.log('\n\n Get Available Hours Post Data:', postData, '\n\n');
|
||||
|
||||
// Make ajax post request and get the available hours.
|
||||
var ajaxurl = '<?php echo $this->config->base_url(); ?>index.php/appointments/getAvailableHours';
|
||||
jQuery.post(ajaxurl, postData, function(postResponse) {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
console.log('\n\n Get Available Hours Post Response :', postResponse, '\n\n');
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
try {
|
||||
var jsonResponse = jQuery.parseJSON(postResponse);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
console.log('\n\n Get Available Hours Json Response :', jsonResponse, '\n\n');
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Fill the available time div
|
||||
var currColumn = 1;
|
||||
$('#available-hours').html('<div style="width:50px; float:left;"></div>');
|
||||
$.each(jsonResponse, function(index, availableHour) {
|
||||
if ((currColumn * 10) < (index + 1)) {
|
||||
currColumn++;
|
||||
$('#available-hours').append('<div style="width:50px; float:left;"></div>');
|
||||
}
|
||||
$('#available-hours div:eq(' + (currColumn - 1) + ')')
|
||||
.append('<span class="available-hour">' + availableHour + '</span><br/>');
|
||||
});
|
||||
|
||||
} catch(exception) {
|
||||
// @task Display message to the user.
|
||||
};
|
||||
});
|
||||
}
|
||||
bookAppointment.initialize(); // Begin jquery magic :P
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
@ -188,97 +63,120 @@
|
|||
|
||||
<?php // SELECT SERVICE AND PROVIDER ?>
|
||||
<div id="book-appointment-1" class="book-appoinment-step">
|
||||
<h2>Select Service & Provider</h2>
|
||||
<label for="select-service">Select Service</label>
|
||||
<select id="select-service">
|
||||
<?php
|
||||
foreach($availableServices as $service) {
|
||||
echo '<option value="' . $service['id'] . '">' . $service['name'] . '</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<div class="book-step-content">
|
||||
<h2>Select Service & Provider</h2>
|
||||
<div class="span5">
|
||||
<label for="select-service">Select Service</label>
|
||||
<select id="select-service">
|
||||
<?php
|
||||
foreach($availableServices as $service) {
|
||||
echo '<option value="' . $service['id'] . '">' . $service['name'] . '</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
<label for="select-provider">Select Provider</label>
|
||||
<select id="select-provider"></select>
|
||||
<label for="select-provider">Select Provider</label>
|
||||
<select id="select-provider"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="command-buttons">
|
||||
<button type="button" id="button-next-1" class="btn button-next" data-step_index="1">Next</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>
|
||||
|
||||
<?php // APPOINTMENT DATE ?>
|
||||
<div id="book-appointment-2" class="book-appoinment-step" style="display:none;">
|
||||
<h2>Select Appointment Date And Time</h2>
|
||||
<div class="span3">
|
||||
<div id="select-date"></div>
|
||||
</div>
|
||||
<div class="book-step-content">
|
||||
<h2>Select Appointment Date And Time</h2>
|
||||
<div class="span3">
|
||||
<div id="select-date"></div>
|
||||
</div>
|
||||
|
||||
<div class="span3">
|
||||
<?php // Available hours are going to be fetched via ajax call. ?>
|
||||
<div id="available-hours"></div>
|
||||
<div class="span3">
|
||||
<?php // Available hours are going to be fetched via ajax call. ?>
|
||||
<div id="available-hours"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="command-buttons">
|
||||
<button type="button" id="button-back-2" class="btn button-back" data-step_index="2">Back</button>
|
||||
<button type="button" id="button-next-2" class="btn button-next" data-step_index="2">Next</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>
|
||||
|
||||
<?php // CUSTOMER'S INFO ?>
|
||||
<div id="book-appointment-3" class="book-appoinment-step" style="display:none;">
|
||||
<h2>Fill In Your Information</h2>
|
||||
<div class="book-step-content">
|
||||
<h2>Fill In Your Information</h2>
|
||||
|
||||
<div class="span3">
|
||||
<label for="last-name">Last Name *</label>
|
||||
<input type="text" id="last-name" maxlength="250" />
|
||||
<div class="span3">
|
||||
<label for="last-name">Last Name *</label>
|
||||
<input type="text" id="last-name" class="required" maxlength="250" />
|
||||
|
||||
<label for="first-name">First Name</label>
|
||||
<input type="text" id="first-name" maxlength="100" />
|
||||
<label for="first-name">First Name</label>
|
||||
<input type="text" id="first-name" maxlength="100" />
|
||||
|
||||
<label for="email">Email *</label>
|
||||
<input type="text" id="email" maxlength="250" />
|
||||
<label for="email">Email *</label>
|
||||
<input type="text" id="email" class="required" maxlength="250" />
|
||||
|
||||
<label for="phone-number">Phone Number *</label>
|
||||
<input type="text" id="phone-number" maxlength="60" />
|
||||
</div>
|
||||
<label for="phone-number">Phone Number *</label>
|
||||
<input type="text" id="phone-number" class="required" maxlength="60" />
|
||||
|
||||
<div class="span3">
|
||||
<label for="address">Address</label>
|
||||
<input type="text" id="address" maxlength="250" />
|
||||
<br/><br/>
|
||||
<em class="text-error">Fields with * are mandatory.</em>
|
||||
</div>
|
||||
|
||||
<label for="city">City</label>
|
||||
<input type="text" id="city" maxlength="120" />
|
||||
<div class="span3">
|
||||
<label for="address">Address</label>
|
||||
<input type="text" id="address" maxlength="250" />
|
||||
|
||||
<label for="zip-code">Zip Code</label>
|
||||
<input type="text" id="zip-code" maxlength="120" />
|
||||
<label for="city">City</label>
|
||||
<input type="text" id="city" maxlength="120" />
|
||||
|
||||
<label for="zip-code">Zip Code</label>
|
||||
<input type="text" id="zip-code" maxlength="120" />
|
||||
|
||||
<label for="notes">Notes</label>
|
||||
<textarea id="notes" maxlength="500" rows="4"></textarea>
|
||||
</div>
|
||||
|
||||
<label for="notes">Notes</label>
|
||||
<textarea id="notes" maxlength="500"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="command-buttons">
|
||||
<button type="button" id="button-back-3" class="btn button-back" data-step_index="3">Back</button>
|
||||
<button type="button" id="button-next-3" class="btn button-next" data-step_index="3">Next</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>
|
||||
|
||||
<?php // CONFIRMATION STEP ?>
|
||||
<div id="book-appointment-4" class="book-appoinment-step" style="display:none;">
|
||||
<h2>Confirm Appointment</h2>
|
||||
|
||||
<div id="appointment-info">
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div id="customer-info">
|
||||
<div class="book-step-content">
|
||||
<h2>Confirm Appointment</h2>
|
||||
|
||||
<div id="appointment-info" class="span3"></div>
|
||||
<div id="customer-info" class="span3"></div>
|
||||
</div>
|
||||
|
||||
<div class="command-buttons">
|
||||
<button type="button" id="button-back-4" class="btn button-back" data-step_index="4">Back</button>
|
||||
<form>
|
||||
<button type="submit" class="btn-success">Confirm Appointment</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>
|
||||
|
||||
<input type="hidden" name="lastName" />
|
||||
<input type="hidden" name="firstName" />
|
||||
<input type="hidden" name="email" />
|
||||
<input type="hidden" name="phoneNumber" />
|
||||
<input type="hidden" name="address" />
|
||||
<input type="hidden" name="city" />
|
||||
<input type="hidden" name="zipCode" />
|
||||
|
||||
<input type="hidden" name="startDatetime" />
|
||||
<input type="hidden" name="endDatetime" />
|
||||
<input type="hidden" name="notes" />
|
||||
<input type="hidden" name="providerId" />
|
||||
<input type="hidden" name="serviceId" />
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
4
src/assets/css/libs/bootstrap/bootstrap.css
vendored
|
@ -2282,7 +2282,7 @@ table th[class*="span"],
|
|||
*margin-right: .3em;
|
||||
line-height: 14px;
|
||||
vertical-align: text-top;
|
||||
background-image: url("../../../img/glyphicons-halflings.png");
|
||||
background-image: url("../../../images/glyphicons-halflings.png");
|
||||
background-position: 14px 14px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
@ -2306,7 +2306,7 @@ table th[class*="span"],
|
|||
.dropdown-submenu:focus > a > [class^="icon-"],
|
||||
.dropdown-submenu:hover > a > [class*=" icon-"],
|
||||
.dropdown-submenu:focus > a > [class*=" icon-"] {
|
||||
background-image: url("../../../img/glyphicons-halflings-white.png");
|
||||
background-image: url("../../../images/glyphicons-halflings-white.png");
|
||||
}
|
||||
|
||||
.icon-glass {
|
||||
|
|
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 418 B |
BIN
src/assets/css/libs/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png
Normal file
After Width: | Height: | Size: 212 B |
BIN
src/assets/css/libs/jquery/images/ui-bg_flat_0_eeeeee_40x100.png
Normal file
After Width: | Height: | Size: 220 B |
Before Width: | Height: | Size: 206 B |
Before Width: | Height: | Size: 205 B |
Before Width: | Height: | Size: 220 B |
After Width: | Height: | Size: 208 B |
After Width: | Height: | Size: 208 B |
Before Width: | Height: | Size: 333 B |
Before Width: | Height: | Size: 207 B After Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 336 B |
Before Width: | Height: | Size: 321 B |
Before Width: | Height: | Size: 328 B |
Before Width: | Height: | Size: 252 B |
After Width: | Height: | Size: 277 B |
After Width: | Height: | Size: 351 B |
Before Width: | Height: | Size: 353 B |
After Width: | Height: | Size: 280 B |
Before Width: | Height: | Size: 355 B |
Before Width: | Height: | Size: 328 B |
Before Width: | Height: | Size: 351 B |
Before Width: | Height: | Size: 203 B |
Before Width: | Height: | Size: 203 B |
Before Width: | Height: | Size: 349 B |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 6.8 KiB |
BIN
src/assets/css/libs/jquery/images/ui-icons_454545_256x240.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
BIN
src/assets/css/libs/jquery/images/ui-icons_666666_256x240.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
BIN
src/assets/css/libs/jquery/images/ui-icons_fa6676_256x240.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 6.2 KiB |
6
src/assets/css/libs/jquery/jquery-ui.min.css
vendored
|
@ -38,7 +38,7 @@ body {
|
|||
}
|
||||
|
||||
#book-appointment #book-steps {
|
||||
width: 252px;
|
||||
width: 204px;
|
||||
display: inline-block;
|
||||
float: right;
|
||||
margin-top: 15px;
|
||||
|
@ -46,7 +46,21 @@ body {
|
|||
|
||||
#book-appointment .book-appoinment-step {
|
||||
padding: 10px 20px;
|
||||
height: 363px;
|
||||
height: 434px;
|
||||
}
|
||||
|
||||
#book-appointment .book-appoinment-step .book-step-content {
|
||||
height: 370px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#book-appointment .command-buttons {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#book-appointment .command-buttons .btn {
|
||||
min-width: 80px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
#book-appointment .book-step {
|
||||
|
@ -55,20 +69,34 @@ body {
|
|||
width: 20px;
|
||||
float: left;
|
||||
background: #FFF;
|
||||
padding: 10px;
|
||||
padding: 3px;
|
||||
margin-right: 15px;
|
||||
margin-top: 10px;
|
||||
border: 3px solid #38A07A;
|
||||
}
|
||||
|
||||
#book-appointment .book-step strong {
|
||||
font-size: 25px;
|
||||
font-size: 18px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
color: #B6DFC6;
|
||||
}
|
||||
|
||||
#book-appointment .active-step {
|
||||
display: inline-block;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
float: left;
|
||||
background: #FFF;
|
||||
padding: 10px;
|
||||
margin-right: 15px;
|
||||
margin-top: 0px;
|
||||
border: 3px solid #38A07A;
|
||||
}
|
||||
|
||||
#book-appointment .active-step strong {
|
||||
color: #396946;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
#book-appointment #frame-footer {
|
||||
|
@ -82,6 +110,12 @@ body {
|
|||
border-width: 2px;
|
||||
}
|
||||
|
||||
#available-hours .available-hour {
|
||||
font-size: 15px;
|
||||
padding: 1px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#available-hours .available-hour:hover {
|
||||
font-weight: bold;
|
||||
background-color: #CAEDF3;
|
||||
|
@ -93,3 +127,7 @@ body {
|
|||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#book-appointment .span3 {
|
||||
min-width: 270px; /* This is especially needed for ie8 */
|
||||
}
|
||||
|
|
BIN
src/assets/images/success.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
283
src/assets/js/frontend/book-appointment.js
Normal file
|
@ -0,0 +1,283 @@
|
|||
/**
|
||||
* This class implements the book appointment page functionality.
|
||||
* Once the initialize() method is called the page is fully functional
|
||||
* and can serve the appointment booking process.
|
||||
*
|
||||
* @class Implelements the js part of the appointment booking page.
|
||||
*/
|
||||
var bookAppointment = {
|
||||
/**
|
||||
* This method initializes the book appointment page.
|
||||
*/
|
||||
initialize : function() {
|
||||
// Initialize page components.
|
||||
$('.book-step').qtip({
|
||||
position: {
|
||||
my: 'top center',
|
||||
at: 'bottom center'
|
||||
},
|
||||
style: {
|
||||
classes: 'qtip-green qtip-shadow custom-qtip'
|
||||
}
|
||||
});
|
||||
|
||||
$('#select-date').datepicker({
|
||||
//dateFormat : 'dd/mm/yy',
|
||||
minDate : 0,
|
||||
defaultDate : Date.today(),
|
||||
onSelect : function(dateText, inst) {
|
||||
bookAppointment.refreshAvailableHours(dateText);
|
||||
bookAppointment.updateConfirmData();
|
||||
}
|
||||
});
|
||||
|
||||
// Bind event handlers.
|
||||
bookAppointment.bindEventHandlers();
|
||||
|
||||
// Execute other necessary operations.
|
||||
$('#select-service').trigger('change');
|
||||
},
|
||||
|
||||
/**
|
||||
* This method binds the necessary event handlers
|
||||
* for the book appointments page.
|
||||
*/
|
||||
bindEventHandlers : function() {
|
||||
/**
|
||||
* Event : Selected Provider "Changed"
|
||||
*/
|
||||
$('#select-provider').change(function() {
|
||||
bookAppointment.refreshAvailableHours(Date.today().toString('MM/dd/yyyy'));
|
||||
bookAppointment.updateConfirmData();
|
||||
});
|
||||
|
||||
/**
|
||||
* Event : Selected Service "Changed"
|
||||
*
|
||||
* When the user clicks on a service, its available providers should
|
||||
* become visible.
|
||||
*/
|
||||
$('#select-service').change(function() {
|
||||
var currServiceId = $('#select-service').val();
|
||||
$('#select-provider').empty();
|
||||
|
||||
$.each(GlobalVariables.providers, function(indexProvider, provider) {
|
||||
$.each(provider['services'], function(indexService, serviceId) {
|
||||
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>';
|
||||
$('#select-provider').append(optionHtml);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
bookAppointment.refreshAvailableHours(Date.today().toString('MM/dd/yyyy'));
|
||||
bookAppointment.updateConfirmData();
|
||||
});
|
||||
|
||||
/**
|
||||
* Event : Next Step Button "Clicked"
|
||||
*/
|
||||
$('.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 (!bookAppointment.validateCustomerDataForm()) {
|
||||
return; // Do not continue.
|
||||
} else {
|
||||
bookAppointment.updateConfirmData();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var nextTabIndex = parseInt($(this).attr('data-step_index')) + 1;
|
||||
|
||||
$(this).parents().eq(1).hide('fade', function() {
|
||||
$('.active-step').removeClass('active-step');
|
||||
$('#step-' + nextTabIndex).addClass('active-step');
|
||||
$('#book-appointment-' + nextTabIndex).show('fade');
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Event : Back Step Button "Clicked"
|
||||
*/
|
||||
$('.button-back').click(function() {
|
||||
var prevTabIndex = parseInt($(this).attr('data-step_index')) - 1;
|
||||
|
||||
$(this).parents().eq(1).hide('fade', function() {
|
||||
$('.active-step').removeClass('active-step');
|
||||
$('#step-' + prevTabIndex).addClass('active-step');
|
||||
$('#book-appointment-' + prevTabIndex).show('fade');
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Event : Available Hour "Click"
|
||||
*/
|
||||
$('#available-hours').on('click', '.available-hour', function() {
|
||||
$('.selected-hour').removeClass('selected-hour');
|
||||
$(this).addClass('selected-hour');
|
||||
bookAppointment.updateConfirmData();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* This function makes an ajax call and returns the available
|
||||
* hours for the selected service, provider and date.
|
||||
*
|
||||
* @param {string} selDate The selected date of which the available
|
||||
* hours we need to receive.
|
||||
*/
|
||||
refreshAvailableHours : function(selDate) {
|
||||
// Fetch the available hours of the current date
|
||||
// for the chosen service and provider.
|
||||
var selServiceDuration = 15; // Default duration.
|
||||
$.each(GlobalVariables.services, function(index, service) {
|
||||
if (service['id'] == $('#select-service').val()) {
|
||||
selServiceDuration = service['duration'];
|
||||
}
|
||||
})
|
||||
|
||||
var postData = {
|
||||
'serviceId' : $('#select-service').val(),
|
||||
'providerId' : $('#select-provider').val(),
|
||||
'selectedDate' : selDate,
|
||||
'serviceDuration' : selServiceDuration
|
||||
};
|
||||
|
||||
// Make ajax post request and get the available hours.
|
||||
var ajaxurl = GlobalVariables.baseUrl + 'index.php/appointments/getAvailableHours';
|
||||
jQuery.post(ajaxurl, postData, function(postResponse) {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//console.log('\n\n Get Available Hours Post Response :', postResponse, '\n\n');
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
try {
|
||||
var jsonResponse = jQuery.parseJSON(postResponse);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//console.log('\n\n Get Available Hours JSON Response :', jsonResponse, '\n\n');
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Fill the available time div
|
||||
var currColumn = 1;
|
||||
$('#available-hours').html('<div style="width:50px; float:left;"></div>');
|
||||
$.each(jsonResponse, function(index, availableHour) {
|
||||
if ((currColumn * 10) < (index + 1)) {
|
||||
currColumn++;
|
||||
$('#available-hours').append('<div style="width:50px; float:left;"></div>');
|
||||
}
|
||||
|
||||
$('#available-hours div:eq(' + (currColumn - 1) + ')')
|
||||
.append('<span class="available-hour">' + availableHour + '</span><br/>');
|
||||
});
|
||||
|
||||
// Set the first item as selected.
|
||||
$('.available-hour:eq(0)').addClass('selected-hour');
|
||||
bookAppointment.updateConfirmData();
|
||||
|
||||
} catch(exception) {
|
||||
// @task Display message to the user.
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* This function validates the customer's data input.
|
||||
* It only checks for empty fields by the time.
|
||||
*
|
||||
* @return {bool} Returns the validation result.
|
||||
*/
|
||||
validateCustomerDataForm : function() {
|
||||
var validationResult = true;
|
||||
$('.required').css('border', '');
|
||||
|
||||
$('.required').each(function() {
|
||||
if ($(this).val() == '') {
|
||||
validationResult = false;
|
||||
$(this).css('border', '2px solid red');
|
||||
}
|
||||
});
|
||||
|
||||
return validationResult;
|
||||
},
|
||||
|
||||
/**
|
||||
* Every time this function is executed, it updates the confirmation
|
||||
* page with the latest customer settigns and input for the appointment
|
||||
* booking.
|
||||
*/
|
||||
updateConfirmData : function() {
|
||||
/*** SET APPOINTMENT INFO ***/
|
||||
var selectedDate = $('#select-date').datepicker('getDate');
|
||||
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>'
|
||||
);
|
||||
|
||||
/*** SET CUSTOMER'S INFO ***/
|
||||
$('#customer-info').html(
|
||||
'<h4>' + $('#last-name').val() + ' ' + $('#first-name').val() + '</h4>' +
|
||||
'Phone: ' + $('#phone-number').val() + '<br/>' +
|
||||
'Email: ' + $('#email').val() + '<br/>' +
|
||||
'Address: ' + $('#address').val() + '<br/>' +
|
||||
'City: ' + $('#city').val() + '<br/>' +
|
||||
'Zip Code: ' + $('#zip-code').val()
|
||||
);
|
||||
|
||||
/*** UPDATE HIDDEN FIELD VALUES ***/
|
||||
$('input[name="lastName"]').val($('#last-name').val());
|
||||
$('input[name="firstName"]').val($('#first-name').val());
|
||||
$('input[name="email"]').val($('#email').val());
|
||||
$('input[name="phoneNumber"]').val($('#phone-number').val());
|
||||
$('input[name="address"]').val($('#address').val());
|
||||
$('input[name="city"]').val($('#city').val());
|
||||
$('input[name="zipCode"]').val($('#zip-code').val());
|
||||
|
||||
var startDatetime = $('#select-date').datepicker('getDate').toString('yyyy-MM-dd') + ' ' + $('.selected-hour').text();
|
||||
var endDatetime = bookAppointment.getEndDatetime();
|
||||
$('input[name="startDatetime"]').val(startDatetime);
|
||||
$('input[name="endDatetime"]').val(endDatetime);
|
||||
$('input[name="notes"]').val($('#notes').val());
|
||||
$('input[name="providerId"]').val($('#select-provider').val());
|
||||
$('input[name="serviceId"]').val($('#select-service').val());
|
||||
},
|
||||
|
||||
/**
|
||||
* This method calculates the end datetime of the current appointment.
|
||||
* End datetime is depending on the service and start datetime fieldss.
|
||||
*
|
||||
* @return {string} Returns the end datetime in string format.
|
||||
*/
|
||||
getEndDatetime : function() {
|
||||
// Find selected service duration.
|
||||
var selServiceDuration = undefined;
|
||||
|
||||
$.each(GlobalVariables.services, function(index, service) {
|
||||
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();
|
||||
startDatetime = Date.parseExact(startDatetime, 'MM/dd/yyyy HH:mm');
|
||||
var endDatetime = undefined;
|
||||
|
||||
if (selServiceDuration != undefined && startDatetime != null) {
|
||||
endDatetime = startDatetime.add({ minutstartDatetimees : parseInt(selServiceDuration) });
|
||||
} else {
|
||||
endDatetime = new Date();
|
||||
}
|
||||
|
||||
return endDatetime.toString('yyyy-MM-dd HH:mm');
|
||||
}
|
||||
}
|