Υλοποίηση κύριας λειτουργίας των τεσσάρων βημάτων της κράτησης ραντεβού. Λείπουν επιπλέον λειτουργίες ελέχγου των δεδομένων και η μορφοποίηση της σελίδας.
|
@ -5,11 +5,45 @@ class Appointments extends CI_Controller {
|
|||
* This page displays the book appointment wizard
|
||||
* for the customers.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
public function index() {
|
||||
// Get business name.
|
||||
$this->load->model('Settings');
|
||||
$viewData['businessName'] = $this->Settings->getSetting('business_name');
|
||||
|
||||
// Get the available services and providers.
|
||||
$this->load->model('Services');
|
||||
$viewData['availableServices'] = $this->Services->getAvailableServices();
|
||||
|
||||
$this->load->model('Providers');
|
||||
$viewData['availableProviders'] = $this->Providers->getAvailableProviders(); // Provider rows contain an array of which services they can provide.
|
||||
|
||||
// Load the book appointment view.
|
||||
$this->load->view('appointments/book', $viewData);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method answers to an AJAX request. It calculates the
|
||||
* available hours for the given service, provider and date.
|
||||
*
|
||||
* @param array $_POST['postData'] An associative array that
|
||||
* contains the user selected service, provider and date.
|
||||
*/
|
||||
public function getAvailableHours() {
|
||||
/*** CHECK BUSINESS WORKING HOURS ***/
|
||||
/*** CHECK PROVIDERS WORKING HOURS ***/
|
||||
/*** CHECK ALREADY BOOKED APPOINTMENTS ***/
|
||||
/*** RETURN AVAILABLE HOURS ***/
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// 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
|
||||
|
||||
for ($i=0; ($startTime*60 + $i*60)<=($endTime*60); $i+=intval($_POST['serviceDuration'])) {
|
||||
$availableHours[] = date('H:i', $startTime * 60 + $i * 60);
|
||||
}
|
||||
|
||||
echo json_encode($availableHours);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,44 @@
|
|||
<?php
|
||||
class Providers extends CI_Model {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
/**
|
||||
* This method returns the available providers and
|
||||
* the services that can provide.
|
||||
*
|
||||
* @return array Returns an array with the providers
|
||||
* 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"';
|
||||
|
||||
$providers = $this->db->query($sql)->result_array();
|
||||
|
||||
foreach($providers as &$provider) {
|
||||
$sql = '
|
||||
SELECT id_services
|
||||
FROM ea_services_providers
|
||||
WHERE id_users = ' . $this->db->escape($provider['id']);
|
||||
|
||||
$providerServices = $this->db->query($sql)->result_array();
|
||||
|
||||
if (!isset($provider['services'])) {
|
||||
$provider['services'] = array();
|
||||
}
|
||||
|
||||
foreach($providerServices as $providerService) {
|
||||
$provider['services'][] = $providerService['id_services'];
|
||||
}
|
||||
}
|
||||
|
||||
return $providers;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -10,10 +10,8 @@ class Services extends CI_Model {
|
|||
* @return array Returns an object array with all the
|
||||
* database services.
|
||||
*/
|
||||
function getAllServices() {
|
||||
$query = $this->db->query('SELECT *');
|
||||
|
||||
return $this->db->get('ea_services');
|
||||
function getAvailableServices() {
|
||||
return $this->db->get('ea_services')->result_array();
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -27,7 +27,6 @@ class Settings extends CI_Model {
|
|||
*
|
||||
* @param string $name The setting name.
|
||||
* @param type $value The setting value.
|
||||
*
|
||||
* @return bool Returns the operation success - failure
|
||||
* result.
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<!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">
|
||||
|
@ -13,13 +15,151 @@
|
|||
<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>
|
||||
|
||||
<?php // SET FAVICON FOR PAGE ?>
|
||||
<link rel="icon" type="image/x-icon" href="<?php echo $this->config->base_url(); ?>assets/images/favicon.ico">
|
||||
|
||||
<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.
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
@ -51,37 +191,98 @@
|
|||
<h2>Select Service & Provider</h2>
|
||||
<label for="select-service">Select Service</label>
|
||||
<select id="select-service">
|
||||
<option value="1">General Examination</option>
|
||||
<option value="2">Check Blood Pressure</option>
|
||||
<?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">
|
||||
<option value="1">Dr. Andy Smith</option>
|
||||
<option value="2">Dr. Peter Grol</option>
|
||||
<option value="3">Dr. Kurt Benstein</option>
|
||||
</select>
|
||||
<select id="select-provider"></select>
|
||||
|
||||
<button type="button" id="button-next-1" class="btn">Next</button>
|
||||
<div class="command-buttons">
|
||||
<button type="button" id="button-next-1" class="btn button-next" data-step_index="1">Next</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php // APPOINTMENT DATE ?>
|
||||
<div id="book-appointment-2" class="book-appoinment-step">
|
||||
<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="span3">
|
||||
<?php // Available hours are going to be fetched via ajax call. ?>
|
||||
<div id="available-hours"></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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php // CUSTOMER'S INFO ?>
|
||||
<div id="book-appointment-3" class="book-appoinment-step">
|
||||
<div id="book-appointment-3" class="book-appoinment-step" style="display:none;">
|
||||
<h2>Fill In Your Information</h2>
|
||||
|
||||
<div class="span3">
|
||||
<label for="last-name">Last Name *</label>
|
||||
<input type="text" id="last-name" maxlength="250" />
|
||||
|
||||
<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="phone-number">Phone Number *</label>
|
||||
<input type="text" id="phone-number" maxlength="60" />
|
||||
</div>
|
||||
|
||||
<div class="span3">
|
||||
<label for="address">Address</label>
|
||||
<input type="text" id="address" maxlength="250" />
|
||||
|
||||
<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"></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>
|
||||
</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>
|
||||
|
||||
<?php // CONFIRMATION STEP ?>
|
||||
<div id="book-appointment-4" class="book-appoinment-step">
|
||||
<div id="customer-info">
|
||||
|
||||
</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>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="frame-footer">
|
||||
<em>Powered By <a href="https://code.google.com/p/easy-appointments/">Easy!Appointments</a></em>
|
||||
</div>
|
||||
|
|
After Width: | Height: | Size: 333 B |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 336 B |
After Width: | Height: | Size: 321 B |
After Width: | Height: | Size: 328 B |
After Width: | Height: | Size: 252 B |
After Width: | Height: | Size: 353 B |
After Width: | Height: | Size: 351 B |
After Width: | Height: | Size: 349 B |
BIN
src/assets/css/libs/jquery/images/ui-icons_808080_256x240.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
src/assets/css/libs/jquery/images/ui-icons_847e71_256x240.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
src/assets/css/libs/jquery/images/ui-icons_8DC262_256x240.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
src/assets/css/libs/jquery/images/ui-icons_cd0a0a_256x240.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
src/assets/css/libs/jquery/images/ui-icons_eeeeee_256x240.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
6
src/assets/css/libs/jquery/jquery-ui.min.css
vendored
|
@ -14,9 +14,10 @@ body {
|
|||
------------------------------------------------------------------------------ */
|
||||
#book-appointment {
|
||||
width: 660px;
|
||||
margin: 150px auto;
|
||||
margin: 150px auto 0 auto;
|
||||
background: #FFF;
|
||||
box-shadow: 0px 1px 1px #B6B6B6;
|
||||
min-height: 480px;
|
||||
}
|
||||
|
||||
#book-appointment #top-bar {
|
||||
|
@ -40,39 +41,34 @@ body {
|
|||
width: 252px;
|
||||
display: inline-block;
|
||||
float: right;
|
||||
margin-top: 12px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
#book-appointment .book-appoinment-step {
|
||||
padding: 10px 20px;
|
||||
height: 363px;
|
||||
}
|
||||
|
||||
#book-appointment .book-step {
|
||||
display: inline-block;
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
float: left;
|
||||
background: #E1FFCF;
|
||||
background: #FFF;
|
||||
padding: 10px;
|
||||
margin-right: 15px;
|
||||
border-radius: 50px;
|
||||
box-shadow: inset 1px 1px 3px #2B2B2B;
|
||||
border: 3px solid #38A07A;
|
||||
}
|
||||
|
||||
#book-appointment .book-step strong {
|
||||
font-size: 29px;
|
||||
font-size: 25px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-top: 4px;
|
||||
color: #B6DFC6;
|
||||
}
|
||||
|
||||
#book-appointment .active-step {
|
||||
background: #FAFA99;
|
||||
}
|
||||
|
||||
#book-appointment .active-step strong {
|
||||
color: #696439;
|
||||
color: #396946;
|
||||
}
|
||||
|
||||
#book-appointment #frame-footer {
|
||||
|
@ -81,3 +77,19 @@ body {
|
|||
border-top: 1px solid #EEE;
|
||||
background: #FAFAFA;
|
||||
}
|
||||
|
||||
.custom-qtip {
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
#available-hours .available-hour:hover {
|
||||
font-weight: bold;
|
||||
background-color: #CAEDF3;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#available-hours .selected-hour {
|
||||
color: #0088cc;
|
||||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
|