Created a new service categories resource controller
This commit is contained in:
parent
8dd509d4dc
commit
aadac6a060
3 changed files with 462 additions and 10 deletions
173
application/controllers/Service_categories.php
Normal file
173
application/controllers/Service_categories.php
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
<?php defined('BASEPATH') or exit('No direct script access allowed');
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Easy!Appointments - Open Source Web Scheduler
|
||||||
|
*
|
||||||
|
* @package EasyAppointments
|
||||||
|
* @author A.Tselegidis <alextselegidis@gmail.com>
|
||||||
|
* @copyright Copyright (c) 2013 - 2020, Alex Tselegidis
|
||||||
|
* @license https://opensource.org/licenses/GPL-3.0 - GPLv3
|
||||||
|
* @link https://easyappointments.org
|
||||||
|
* @since v1.0.0
|
||||||
|
* ---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service categories controller.
|
||||||
|
*
|
||||||
|
* Handles the service categories related operations.
|
||||||
|
*
|
||||||
|
* @package Controllers
|
||||||
|
*/
|
||||||
|
class Service_categories extends EA_Controller {
|
||||||
|
/**
|
||||||
|
* Service_categories constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->load->model('service_categories_model');
|
||||||
|
$this->load->model('roles_model');
|
||||||
|
|
||||||
|
$this->load->library('accounts');
|
||||||
|
$this->load->library('timezones');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the backend services page.
|
||||||
|
*
|
||||||
|
* On this page admin users will be able to manage services, which are eventually selected by customers during the
|
||||||
|
* booking process.
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
session(['dest_url' => site_url('service_categories')]);
|
||||||
|
|
||||||
|
if (cannot('view', 'services'))
|
||||||
|
{
|
||||||
|
show_error('Forbidden', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_id = session('user_id');
|
||||||
|
|
||||||
|
$role_slug = session('role_slug');
|
||||||
|
|
||||||
|
$this->load->view('pages/service_categories/service_categories_page', [
|
||||||
|
'page_title' => lang('services'),
|
||||||
|
'active_menu' => PRIV_SERVICES,
|
||||||
|
'user_display_name' => $this->accounts->get_user_display_name($user_id),
|
||||||
|
'timezones' => $this->timezones->to_array(),
|
||||||
|
'privileges' => $this->roles_model->get_permissions_by_slug($role_slug),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter services by the provided keyword.
|
||||||
|
*/
|
||||||
|
public function search()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (cannot('view', 'services'))
|
||||||
|
{
|
||||||
|
show_error('Forbidden', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$keyword = request('keyword', '');
|
||||||
|
|
||||||
|
$order_by = 'name ASC';
|
||||||
|
|
||||||
|
$limit = request('limit', 1000);
|
||||||
|
|
||||||
|
$offset = 0;
|
||||||
|
|
||||||
|
$service_categories = $this->service_categories_model->search($keyword, $limit, $offset, $order_by);
|
||||||
|
|
||||||
|
json_response($service_categories);
|
||||||
|
}
|
||||||
|
catch (Throwable $e)
|
||||||
|
{
|
||||||
|
json_exception($e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a service.
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$service_category = json_decode(request('service_category'), TRUE);
|
||||||
|
|
||||||
|
if (cannot('add', 'services'))
|
||||||
|
{
|
||||||
|
show_error('Forbidden', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$service_category_id = $this->service_categories_model->save($service_category);
|
||||||
|
|
||||||
|
json_response([
|
||||||
|
'success' => TRUE,
|
||||||
|
'id' => $service_category_id
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
catch (Throwable $e)
|
||||||
|
{
|
||||||
|
json_exception($e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a service.
|
||||||
|
*/
|
||||||
|
public function update()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$service_category = json_decode(request('service_category'), TRUE);
|
||||||
|
|
||||||
|
if (cannot('edit', 'services'))
|
||||||
|
{
|
||||||
|
show_error('Forbidden', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$service_category_id = $this->service_categories_model->save($service_category);
|
||||||
|
|
||||||
|
json_response([
|
||||||
|
'success' => TRUE,
|
||||||
|
'id' => $service_category_id
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
catch (Throwable $e)
|
||||||
|
{
|
||||||
|
json_exception($e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a service.
|
||||||
|
*/
|
||||||
|
public function destroy()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (cannot('delete', 'services'))
|
||||||
|
{
|
||||||
|
show_error('Forbidden', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$service_category_id = request('service_category_id');
|
||||||
|
|
||||||
|
$this->service_categories_model->delete($service_category_id);
|
||||||
|
|
||||||
|
json_response([
|
||||||
|
'success' => TRUE,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
catch (Throwable $e)
|
||||||
|
{
|
||||||
|
json_exception($e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
279
application/views/pages/service_categories/service_categories_page.php
Executable file
279
application/views/pages/service_categories/service_categories_page.php
Executable file
|
@ -0,0 +1,279 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @var string $timezones
|
||||||
|
* @var array $privileges
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php extend('layouts/backend/backend_layout') ?>
|
||||||
|
|
||||||
|
<?php section('content') ?>
|
||||||
|
|
||||||
|
<script src="<?= asset_url('assets/js/backend_services_helper.js') ?>"></script>
|
||||||
|
<script src="<?= asset_url('assets/js/backend_categories_helper.js') ?>"></script>
|
||||||
|
<script src="<?= asset_url('assets/js/backend_services.js') ?>"></script>
|
||||||
|
<script>
|
||||||
|
var GlobalVariables = {
|
||||||
|
csrfToken: <?= json_encode($this->security->get_csrf_hash()) ?>,
|
||||||
|
baseUrl: <?= json_encode(config('base_url')) ?>,
|
||||||
|
dateFormat: <?= json_encode(setting('date_format')) ?>,
|
||||||
|
timeFormat: <?= json_encode(setting('time_format')) ?>,
|
||||||
|
timezones: <?= json_encode($timezones) ?>,
|
||||||
|
user: {
|
||||||
|
id: <?= session('user_id') ?>,
|
||||||
|
email: <?= json_encode(session('user_email')) ?>,
|
||||||
|
timezone: <?= json_encode(session('timezone')) ?>,
|
||||||
|
role_slug: <?= json_encode(session('role_slug')) ?>,
|
||||||
|
privileges: <?= json_encode($privileges) ?>
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
BackendServices.initialize(true);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container-fluid backend-page" id="services-page">
|
||||||
|
<ul class="nav nav-pills">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="#services" data-toggle="tab">
|
||||||
|
<?= lang('services') ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#categories" data-toggle="tab">
|
||||||
|
<?= lang('categories') ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="tab-content">
|
||||||
|
|
||||||
|
<!-- SERVICES TAB -->
|
||||||
|
|
||||||
|
<div class="tab-pane active" id="services">
|
||||||
|
<div class="row">
|
||||||
|
<div id="filter-services" class="filter-records col col-12 col-md-5">
|
||||||
|
<form class="mb-4">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="key form-control">
|
||||||
|
|
||||||
|
<div class="input-group-addon">
|
||||||
|
<div>
|
||||||
|
<button class="filter btn btn-outline-secondary" type="submit"
|
||||||
|
data-tippy-content="<?= lang('filter') ?>">
|
||||||
|
<i class="fas fa-search"></i>
|
||||||
|
</button>
|
||||||
|
<button class="clear btn btn-outline-secondary" type="button"
|
||||||
|
data-tippy-content="<?= lang('clear') ?>">
|
||||||
|
<i class="fas fa-redo-alt"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h3><?= lang('services') ?></h3>
|
||||||
|
<div class="results"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="record-details column col-12 col-md-5">
|
||||||
|
<div class="btn-toolbar mb-4">
|
||||||
|
<div class="add-edit-delete-group btn-group">
|
||||||
|
<button id="add-service" class="btn btn-primary">
|
||||||
|
<i class="fas fa-plus-square mr-2"></i>
|
||||||
|
<?= lang('add') ?>
|
||||||
|
</button>
|
||||||
|
<button id="edit-service" class="btn btn-outline-secondary" disabled="disabled">
|
||||||
|
<i class="fas fa-edit mr-2"></i>
|
||||||
|
<?= lang('edit') ?>
|
||||||
|
</button>
|
||||||
|
<button id="delete-service" class="btn btn-outline-secondary" disabled="disabled">
|
||||||
|
<i class="fas fa-trash-alt mr-2"></i>
|
||||||
|
<?= lang('delete') ?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="save-cancel-group btn-group" style="display:none;">
|
||||||
|
<button id="save-service" class="btn btn-primary">
|
||||||
|
<i class="fas fa-check-square mr-2"></i>
|
||||||
|
<?= lang('save') ?>
|
||||||
|
</button>
|
||||||
|
<button id="cancel-service" class="btn btn-outline-secondary">
|
||||||
|
<i class="fas fa-ban mr-2"></i>
|
||||||
|
<?= lang('cancel') ?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3><?= lang('details') ?></h3>
|
||||||
|
|
||||||
|
<div class="form-message alert" style="display:none;"></div>
|
||||||
|
|
||||||
|
<input type="hidden" id="service-id">
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="service-name">
|
||||||
|
<?= lang('name') ?>
|
||||||
|
<span class="text-danger">*</span>
|
||||||
|
</label>
|
||||||
|
<input id="service-name" class="form-control required" maxlength="128">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="service-duration">
|
||||||
|
<?= lang('duration_minutes') ?>
|
||||||
|
<span class="text-danger">*</span>
|
||||||
|
</label>
|
||||||
|
<input id="service-duration" class="form-control required" type="number" min="<?= EVENT_MINIMUM_DURATION ?>">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="service-price">
|
||||||
|
<?= lang('price') ?>
|
||||||
|
<span class="text-danger">*</span>
|
||||||
|
</label>
|
||||||
|
<input id="service-price" class="form-control required">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="service-currency">
|
||||||
|
<?= lang('currency') ?>
|
||||||
|
|
||||||
|
</label>
|
||||||
|
<input id="service-currency" class="form-control" maxlength="32">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="service-category">
|
||||||
|
<?= lang('category') ?>
|
||||||
|
</label>
|
||||||
|
<select id="service-category" class="form-control"></select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="service-availabilities-type">
|
||||||
|
<?= lang('availabilities_type') ?>
|
||||||
|
|
||||||
|
</label>
|
||||||
|
<select id="service-availabilities-type" class="form-control">
|
||||||
|
<option value="<?= AVAILABILITIES_TYPE_FLEXIBLE ?>">
|
||||||
|
<?= lang('flexible') ?>
|
||||||
|
</option>
|
||||||
|
<option value="<?= AVAILABILITIES_TYPE_FIXED ?>">
|
||||||
|
<?= lang('fixed') ?>
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="service-attendants-number">
|
||||||
|
<?= lang('attendants_number') ?>
|
||||||
|
<span class="text-danger">*</span>
|
||||||
|
</label>
|
||||||
|
<input id="service-attendants-number" class="form-control required" type="number" min="1">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="service-location">
|
||||||
|
<?= lang('location') ?>
|
||||||
|
|
||||||
|
</label>
|
||||||
|
<input id="service-location" class="form-control">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="service-description">
|
||||||
|
<?= lang('description') ?>
|
||||||
|
</label>
|
||||||
|
<textarea id="service-description" rows="4" class="form-control"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- CATEGORIES TAB -->
|
||||||
|
|
||||||
|
<div class="tab-pane" id="categories">
|
||||||
|
<div class="row">
|
||||||
|
<div id="filter-categories" class="filter-records column col-12 col-md-5">
|
||||||
|
<form class="input-append mb-4">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="key form-control">
|
||||||
|
|
||||||
|
<div class="input-group-addon">
|
||||||
|
<div>
|
||||||
|
<button class="filter btn btn-outline-secondary" type="submit"
|
||||||
|
data-tippy-content="<?= lang('filter') ?>">
|
||||||
|
<i class="fas fa-search"></i>
|
||||||
|
</button>
|
||||||
|
<button class="clear btn btn-outline-secondary" type="button"
|
||||||
|
data-tippy-content="<?= lang('clear') ?>">
|
||||||
|
<i class="fas fa-redo-alt"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h3><?= lang('categories') ?></h3>
|
||||||
|
<div class="results"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="record-details col-12 col-md-5">
|
||||||
|
<div class="btn-toolbar mb-4">
|
||||||
|
<div class="add-edit-delete-group btn-group">
|
||||||
|
<button id="add-category" class="btn btn-primary">
|
||||||
|
<i class="fas fa-plus-square mr-2"></i>
|
||||||
|
<?= lang('add') ?>
|
||||||
|
</button>
|
||||||
|
<button id="edit-category" class="btn btn-outline-secondary" disabled="disabled">
|
||||||
|
<i class="fas fa-edit mr-2"></i>
|
||||||
|
<?= lang('edit') ?>
|
||||||
|
</button>
|
||||||
|
<button id="delete-category" class="btn btn-outline-secondary" disabled="disabled">
|
||||||
|
<i class="fas fa-trash-alt mr-2"></i>
|
||||||
|
<?= lang('delete') ?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="save-cancel-group btn-group" style="display:none;">
|
||||||
|
<button id="save-category" class="btn btn-primary">
|
||||||
|
<i class="fas fa-check-square mr-2"></i>
|
||||||
|
<?= lang('save') ?>
|
||||||
|
</button>
|
||||||
|
<button id="cancel-category" class="btn btn-outline-secondary">
|
||||||
|
<i class="fas fa-ban mr-2"></i>
|
||||||
|
<?= lang('cancel') ?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3><?= lang('details') ?></h3>
|
||||||
|
|
||||||
|
<div class="form-message alert" style="display:none;"></div>
|
||||||
|
|
||||||
|
<input type="hidden" id="category-id">
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="category-name">
|
||||||
|
<?= lang('name') ?>
|
||||||
|
<span class="text-danger">*</span>
|
||||||
|
</label>
|
||||||
|
<input id="category-name" class="form-control required">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="category-description">
|
||||||
|
<?= lang('description') ?>
|
||||||
|
|
||||||
|
</label>
|
||||||
|
<textarea id="category-description" rows="4" class="form-control"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php section('content') ?>
|
|
@ -174,17 +174,17 @@
|
||||||
/**
|
/**
|
||||||
* Filter service categories records.
|
* Filter service categories records.
|
||||||
*
|
*
|
||||||
* @param {String} key This key string is used to filter the category records.
|
* @param {String} keyword This key string is used to filter the category records.
|
||||||
* @param {Number} selectId Optional, if set then after the filter operation the record with the given
|
* @param {Number} selectId Optional, if set then after the filter operation the record with the given
|
||||||
* ID will be selected (but not displayed).
|
* ID will be selected (but not displayed).
|
||||||
* @param {Boolean} display Optional (false), if true then the selected record will be displayed on the form.
|
* @param {Boolean} display Optional (false), if true then the selected record will be displayed on the form.
|
||||||
*/
|
*/
|
||||||
CategoriesHelper.prototype.filter = function (key, selectId, display) {
|
CategoriesHelper.prototype.filter = function (keyword, selectId, display) {
|
||||||
var url = GlobalVariables.baseUrl + '/index.php/backend_api/ajax_filter_service_categories';
|
var url = GlobalVariables.baseUrl + '/index.php/service_categories/search';
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
csrfToken: GlobalVariables.csrfToken,
|
csrfToken: GlobalVariables.csrfToken,
|
||||||
key: key,
|
keyword: keyword,
|
||||||
limit: this.filterLimit
|
limit: this.filterLimit
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@
|
||||||
'text': EALang.load_more,
|
'text': EALang.load_more,
|
||||||
'click': function () {
|
'click': function () {
|
||||||
this.filterLimit += 20;
|
this.filterLimit += 20;
|
||||||
this.filter(key, selectId, display);
|
this.filter(keyword, selectId, display);
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
}).appendTo('#filter-categories .results');
|
}).appendTo('#filter-categories .results');
|
||||||
}
|
}
|
||||||
|
@ -231,11 +231,11 @@
|
||||||
* @param {Object} category Contains the category data.
|
* @param {Object} category Contains the category data.
|
||||||
*/
|
*/
|
||||||
CategoriesHelper.prototype.save = function (category) {
|
CategoriesHelper.prototype.save = function (category) {
|
||||||
var url = GlobalVariables.baseUrl + '/index.php/backend_api/ajax_save_service_category';
|
var url = GlobalVariables.baseUrl + '/index.php/service_categories/' + (category.id ? 'update' : 'create');
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
csrfToken: GlobalVariables.csrfToken,
|
csrfToken: GlobalVariables.csrfToken,
|
||||||
category: JSON.stringify(category)
|
service_category: JSON.stringify(category)
|
||||||
};
|
};
|
||||||
|
|
||||||
$.post(url, data).done(
|
$.post(url, data).done(
|
||||||
|
@ -252,14 +252,14 @@
|
||||||
/**
|
/**
|
||||||
* Delete category record.
|
* Delete category record.
|
||||||
*
|
*
|
||||||
* @param Number} id Record ID to be deleted.
|
* @param {Number} id Record ID to be deleted.
|
||||||
*/
|
*/
|
||||||
CategoriesHelper.prototype.delete = function (id) {
|
CategoriesHelper.prototype.delete = function (id) {
|
||||||
var url = GlobalVariables.baseUrl + '/index.php/backend_api/ajax_delete_service_category';
|
var url = GlobalVariables.baseUrl + '/index.php/service_categories/destroy';
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
csrfToken: GlobalVariables.csrfToken,
|
csrfToken: GlobalVariables.csrfToken,
|
||||||
category_id: id
|
service_category_id: id
|
||||||
};
|
};
|
||||||
|
|
||||||
$.post(url, data).done(
|
$.post(url, data).done(
|
||||||
|
|
Loading…
Reference in a new issue