diff --git a/application/controllers/settings/Current_user.php b/application/controllers/settings/Current_user.php
new file mode 100644
index 00000000..10af7573
--- /dev/null
+++ b/application/controllers/settings/Current_user.php
@@ -0,0 +1,110 @@
+
+ * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis
+ * @license https://opensource.org/licenses/GPL-3.0 - GPLv3
+ * @link https://easyappointments.org
+ * @since v1.5.0
+ * ---------------------------------------------------------------------------- */
+
+/**
+ * Current user controller.
+ *
+ * Handles current user settings related operations.
+ *
+ * @package Controllers
+ */
+class Current_user extends EA_Controller {
+ /**
+ * @var array
+ */
+ protected array $permissions;
+
+ /**
+ * Current_user constructor.
+ */
+ public function __construct()
+ {
+ parent::__construct();
+
+ $this->load->model('appointments_model');
+ $this->load->model('customers_model');
+ $this->load->model('services_model');
+ $this->load->model('providers_model');
+ $this->load->model('roles_model');
+ $this->load->model('settings_model');
+
+ $this->load->library('accounts');
+ $this->load->library('google_sync');
+ $this->load->library('notifications');
+ $this->load->library('synchronization');
+ $this->load->library('timezones');
+
+ $role_slug = session('role_slug');
+
+ if ($role_slug)
+ {
+ $this->permissions = $this->roles_model->get_permissions_by_slug($role_slug);
+ }
+ }
+
+ /**
+ * Render the settings page.
+ */
+ public function index()
+ {
+ session(['dest_url' => site_url('services')]);
+
+ if (cannot('view', 'services'))
+ {
+ show_error('Forbidden', 403);
+ }
+
+ $user_id = session('user_id');
+
+ $role_slug = session('role_slug');
+
+ $this->load->view('pages/settings/current_user/current_user_page', [
+ 'page_title' => lang('settings'),
+ 'active_menu' => PRIV_SYSTEM_SETTINGS,
+ '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),
+ 'user_settings' => $this->users_model->find($user_id),
+ ]);
+ }
+
+ /**
+ * Save general settings.
+ */
+ public function save()
+ {
+ try
+ {
+ if ($this->permissions[PRIV_USER_SETTINGS]['edit'] == FALSE)
+ {
+ throw new Exception('You do not have the required permissions for this task.');
+ }
+
+ $settings = json_decode(request('settings'), TRUE);
+
+ $this->users_model->save($settings);
+
+ session([
+ 'user_email' => $settings['email'],
+ 'username' => $settings['settings']['username'],
+ 'timezone' => $settings['timezone'],
+ ]);
+
+ response();
+ }
+ catch (Throwable $e)
+ {
+ json_exception($e);
+ }
+ }
+}
diff --git a/application/views/pages/settings/current_user/current_user_page.php b/application/views/pages/settings/current_user/current_user_page.php
new file mode 100644
index 00000000..5f676c6a
--- /dev/null
+++ b/application/views/pages/settings/current_user/current_user_page.php
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/js/backend_settings_current_user.js b/assets/js/backend_settings_current_user.js
new file mode 100644
index 00000000..bab8fd35
--- /dev/null
+++ b/assets/js/backend_settings_current_user.js
@@ -0,0 +1,94 @@
+/* ----------------------------------------------------------------------------
+ * Easy!Appointments - Open Source Web Scheduler
+ *
+ * @package EasyAppointments
+ * @author A.Tselegidis
+ * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis
+ * @license http://opensource.org/licenses/GPL-3.0 - GPLv3
+ * @link http://easyappointments.org
+ * @since v1.0.0
+ * ---------------------------------------------------------------------------- */
+
+window.BackendSettingsCurrentUser = window.BackendSettingsCurrentUser || {};
+
+/**
+ * Backend Settings
+ *
+ * Contains the functionality of the backend settings page. Can either work for system or user settings,
+ * but the actions allowed to the user are restricted to his role (only admin has full privileges).
+ *
+ * @module BackendSettingsCurrentUser
+ */
+(function (exports) {
+ 'use strict';
+
+ // Constants
+ exports.SETTINGS_USER = 'SETTINGS_USER';
+
+ /**
+ * Use this WorkingPlan class instance to perform actions on the page's working plan tables.
+ *
+ * @type {WorkingPlan}
+ */
+ exports.wp = {};
+
+ /**
+ * Tab settings object.
+ *
+ * @type {Object}
+ */
+ var settings = {};
+
+ /**
+ * Initialize Page
+ *
+ * @param {bool} defaultEventHandlers Optional (true), determines whether to bind the default event handlers.
+ */
+ exports.initialize = function (defaultEventHandlers) {
+ defaultEventHandlers = defaultEventHandlers || true;
+
+ // Load user settings into form
+ $('#user-id').val(GlobalVariables.settings.user.id);
+ $('#first-name').val(GlobalVariables.settings.user.first_name);
+ $('#last-name').val(GlobalVariables.settings.user.last_name);
+ $('#email').val(GlobalVariables.settings.user.email);
+ $('#mobile-number').val(GlobalVariables.settings.user.mobile_number);
+ $('#phone-number').val(GlobalVariables.settings.user.phone_number);
+ $('#address').val(GlobalVariables.settings.user.address);
+ $('#city').val(GlobalVariables.settings.user.city);
+ $('#state').val(GlobalVariables.settings.user.state);
+ $('#zip-code').val(GlobalVariables.settings.user.zip_code);
+ $('#notes').val(GlobalVariables.settings.user.notes);
+ $('#timezone').val(GlobalVariables.settings.user.timezone);
+ $('#username').val(GlobalVariables.settings.user.settings.username);
+ $('#password, #retype-password').val('');
+ $('#calendar-view').val(GlobalVariables.settings.user.settings.calendar_view);
+ $('#user-notifications').prop('checked', Boolean(Number(GlobalVariables.settings.user.settings.notifications)));
+
+ // Set default settings helper.
+ settings = new SystemSettingsCurrentUserHelper();
+
+ if (defaultEventHandlers) {
+ bindEventHandlers();
+ }
+
+ Backend.placeFooterToBottom();
+ };
+
+ /**
+ * Bind the backend/settings default event handlers.
+ *
+ * This method depends on the backend/settings html, so do not use this method on a different page.
+ */
+ function bindEventHandlers() {
+ /**
+ * Event: Save Settings Button "Click"
+ *
+ * Store the setting changes into the database.
+ */
+ $('.save-settings').on('click', function () {
+ var data = settings.get();
+ settings.save(data);
+ });
+ }
+})(window.BackendSettingsCurrentUser);
diff --git a/assets/js/backend_settings_current_user_helper.js b/assets/js/backend_settings_current_user_helper.js
new file mode 100644
index 00000000..7a73f729
--- /dev/null
+++ b/assets/js/backend_settings_current_user_helper.js
@@ -0,0 +1,131 @@
+/* ----------------------------------------------------------------------------
+ * Easy!Appointments - Open Source Web Scheduler
+ *
+ * @package EasyAppointments
+ * @author A.Tselegidis
+ * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis
+ * @license http://opensource.org/licenses/GPL-3.0 - GPLv3
+ * @link http://easyappointments.org
+ * @since v1.0.0
+ * ---------------------------------------------------------------------------- */
+
+(function () {
+ 'use strict';
+
+ /**
+ * "User Settings" Tab Helper Class
+ *
+ * @class SystemSettingsCurrentUserHelper
+ */
+ var SystemSettingsCurrentUserHelper = function () {};
+
+ /**
+ * Get the settings data for the user settings.
+ *
+ * @return {Object} Returns the user settings array.
+ */
+ SystemSettingsCurrentUserHelper.prototype.get = function () {
+ var user = {
+ id: $('#user-id').val(),
+ first_name: $('#first-name').val(),
+ last_name: $('#last-name').val(),
+ email: $('#email').val(),
+ mobile_number: $('#mobile-number').val(),
+ phone_number: $('#phone-number').val(),
+ address: $('#address').val(),
+ city: $('#city').val(),
+ state: $('#state').val(),
+ zip_code: $('#zip-code').val(),
+ notes: $('#notes').val(),
+ timezone: $('#timezone').val(),
+ settings: {
+ username: $('#username').val(),
+ notifications: $('#user-notifications').prop('checked'),
+ calendar_view: $('#calendar-view').val()
+ }
+ };
+
+ if ($('#password').val()) {
+ user.settings.password = $('#password').val();
+ }
+
+ return user;
+ };
+
+ /**
+ * Store the user settings into the database.
+ *
+ * @param {Array} settings Contains the user settings.
+ */
+ SystemSettingsCurrentUserHelper.prototype.save = function (settings) {
+ if (!this.validate(settings)) {
+ Backend.displayNotification(EALang.user_settings_are_invalid);
+ return; // Validation failed, do not proceed.
+ }
+
+ var url = GlobalVariables.baseUrl + '/index.php/settings/current_user/save';
+
+ var data = {
+ csrfToken: GlobalVariables.csrfToken,
+ type: BackendSettingsCurrentUser.SETTINGS_USER,
+ settings: JSON.stringify(settings)
+ };
+
+ $.post(url, data).done(function () {
+ Backend.displayNotification(EALang.settings_saved);
+
+ // Update footer greetings.
+ $('#footer-user-display-name').text('Hello, ' + $('#first-name').val() + ' ' + $('#last-name').val() + '!');
+ });
+ };
+
+ /**
+ * Validate the settings data.
+ *
+ * If the validation fails then display a message to the user.
+ *
+ * @return {Boolean} Returns the validation result.
+ */
+ SystemSettingsCurrentUserHelper.prototype.validate = function () {
+ $('#current-user .has-error').removeClass('has-error');
+
+ try {
+ // Validate required fields.
+ var missingRequired = false;
+ $('#current-user .required').each(function (index, requiredField) {
+ if (!$(requiredField).val()) {
+ $(requiredField).closest('.form-group').addClass('has-error');
+ missingRequired = true;
+ }
+ });
+
+ if (missingRequired) {
+ throw new Error(EALang.fields_are_required);
+ }
+
+ // Validate passwords (if provided).
+ if ($('#password').val() !== $('#retype-password').val()) {
+ $('#password, #retype-password').closest('.form-group').addClass('has-error');
+ throw new Error(EALang.passwords_mismatch);
+ }
+
+ // Validate user email.
+ if (!GeneralFunctions.validateEmail($('#email').val())) {
+ $('#email').closest('.form-group').addClass('has-error');
+ throw new Error(EALang.invalid_email);
+ }
+
+ if ($('#username').attr('already-exists') === 'true') {
+ $('#username').closest('.form-group').addClass('has-error');
+ throw new Error(EALang.username_already_exists);
+ }
+
+ return true;
+ } catch (error) {
+ Backend.displayNotification(error.message);
+ return false;
+ }
+ };
+
+ window.SystemSettingsCurrentUserHelper = SystemSettingsCurrentUserHelper;
+})();