update v. 3.31.1

This commit is contained in:
2026-03-05 17:43:48 +05:00
parent ff11df5740
commit 29aa40f7bb
20 changed files with 2210 additions and 1518 deletions

View File

@@ -1,14 +1,33 @@
### login
## Модуль Авторизация v2.26.1
## Модуль Авторизация v3.31.1
### Данный модуль предназначен для регистрации пользователей на вашем сайте.
* Для вывода формы авторизации, разместите системный тег <strong>[mod_login]</strong> в нужном месте вашего шаблона. Также вы можете указать шаблон, в котором будет отображена форма для регистрации и авторизации.
* Для вывода формы авторизации, разместите системный тег <strong>[mod_login]</strong> в нужном месте вашего шаблона. Также вы можете указать шаблон, в котором будет отображена форма для регистрации и авторизации. Для подключения в дефолтный шаблон Ave.cms начиная с версии 3.31 ALT , найдите блок:
```
<div class="collapse navbar-collapse" id="navbarCollapse">
[tag:navigation:main]
</div>
```
и замените его на:
```
<div class="collapse navbar-collapse" id="navbarCollapse">
[tag:navigation:main]
<div class="ms-auto">
[mod_login]
</div>
</div>
```
### Changelog:
05.03.2026 - версия 3.31.1 Рефакторинг кода для работы в среде PHP-8.4,
добавлено управление Аватаром Пользователя, улучшен Пользовательский интерфейс, верстка Bootstrap v5
02.09.2019 - версия 2.26.1 Адаптирован для версии 3.26
20.04.2014 - версия 2.2.1

View File

@@ -2,97 +2,147 @@
<div class="widget" style="margin-top: 0px;">
<div class="body">
{#LOGIN_MODULE_INFO#}
{#LOGIN_MODULE_INFO#}
</div>
</div>
<div class="breadCrumbHolder module">
<div class="breadCrumb module">
<ul>
<li class="firstB"><a href="index.php" title="{#MAIN_PAGE#}">{#MAIN_PAGE#}</a></li>
<li><a href="index.php?do=modules&amp;cp={$sess}">{#MODULES_SUB_TITLE#}</a></li>
<li>{#LOGIN_MODULE#}</li>
<li><strong class="code">{#LOGIN_MODULE_NAME#}</strong></li>
</ul>
</div>
<div class="breadCrumb module">
<ul>
<li class="firstB"><a href="index.php" title="{#MAIN_PAGE#}">{#MAIN_PAGE#}</a></li>
<li><a href="index.php?do=modules&amp;cp={$sess}">{#MODULES_SUB_TITLE#}</a></li>
<li>{#LOGIN_MODULE#}</li>
<li><strong class="code">{#LOGIN_MODULE_NAME#}</strong></li>
</ul>
</div>
</div>
<div class="widget first">
<div class="head"><h5 class="iFrames">{#LOGIN_MODULE_EDIT#}</h5></div>
<div class="head"><h5 class="iFrames">{#LOGIN_MODULE_EDIT#}</h5></div>
<form method="post" action="index.php?do=modules&action=modedit&mod=login&moduleaction=1&cp={$sess}&sub=save" class="mainForm">
<table cellpadding="0" cellspacing="0" width="100%" class="tableStatic">
<form method="post" action="index.php?do=modules&action=modedit&mod=login&moduleaction=1&cp={$sess}&sub=save" class="mainForm" id="login_settings_form">
<table cellpadding="0" cellspacing="0" width="100%" class="tableStatic">
<tr class="noborder">
<td width="200">{#LOGIN_REGISTRATION_TYPE#}</td>
<td>
<select name="login_reg_type" id="login_reg_type">
<option value="email" {if $login_reg_type=='email'}selected{/if}>{#LOGIN_TYPE_BYEMAIL#}</option>
<option value="now" {if $login_reg_type=='now'}selected{/if}>{#LOGIN_TYPE_NOW#}</option>
<option value="byadmin" {if $login_reg_type=='byadmin'}selected{/if}>{#LOGIN_TYPE_BYADMIN#}</option>
</select>
</td>
</tr>
<tr class="noborder">
<td width="200">{#LOGIN_REGISTRATION_TYPE#}</td>
<td>
<select name="login_reg_type" id="login_reg_type">
<option value="email" {if $login_reg_type=='email'}selected{/if}>{#LOGIN_TYPE_BYEMAIL#}</option>
<option value="now" {if $login_reg_type=='now'}selected{/if}>{#LOGIN_TYPE_NOW#}</option>
<option value="byadmin" {if $login_reg_type=='byadmin'}selected{/if}>{#LOGIN_TYPE_BYADMIN#}</option>
</select>
</td>
</tr>
<tr>
<td width="200">{#LOGIN_USE_SCODE#}</td>
<td>
<input name="login_antispam" type="radio" value="1" {if $login_antispam=='1'}checked{/if} > <label>{#LOGIN_YES#}</label>
<input name="login_antispam" type="radio" value="0" {if $login_antispam!='1'}checked{/if}> <label>{#LOGIN_NO#}</label>
</td>
</tr>
<tr>
<td width="200">{#LOGIN_USE_SCODE#}</td>
<td>
<input name="login_antispam" type="radio" value="1" {if $login_antispam=='1'}checked{/if} > <label>{#LOGIN_YES#}</label>
<input name="login_antispam" type="radio" value="0" {if $login_antispam!='1'}checked{/if}> <label>{#LOGIN_NO#}</label>
</td>
</tr>
<tr>
<td width="200">{#LOGIN_ENABLE_REGISTER#}</td>
<td>
<input name="login_status" type="radio" value="1" {if $login_status=='1'}checked{/if} > <label>{#LOGIN_YES#}</label>
<input name="login_status" type="radio" value="0" {if $login_status!='1'}checked{/if}> <label>{#LOGIN_NO#}</label>
</td>
</tr>
<tr>
<td width="200">{#LOGIN_ENABLE_REGISTER#}</td>
<td>
<input name="login_status" type="radio" value="1" {if $login_status=='1'}checked{/if} > <label>{#LOGIN_YES#}</label>
<input name="login_status" type="radio" value="0" {if $login_status!='1'}checked{/if}> <label>{#LOGIN_NO#}</label>
</td>
</tr>
<tr>
<td>{#LOGIN_SHOW_FIRSTNAME#}</td>
<td>
<input name="login_require_firstname" type="radio" value="1" {if $login_require_firstname=='1'}checked{/if} > <label>{#LOGIN_YES#}</label>
<input name="login_require_firstname" type="radio" value="0" {if $login_require_firstname!='1'}checked{/if}> <label>{#LOGIN_NO#}</label>
</td>
</tr>
<tr>
<td>{#LOGIN_SHOW_FIRSTNAME#}</td>
<td>
<input name="login_require_firstname" type="radio" value="1" {if $login_require_firstname=='1'}checked{/if} > <label>{#LOGIN_YES#}</label>
<input name="login_require_firstname" type="radio" value="0" {if $login_require_firstname!='1'}checked{/if}> <label>{#LOGIN_NO#}</label>
</td>
</tr>
<tr>
<td>{#LOGIN_SHOW_LASTNAME#}</td>
<td>
<input name="login_require_lastname" type="radio" value="1" {if $login_require_lastname=='1'}checked{/if} > <label>{#LOGIN_YES#}</label>
<input name="login_require_lastname" type="radio" value="0" {if $login_require_lastname!='1'}checked{/if}> <label>{#LOGIN_NO#}</label>
</td>
</tr>
<tr>
<td>{#LOGIN_SHOW_LASTNAME#}</td>
<td>
<input name="login_require_lastname" type="radio" value="1" {if $login_require_lastname=='1'}checked{/if} > <label>{#LOGIN_YES#}</label>
<input name="login_require_lastname" type="radio" value="0" {if $login_require_lastname!='1'}checked{/if}> <label>{#LOGIN_NO#}</label>
</td>
</tr>
<tr>
<td>{#LOGIN_SHOW_COMPANY#}</td>
<td>
<input name="login_require_company" type="radio" value="1" {if $login_require_company=='1'}checked{/if} > <label>{#LOGIN_YES#}</label>
<input name="login_require_company" type="radio" value="0" {if $login_require_company!='1'}checked{/if}> <label>{#LOGIN_NO#}</label>
</td>
</tr>
<tr>
<td>{#LOGIN_SHOW_COMPANY#}</td>
<td>
<input name="login_require_company" type="radio" value="1" {if $login_require_company=='1'}checked{/if} > <label>{#LOGIN_YES#}</label>
<input name="login_require_company" type="radio" value="0" {if $login_require_company!='1'}checked{/if}> <label>{#LOGIN_NO#}</label>
</td>
</tr>
<tr>
<td>{#LOGIN_SHOW_COUNTRY#}</td>
<td>
<input name="login_require_country" type="radio" value="1" {if $login_require_country=='1'}checked{/if} > <label>{#LOGIN_YES#}</label>
<input name="login_require_country" type="radio" value="0" {if $login_require_country!='1'}checked{/if}> <label>{#LOGIN_NO#}</label>
</td>
</tr>
<tr>
<td width="200" valign="top">{#LOGIN_BLACK_DOMAINS#}</td>
<td>
<textarea style="width:400px; height:100px" name="login_deny_domain" id="login_deny_domain">{$login_deny_domain}</textarea>
</td>
</tr>
<tr>
<td width="200" valign="top">{#LOGIN_BLACK_DOMAINS#}</td>
<td>
<textarea style="width:400px; height:100px" name="login_deny_domain" id="login_deny_domain">{$login_deny_domain}</textarea>
</td>
</tr>
<tr>
<td width="200" valign="top">{#LOGIN_BLACK_EMAILS#}</td>
<td >
<textarea style="width:400px; height:100px" name="login_deny_email" id="login_deny_email">{$login_deny_email}</textarea>
</td>
</tr>
<tr>
<td width="200" valign="top">{#LOGIN_BLACK_EMAILS#}</td>
<td >
<textarea style="width:400px; height:100px" name="login_deny_email" id="login_deny_email">{$login_deny_email}</textarea>
</td>
</tr>
</table>
<div class="rowElem">
<input type="submit" id="apply_login_settings" class="basicBtn" style="margin-right: 15px;" value="{#LOGIN_BUTTON_SAVE#}" />
<a href="index.php?do=modules&amp;cp={$sess}" class="btn greyishBtn">{#LOGIN_SETTING_EXIT#}</a>
</div>
</form>
</div>
</table>
<div class="rowElem">
<input type="submit" class="basicBtn" style="margin-right: 15px;" value="{#LOGIN_BUTTON_SAVE#}" />
<a href="index.php?do=modules&amp;cp={$sess}" class="btn greyishBtn">{#LOGIN_SETTING_EXIT#}</a>
</div>
</form>
</div>
<script type="text/javascript">
$(document).ready(function() {
function saveLoginSettings() {
var form = $('#login_settings_form');
var actionUrl = form.attr('action');
var formData = form.serialize();
$.ajax({
type: "POST",
url: actionUrl,
data: formData,
beforeSend: function() {
$("#apply_login_settings").val("{#LOGIN_SETTING_SAVE_PR#}").attr("disabled", true);
},
success: function (data) {
if (data.trim() === "success") {
$.jGrowl("{#LOGIN_SETTING_SAVE#}", { theme: "accept", life: 3000 });
} else {
$.jGrowl("Ошибка: " + data, { theme: "error", life: 5000 });
}
},
error: function () {
$.jGrowl("{#LOGIN_SETTING_SAVE_ERR#}", { theme: "error" });
},
complete: function() {
$("#apply_login_settings").val("{#LOGIN_BUTTON_SAVE#}").attr("disabled", false);
}
});
}
$('#login_settings_form').on('submit', function(e) {
e.preventDefault();
saveLoginSettings();
});
$(document).on('keydown', function(e) {
if ((e.ctrlKey || e.metaKey) && e.which === 83) {
e.preventDefault();
saveLoginSettings();
return false;
}
});
});
</script>

File diff suppressed because it is too large Load Diff

BIN
img/ajax-loader.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -4,7 +4,7 @@
$module = array(
'ModuleSysName' => 'login',
'ModuleVersion' => '2.26.1',
'ModuleVersion' => '3.31.1',
'ModuleAutor' => 'AVE.cms Team',
'ModuleCopyright' => '&copy; 2007-' . date('Y') . ' AVE.cms',
'ModuleStatus' => 1,

View File

@@ -18,7 +18,7 @@ LOGIN_AUTORIZATION = "Авторизация"
[displaypanel]
LOGIN_ADMIN_LINK = "Панель управления"
LOGIN_CHANGE_DETAILS = "Настройки профиля"
LOGIN_CHANGE_DETAILS = "Редактировать профиль"
LOGIN_CHANGE_LINK = "Сменить пароль"
LOGIN_DELETE_LINK = "Удалить аккаунт"
LOGIN_LOGOUT_LINK = "Выйти"
@@ -41,6 +41,10 @@ LOGIN_YOUR_PHONE = "Контактный телефон:"
LOGIN_YOUR_STREET = "Улица "
LOGIN_YOUR_TOWN = "Город:"
LOGIN_YOUR_ZIP = "Почтовый индекс"
LOGIN_CHANGE_DETAILS = "Редактировать профиль"
LOGIN_CHANGE_SAVE = "Изменения сохранены!"
LOGIN_CHANGE_UPD = "Ваш профиль был успешно обновлен."
LOGIN_CHANGE_CLOSE = "Закрыть"
[loginprocess]
LOGIN_BUTTON_ENTER = "Войти"
@@ -76,6 +80,12 @@ LOGIN_MESSAGE_TEXT = "Процесс регистрации почти з
LOGIN_NOT_ACTIVE = "В настоящий момент регистрация пользователей временно отключена."
LOGIN_PASSWORD = "Пароль:"
LOGIN_REGISTER_OK = "Регистрация успешно завершена"
LOGIN_REGISTER_OK_SP = "Если письмо не пришло в течение 5 минут, проверьте папку <strong>Спам</strong>."
LOGIN_REGISTER_OK_SP_M = "На главную"
LOGIN_REGISTER_OK_SP_L = "Вы будете перенаправлены на предыдущую страницу через несколько секунд..."
LOGIN_REGISTER_OK_SP_N = "Не получили письмо? Проверьте папку «Спам» или"
LOGIN_REGISTER_OK_SP_O = "обновите страницу"
LOGIN_SECURITY_CODE = "Защитный код:"
LOGIN_SECURITY_CODER = "Введите код:"
LOGIN_SUBJECT_ADMIN = "Регистрация нового пользователя"
@@ -107,18 +117,23 @@ LOGIN_YOUR_LOGIN = "Логин:"
LOGIN_YOUR_MAIL = "E-mail:"
LOGIN_TEXT_AUTHORIZATION = "Информация для авторизации"
LOGIN_TEXT_USER_INFO = "Персональная информация"
LOGIN_WRONG_FIELD_LOGIN = "Только латинские буквы (A-Z), цифры, символы подчеркивания (_) или дефис (-)."
LOGIN_CAPTCHA_UPD = "Кликните на картинку, если код неразборчив"
LOGIN_WRONG_COUNTRY_EMPTY = "Пожалуйста, выберите страну."
[passwordreminder]
LOGIN_BUTTON_NEWPASS = "Выслать пароль"
LOGIN_YOUR_MAIL = "E-mail:"
LOGIN_ENTER_EMAIL = "Пожалуйста, укажите Ваш E-mail."
LOGIN_MESSAGE_6 = "Здравствуйте %NAME%.%N%Вы запросили изменения Вашего пароля на сайте %HOST%.%N%%N%Ваш новый пароль: %PASS%%N%%N%Пожалуйста, перейдите по ссылке указанной ниже, чтобы подтвердить смену пароля:%N%%LINK%%N%%N%Если Вы не запрашивали изменение пароля и данное сообщение сообщение попало к Вам по ошибке, удалите его. "
LOGIN_MESSAGE_6 = "Здравствуйте %NAME%.%N%Вы запросили изменения Вашего пароля на сайте %HOST%.%N%%N%Ваш новый пароль: %PASS%%N%%N%Пожалуйста, перейдите по ссылке указанной ниже, чтобы активировать новый пароль:%N%%LINK%%N%%N%Если Вы не запрашивали изменение пароля и данное сообщение сообщение попало к Вам по ошибке, удалите его. "
LOGIN_PASSWORD_RESTOR = "Ваш пароль успешно изменён."
LOGIN_REMIND = "Восстановление пароля"
LOGIN_REMINDER_INFO2 = "Пожалуйста, укажите E-mail адрес, который был использован при регистрации. На указанный E-mail будет выслан новый пароль."
LOGIN_REMINDER_INFO4 = "Пожалуйста, укажите E-mail адрес"
LOGIN_REMINDER_INFO3 = "Новый пароль выслан на указанный E-mail адрес."
LOGIN_SUBJECT_REMINDER = "Ваш новый пароль"
LOGIN_SUBJECT_REMIND_OK = "Теперь вы можете использовать свой новый пароль для доступа к сайту."
LOGIN_SUBJECT_REMIND_AK = "Войти в аккаунт"
[passwordchange]
LOGIN_CHANGE_PASSWORD = "Изменить пароль"
@@ -134,12 +149,14 @@ LOGIN_OLD_PASSWORD = "Текущий пароль:"
LOGIN_OLD_PASS_EMPTY = "Ошибка! Вы не указали текущий пароль. Пожалуйста, правильность ввода."
LOGIN_PASSWORDS_NOEQU = "Введенные пароли не совпадают. Пожалуйста, проверьте правильность ввода."
LOGIN_PASSWORD_CHANGE = "Смена текущего пароля"
LOGIN_PASSWORD_INFO = "Пожалуйста, укажите новый пароль, который Вы хотите использовать. Пароль должн быть не менее 5 символов."
LOGIN_PASSWORD_INFO = "Пожалуйста, укажите новый пароль, который Вы хотите использовать. Пароль должен содержать не менее 5 символов."
LOGIN_PASSWORD_OK = "Пароль успешно изменён!"
LOGIN_WRONG_EQU_PASS = "Значение нового пароля и подтверждающего не совпадают"
LOGIN_WRONG_OLD_PASS = "Текущий пароль указан неверно."
LOGIN_WRONG_SHORT_PASS = "Длина пароля менее 5 символов."
LOGIN_WRONG_SYM_PASS = "Пароль содержит недопустимые символы."
LOGIN_AKTIV_NEW_PASS = "Ваш новый пароль активирован."
LOGIN_NEW_PASS_REDIR = "В профиль"
[delaccount]
LOGIN_ADMIN_ACCOUNT = "Извините, но Вы не можете удалить свой аккаунт, так как Вы являетесь Администратором. Пожалуйста, обратитесь к Главному Администратору сайта."
@@ -149,6 +166,10 @@ LOGIN_DELETE_CONFIRM = "Да, я согласен"
LOGIN_DELETE_INFO = "Все готово для окончательного удаления Вашего аккаунта из системы. Помните, что удалив свой аккаунт, Вы потеряете доступ к разделам сайта, разрешенным для просмотра только зарегистрированным пользователям. Вы уверены, что хотите удалить свой аккаунт?"
LOGIN_DELETE_OK = "Ваш аккаунт успешно удалён."
LOGIN_DELETE_WARNING = "Внимание!"
LOGIN_DELETE_INF_DEL = "Мы удалим все ваши персональные данные в соответствии с требованиями законодательства"
LOGIN_DELETE_INF_DEL_A = "Нам жаль, что вы уходите. Сессия будет завершена."
LOGIN_DELETE_INF_DEL_L = "На главную"
LOGIN_DELETE_INF_DEL_C = "Отмена"
[myprofile]
LOGIN_BUTTON_CHANGE = "Сохранить изменения"
@@ -185,6 +206,9 @@ LOGIN_YOUR_PHONE = "Контактный телефон:"
LOGIN_YOUR_STREET = "Улица "
LOGIN_YOUR_TOWN = "Город:"
LOGIN_YOUR_ZIP = "Почтовый индекс"
LOGIN_YOUR_PRIVAT_DATA = "Личные данные"
LOGIN_YOUR_PRIVAT_ADR = "Адрес проживания"
LOGIN_YOUR_PRIVAT_JOB = "Связь и работа"
[showconfig]
LOGIN_BLACK_DOMAINS = "Чёрный список доменов:<br /><small>Укажите домены, с которых запрещена регистрация. Один домен на одну строку.</small>"
@@ -206,3 +230,7 @@ LOGIN_TYPE_NOW = "Сразу же, после регистрации"
LOGIN_USE_SCODE = "Использовать защитный код?"
LOGIN_YES = "Да"
LOGIN_SETTING_EXIT = "Выйти из настроек"
LOGIN_SETTING_SAVE = "Настройки успешно сохранены (Ctrl+S)"
LOGIN_SETTING_SAVE_ERR = "Ошибка при сохранении настроек"
LOGIN_SETTING_SAVE_PR = "Сохранение..."
LOGIN_SHOW_COUNTRY = "Показывать поле Страна проживания?"

View File

@@ -3,104 +3,87 @@
if (! defined('BASE_DIR'))
exit;
// Фикс для ядра: инициализируем константы заранее, чтобы PHP 8.4 не ругался на null в htmlspecialchars
if (!defined('MODULE_TITLE')) define('MODULE_TITLE', '');
if (!defined('MODULE_DESCRIPTION')) define('MODULE_DESCRIPTION', '');
if (!defined('MODULE_KEYWORDS')) define('MODULE_KEYWORDS', '');
function mod_login ()
{
global $AVE_Template;
require_once(BASE_DIR . '/modules/login/class/login.php');
new Login;
// Создаем экземпляр класса
$login_obj = new Login;
// Если прошли по ссылке, для показа формы, убираем вывод тега
if (isset($_REQUEST['module']) && $_REQUEST['module'] == 'login' && $_REQUEST['action'] == 'form')
// Если прошли по ссылке для показа формы, убираем вывод тега [mod_login]
if (isset($_REQUEST['module']) && $_REQUEST['module'] == 'login' && ($_REQUEST['action'] ?? '') == 'form')
return false;
$tpl_dir = BASE_DIR . '/modules/login/public/';
$lang_file = BASE_DIR . '/modules/login/lang/' . $_SESSION['user_language'] . '.txt';
// PHP 8.4 фикс: используем оператор ?? на случай, если сессия пуста
$lang_file = BASE_DIR . '/modules/login/lang/' . ($_SESSION['user_language'] ?? 'ru') . '.txt';
if (isset($_SESSION['user_id']) && isset($_SESSION['user_pass']))
if (isset($_SESSION['user_id']) && isset($_SESSION['user_pass']))
{
$avatar = getAvatar($_SESSION['user_id'],180);
$avatar = getAvatar((int)$_SESSION['user_id'], 180);
$abs_path = (defined('ABS_PATH')) ? ABS_PATH : '/';
// Если аватар пустой или это заглушка (иконка), подставляем default.png
if (empty($avatar) || strpos($avatar, 'user.png') !== false) {
$avatar = $abs_path . 'uploads/avatars/default.png';
}
$AVE_Template->assign('avatar', $avatar);
$AVE_Template->config_load($lang_file, 'displaypanel');
$AVE_Template->display($tpl_dir . 'panel.tpl');
}
else
{
$active = Login::settings('login_status');
{
// Используем объект для вызова настроек, если метод не статичный
$active = Login::settings('login_status');
$AVE_Template->config_load($lang_file, 'loginform');
$AVE_Template->assign('active', $active);
$AVE_Template->display($tpl_dir . 'form.tpl');
}
$AVE_Template->config_load($lang_file, 'loginform');
$AVE_Template->assign('active', $active);
$AVE_Template->display($tpl_dir . 'form.tpl');
}
return true;
}
//=======================================================
// Public functions
// Public functions (Когда заходим по прямой ссылке на модуль)
//=======================================================
if (! defined('ACP') && isset($_REQUEST['module']) && $_REQUEST['module'] == 'login' && ! empty($_REQUEST['action']))
{
require_once(BASE_DIR . '/modules/login/class/login.php');
new Login;
$login_obj = new Login;
Login::$_tpl_dir = BASE_DIR . '/modules/login/public/';
Login::$_lang_file = BASE_DIR . '/modules/login/lang/' . ($_SESSION['user_language'] ?? 'ru') . '.txt';
Login::$_lang_file = BASE_DIR . '/modules/login/lang/' . $_SESSION['user_language'] . '.txt';
// В PHP 8+ вызов Login::method() может выдать ошибку, если методы в классе не static.
// Поэтому мы используем созданный $login_obj->method()
switch ($_REQUEST['action'])
{
case 'form':
Login::form();
break;
case 'authorize':
Login::authorize();
break;
case 'logout':
Login::logout();
break;
case 'register':
Login::register();
break;
case 'reminder':
Login::reminder();
break;
case 'change':
Login::change();
break;
case 'delete':
Login::delete();
break;
case 'profile':
Login::profile();
break;
case 'info':
Login::info();
break;
case 'checkusername':
Login::checkusername();
break;
case 'checkemail':
Login::checkemail();
break;
case 'form': $login_obj->form(); break;
case 'authorize': $login_obj->authorize(); break;
case 'logout': $login_obj->logout(); break;
case 'register': $login_obj->register(); break;
case 'reminder': $login_obj->reminder(); break;
case 'change': $login_obj->change(); break;
case 'delete': $login_obj->delete(); break;
case 'profile': $login_obj->profile(); break;
case 'info': $login_obj->info(); break;
case 'checkusername': $login_obj->checkusername(); break;
case 'checkemail': $login_obj->checkemail(); break;
}
}
//=======================================================
// The control module in the admin panel
//=======================================================
@@ -112,11 +95,10 @@
{
require_once(BASE_DIR . '/modules/login/class/login.php');
new Login;
$login_obj = new Login;
Login::$_tpl_dir = BASE_DIR . '/modules/login/admin/';
$lang_file = BASE_DIR . '/modules/login/lang/' . $_SESSION['admin_language'] . '.txt';
$lang_file = BASE_DIR . '/modules/login/lang/' . ($_SESSION['admin_language'] ?? 'ru') . '.txt';
$AVE_Template->config_load($lang_file, 'showconfig');
$AVE_Template->assign('config_vars', $AVE_Template->get_config_vars());
@@ -124,9 +106,8 @@
switch($_REQUEST['moduleaction'])
{
case '1':
Login::admin();
$login_obj->admin();
break;
}
}
?>

View File

@@ -1,71 +1,147 @@
<script type="text/javascript">
function check_password() {ldelim}
if (document.getElementById('o_pass').value == '') {ldelim}
alert("{#LOGIN_OLD_PASS_EMPTY#}");
document.getElementById('o_pass').focus();
return false;
{rdelim}
const errorBlock = document.getElementById('js-error-block');
const errorText = document.getElementById('js-error-text');
errorBlock.classList.add('d-none');
let message = "";
let targetField = null;
if (document.getElementById('n_pass').value == '') {ldelim}
alert("{#LOGIN_NEW_PASS_EMPTY#}");
document.getElementById('n_pass').focus();
return false;
{rdelim}
if (document.getElementById('o_pass').value == '') {ldelim}
message = "{#LOGIN_OLD_PASS_EMPTY#}";
targetField = 'o_pass';
{rdelim}
else if (document.getElementById('n_pass').value == '') {ldelim}
message = "{#LOGIN_NEW_PASS_EMPTY#}";
targetField = 'n_pass';
{rdelim}
else if (document.getElementById('n_pass_c').value == '') {ldelim}
message = "{#LOGIN_NEW_PASSC#}";
targetField = 'n_pass_c';
{rdelim}
else if (document.getElementById('n_pass').value != document.getElementById('n_pass_c').value) {ldelim}
message = "{#LOGIN_PASSWORDS_NOEQU#}";
targetField = 'n_pass';
{rdelim}
if (document.getElementById('n_pass_c').value == '') {ldelim}
alert("{#LOGIN_NEW_PASSC#}");
document.getElementById('n_pass_c').focus();
return false;
{rdelim}
if (message !== "") {ldelim}
errorText.innerText = message;
errorBlock.classList.remove('d-none');
errorBlock.classList.add('animate__shakeX');
setTimeout(() => errorBlock.classList.remove('animate__shakeX'), 500);
document.getElementById(targetField).focus();
return false;
{rdelim}
if (document.getElementById('n_pass').value != document.getElementById('n_pass_c').value) {ldelim}
alert("{#LOGIN_PASSWORDS_NOEQU#}");
document.getElementById('n_pass').focus();
return false;
{rdelim}
return true;
return true;
{rdelim}
</script>
<h2 id="page-heading">{#LOGIN_PASSWORD_CHANGE#}</h2>
<div class="container py-4">
<div class="row justify-content-center">
<div class="col-lg-6">
<div id="js-error-block" class="alert alert-danger shadow-sm border-0 mb-4 d-none animate__animated">
<div class="d-flex align-items-center">
<i class="bi bi-exclamation-circle fs-5 me-3"></i>
<div id="js-error-text"></div>
</div>
</div>
<div class="block" id="forms">
{if $changeok==1}
<fieldset>
<p>{#LOGIN_PASSWORD_OK#}</p>
</fieldset>
{else}
<form method="post" action="{$ABS_PATH}index.php?module=login&action=change" onsubmit="return check_password();">
<input type="hidden" name="sub" value="send" />
{if $changeok == 1}
<div class="alert alert-success shadow-sm border-0 mb-4 animate__animated animate__fadeIn">
<div class="d-flex align-items-center">
<i class="bi bi-check-circle-fill fs-2 me-3"></i>
<div>
<h4 class="h6 mb-1 fw-bold">{#LOGIN_PASSWORD_OK#}</h4>
<p class="mb-0 small opacity-75">{#LOGIN_AKTIV_NEW_PASS#}</p>
</div>
<a href="index.php?module=login&action=info" class="btn btn-sm btn-success ms-auto shadow-sm">{#LOGIN_NEW_PASS_REDIR#}</a>
</div>
</div>
{else}
<p>{#LOGIN_PASSWORD_INFO#}</p>
<div class="card shadow-sm border-0">
<div class="card-header bg-primary text-white py-3 d-flex justify-content-between align-items-center">
<h2 class="h5 mb-0"><i class="bi bi-shield-lock me-2"></i> {#LOGIN_PASSWORD_CHANGE#}</h2>
<a href="index.php?module=login&action=info" class="btn btn-outline-light btn-sm fw-bold shadow-sm">
<i class="bi bi-x-lg me-1"></i> {#LOGIN_CANCEL#}
</a>
</div>
{if $errors}
<p>{#LOGIN_FOUND_ERROR#}</p>
<ul>
{foreach from=$errors item=error}
<li class="regerror">{$error}</li>
{/foreach}
</ul>
{/if}
<div class="card-body p-4">
<p class="text-muted small mb-4">{#LOGIN_PASSWORD_INFO#}</p>
<fieldset class="login">
<p>
<label>{#LOGIN_OLD_PASSWORD#}</label>
<input type="password" name="old_pass" id="o_pass" />
</p>
<p>
<label>{#LOGIN_NEW_PASSWORD#}</label>
<input type="password" name="new_pass" id="n_pass" />
</p>
<p>
<label>{#LOGIN_NEW_PASSWORD_C#}</label>
<input type="password" name="new_pass_c" id="n_pass_c" />
</p>
<input class="login button" type="submit" value="{#LOGIN_CHANGE_PASSWORD#}" />
</fieldset>
</form>
{/if}
{if $errors}
<div class="alert alert-warning border-0 shadow-sm mb-4">
<ul class="mb-0 small">
{foreach from=$errors item=error}
<li><i class="bi bi-chevron-right me-1"></i> {$error}</li>
{/foreach}
</ul>
</div>
{/if}
<form method="post" action="{$ABS_PATH}index.php?module=login&action=change" onsubmit="return check_password();">
<input type="hidden" name="sub" value="send" />
<div class="mb-3">
<label class="form-label small fw-bold text-muted text-uppercase">{#LOGIN_OLD_PASSWORD#}</label>
<div class="input-group">
<span class="input-group-text bg-light border-end-0"><i class="bi bi-key text-muted"></i></span>
<input type="password" name="old_pass" id="o_pass" class="form-control border-start-0" />
<button class="btn btn-outline-secondary border-start-0 toggle-password" type="button"><i class="bi bi-eye"></i></button>
</div>
</div>
<hr class="my-4 opacity-25">
<div class="mb-3">
<label class="form-label small fw-bold text-muted text-uppercase">{#LOGIN_NEW_PASSWORD#}</label>
<div class="input-group">
<span class="input-group-text bg-light border-end-0"><i class="bi bi-lock text-primary"></i></span>
<input type="password" name="new_pass" id="n_pass" class="form-control border-start-0" />
<button class="btn btn-outline-secondary border-start-0 toggle-password" type="button"><i class="bi bi-eye"></i></button>
</div>
</div>
<div class="mb-4">
<label class="form-label small fw-bold text-muted text-uppercase">{#LOGIN_NEW_PASSWORD_C#}</label>
<div class="input-group">
<span class="input-group-text bg-light border-end-0"><i class="bi bi-check-all text-primary"></i></span>
<input type="password" name="new_pass_c" id="n_pass_c" class="form-control border-start-0" />
<button class="btn btn-outline-secondary border-start-0 toggle-password" type="button"><i class="bi bi-eye"></i></button>
</div>
</div>
<div class="d-grid">
<button class="btn btn-primary btn-lg shadow-sm fw-bold" type="submit">
{#LOGIN_CHANGE_PASSWORD#}
</button>
</div>
</form>
</div>
</div>
{/if}
</div>
</div>
</div>
<script>
document.querySelectorAll('.toggle-password').forEach(button => {
button.addEventListener('click', function() {
const input = this.parentElement.querySelector('input');
const icon = this.querySelector('i');
if (input.type === 'password') {
input.type = 'text';
icon.classList.replace('bi-eye', 'bi-eye-slash');
} else {
input.type = 'password';
icon.classList.replace('bi-eye-slash', 'bi-eye');
}
});
});
</script>

View File

@@ -1,29 +1,80 @@
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-7">
{* Заголовок страницы *}
<h2 class="h3 mb-4 fw-bold text-dark text-center" id="page-heading">
{#LOGIN_DELETE_ACCOUNT#}
</h2>
<h2 id="page-heading">{#LOGIN_DELETE_ACCOUNT#}</h2>
<div class="card shadow-sm border-0 overflow-hidden">
{if $admin == 1}
{* Случай, если админ пытается удалить себя *}
<div class="card-body p-5 text-center">
<div class="mb-4 text-warning">
<i class="bi bi-shield-lock" style="font-size: 3rem;"></i>
</div>
<h4 class="fw-bold">{#LOGIN_DELETE_WARNING#}</h4>
<div class="alert alert-warning d-inline-block mt-3 mb-0 px-4">
<i class="bi bi-exclamation-triangle me-2"></i> {#LOGIN_ADMIN_ACCOUNT#}
</div>
</div>
{else}
{if $delok == 1}
{* Сообщение об успешном удалении *}
<div class="card-body p-5 text-center">
<div class="mb-4 text-success">
<i class="bi bi-check-circle" style="font-size: 4rem;"></i>
</div>
<h4 class="fw-bold mb-3">{#LOGIN_DELETE_OK#}</h4>
<p class="text-muted">{#LOGIN_DELETE_INF_DEL_A#}</p>
<a href="{$ABS_PATH}index.php?id=1" class="btn btn-outline-primary mt-3">{#LOGIN_DELETE_INF_DEL_L#}</a>
</div>
{else}
{* Форма подтверждения удаления *}
<div class="card-header bg-danger text-white py-3">
<h5 class="card-title mb-0 d-flex align-items-center">
<i class="bi bi-exclamation-octagon me-2"></i> {#LOGIN_DELETE_WARNING#}
</h5>
</div>
<div class="card-body p-4 p-md-5">
<p class="fs-5 text-secondary mb-4">
{#LOGIN_DELETE_INFO#}
</p>
<div class="block" id="forms">
{if $admin == 1}
<fieldset class="login">
<legend>{#LOGIN_DELETE_WARNING#}</legend>
<p class="regerror">{#LOGIN_ADMIN_ACCOUNT#}</p>
</fieldset>
{else}
{if $delok == 1}
<fieldset class="login">
<p>{#LOGIN_DELETE_OK#}</p>
</fieldset>
{else}
<fieldset class="login">
<legend>{#LOGIN_DELETE_WARNING#}</legend>
<p>{#LOGIN_DELETE_INFO#}</p>
<form method="post" action="index.php?module=login&action=delete">
<input type="hidden" name="send" value="1" />
<input name="confirm" type="checkbox" value="1" />
{#LOGIN_DELETE_CONFIRM#}<br />
<br />
<input class="confirm button" value="{#LOGIN_DELETE_BUTTON#}" type="submit">
</form>
</fieldset>
{/if}
{/if}
<form method="post" action="index.php?module=login&action=delete" class="needs-validation">
<input type="hidden" name="send" value="1" />
<div class="form-check p-3 mb-4 border rounded bg-light transition-hover">
<input class="form-check-input ms-0 me-3" name="confirm" type="checkbox" value="1" id="confirmDelete" required>
<label class="form-check-label fw-bold text-danger" for="confirmDelete">
{#LOGIN_DELETE_CONFIRM#}
</label>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a href="{$ABS_PATH}index.php?module=login&action=profile" class="btn btn-light px-4">{#LOGIN_DELETE_INF_DEL_C#}</a>
<button class="btn btn-danger btn-lg px-5 shadow-sm fw-bold" type="submit">
{#LOGIN_DELETE_BUTTON#}
</button>
</div>
</form>
</div>
{/if}
{/if}
</div>
{if $delok != 1}
<div class="text-center mt-4 text-muted small">
<i class="bi bi-info-circle me-1"></i> {#LOGIN_DELETE_INF_DEL#}.
</div>
{/if}
</div>
</div>
</div>
<style>
.transition-hover { transition: background-color 0.2s ease; cursor: pointer; }
.form-check:hover { background-color: #fff5f5 !important; border-color: #feb2b2 !important; }
.form-check-input:checked ~ .form-check-label { color: #c53030 !important; }
</style>

View File

@@ -1,35 +1,61 @@
<form method="post" action="{$ABS_PATH}index.php?module=login&action=authorize">
<div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title">{#LOGIN_AUTORIZATION#}</h5>
<p class="card-text text-muted">{#LOGIN_PLEASE_LOGON#}</p>
</div>
<div class="card-body">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="user_login">
<i class="fa fa-user" style="width: 20px;"></i>
</span>
</div>
<input type="text" name="user_login" class="form-control" placeholder="" aria-label="user_login" aria-describedby="user_login" value="{$smarty.request.user_login|escape|stripslashes}">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="user_pass">
<i class="fa fa-eye-slash" style="width: 20px;"></i>
</span>
</div>
<input type="password" name="user_pass" class="form-control" placeholder="" aria-label="user_pass" aria-describedby="user_pass" value="">
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="keep_in" id="keep_in" value="1">
<label class="form-check-label" for="keep_in">
{#LOGIN_SAVE_COOKIE#} <span title="{#LOGIN_SAVE_INFO#}"><i class="fa fa-question"></i></span>
</label>
</div>
<button type="submit" class="btn btn-primary btn-block mb-3">{#LOGIN_BUTTON_LOGIN#}</button>
<a title="{#LOGIN_PASSWORD_REMIND#}" href="{$ABS_PATH}index.php?module=login&action=reminder">{#LOGIN_PASSWORD_REMIND#}</a>&nbsp;
{if $active == 1}<a title="{#LOGIN_NEW_REGISTER#}" href="{$ABS_PATH}index.php?module=login&action=register">{#LOGIN_NEW_REGISTER#}</a>{/if}
</div>
</div>
</form>
{assign var="req_login" value=$smarty.request.user_login|default:''}
<div class="dropdown shadow-none">
<a class="nav-link dropdown-toggle text-white d-flex align-items-center"
href="#" id="loginDropdown" role="button" data-bs-toggle="dropdown"
data-bs-auto-close="outside" aria-expanded="false">
<img src="{$ABS_PATH}uploads/avatars/default.png"
alt="User"
class="rounded-circle me-2"
style="width: 24px; height: 24px; object-fit: cover; border: 1px solid rgba(255,255,255,0.2);">
{#LOGIN_AUTORIZATION#}
</a>
<div class="dropdown-menu dropdown-menu-end p-0 border-0 shadow-lg"
aria-labelledby="loginDropdown"
style="min-width: 320px; background: transparent; margin-top: 10px;">
<form method="post" action="{$ABS_PATH}index.php?module=login&action=authorize">
<div class="card border-0 shadow-sm">
<div class="card-body p-4">
<h5 class="card-title text-dark mb-1">{#LOGIN_AUTORIZATION#}</h5>
<p class="card-text text-muted small mb-3">{#LOGIN_PLEASE_LOGON#}</p>
<div class="input-group mb-3">
<span class="input-group-text bg-light border-end-0"><i class="bi bi-person text-muted"></i></span>
<input type="text" name="user_login" class="form-control border-start-0 ps-0"
placeholder="{#LOGIN_YOUR_LOGIN#}" value="{$req_login|escape|stripslashes}">
</div>
<div class="input-group mb-3">
<span class="input-group-text bg-light border-end-0"><i class="bi bi-lock text-muted"></i></span>
<input type="password" name="user_pass" class="form-control border-start-0 ps-0"
placeholder="{#LOGIN_PASSWORD#}">
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="keep_in" id="keep_in_header" value="1">
<label class="form-check-label small text-dark" for="keep_in_header">
{#LOGIN_SAVE_COOKIE#}
</label>
</div>
<button type="submit" class="btn btn-primary w-100 mb-3 py-2 fw-bold">
{#LOGIN_BUTTON_LOGIN#}
</button>
<div class="d-flex justify-content-between border-top pt-3 small">
<a href="{$ABS_PATH}index.php?module=login&action=reminder" class="text-decoration-none">
{#LOGIN_PASSWORD_REMIND#}
</a>
<a href="{$ABS_PATH}index.php?module=login&action=register" class="text-decoration-none fw-bold">
{#LOGIN_NEW_REGISTER#}
</a>
</div>
</div>
</div>
</form>
</div>
</div>

View File

@@ -1,44 +1,89 @@
<h2 id="page-heading">{#LOGIN_USER_PROFILE#}</h2>
{if $user->avatar}<img src="{$user->avatar}" />{/if}
<div class="block" id="forms">
<p>{#LOGIN_DETAILS_INFO#}</p>
<div class="container py-4">
<div class="row justify-content-center">
<div class="col-lg-9">
{if isset($smarty.get.save) && $smarty.get.save == 'ok'}
<div class="alert alert-success shadow-sm border-0 mb-4 d-flex align-items-center animate__animated animate__fadeIn">
<i class="bi bi-check-circle-fill fs-4 me-3"></i>
<div>
<h4 class="h6 mb-1 fw-bold">{#LOGIN_CHANGE_SAVE#}</h4>
<p class="mb-0 small text-muted">{#LOGIN_CHANGE_UPD#}</p>
</div>
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{/if}
<fieldset class="login">
<p>
<label>{#LOGIN_YOUR_FIRSTNAME#}</label>
{$user->firstname|escape|stripslashes}
</p>
<p>
<label>{#LOGIN_YOUR_LASTNAME#}</label>
{$user->lastname|escape|stripslashes}
</p>
<p>
<label>{#LOGIN_YOUR_BIRTHDAY#} {#LOGIN_DATE_FORMAT#}</label>
{$user->birthday|escape|stripslashes}
</p>
<p>
<label>{#LOGIN_YOUR_TOWN#}</label>
{$user->city|escape|stripslashes}
</p>
<p>
<label>{#LOGIN_YOUR_ZIP#}</label>
{$user->zipcode|default:$row.zipcode|escape|stripslashes}
</p>
<p>
<label>{#LOGIN_YOUR_STREET#}</label>
{$user->street|escape|stripslashes}
</p>
<p>
<label>{#LOGIN_YOUR_HOUSE#}</label>
{$user->street_nr|escape|stripslashes}
</p>
<p>
<label>{#LOGIN_YOUR_PHONE#}</label>
{$user->phone|default:$row.phone|escape|stripslashes}
</p>
<p>
<label>{#LOGIN_YOUR_COMPANY#}</label>
{$user->company|escape|stripslashes}
</p>
</fieldset>
</div>
<div class="card shadow-sm border-0 overflow-hidden">
<div class="card-header bg-primary text-white py-3 d-flex justify-content-between align-items-center">
<h2 class="h5 mb-0"><i class="bi bi-person-badge me-2"></i> {#LOGIN_USER_PROFILE#}</h2>
<div class="d-flex gap-2">
<a href="{$ABS_PATH}index.php?module=login&action=profile" class="btn btn-light btn-sm fw-bold shadow-sm">
<i class="bi bi-pencil-square me-1"></i> {#LOGIN_CHANGE_DETAILS#}
</a>
<a href="{$ABS_PATH}index.php?id=1" class="btn btn-outline-light btn-sm fw-bold shadow-sm">
<i class="bi bi-x-lg me-1"></i> {#LOGIN_CHANGE_CLOSE#}
</a>
</div>
</div>
<div class="card-body p-0">
<div class="row g-0">
<div class="col-md-4 bg-light border-end p-4 text-center">
<div class="mb-3">
{if $user->avatar|default:''}
<img src="{$user->avatar}" class="img-thumbnail rounded-circle shadow-sm" style="width: 140px; height: 140px; object-fit: cover;" />
{else}
<div class="bg-white rounded-circle d-inline-flex align-items-center justify-content-center shadow-sm border" style="width: 140px; height: 140px;">
<i class="bi bi-person text-muted" style="font-size: 4rem;"></i>
</div>
{/if}
</div>
<h3 class="h5 fw-bold mb-1">{$user->firstname|default:''|escape} {$user->lastname|default:''|escape}</h3>
<p class="text-muted small">{$user->email|default:''|escape}</p>
<hr>
<p class="small text-muted mb-0">{#LOGIN_DETAILS_INFO#}</p>
</div>
<div class="col-md-8 p-4">
<div class="table-responsive">
<table class="table table-borderless align-middle mb-0">
<tbody>
<tr>
<th class="text-muted small fw-normal py-2" width="45%"><i class="bi bi-calendar3 me-2 text-primary"></i> {#LOGIN_YOUR_BIRTHDAY#}</th>
<td class="py-2">{$user->birthday|default:'—'|escape}</td>
</tr>
<tr>
<th class="text-muted small fw-normal py-2"><i class="bi bi-globe2 me-2 text-primary"></i> {#LOGIN_YOUR_COUNTRY#}</th>
<td class="py-2">{$user->country|default:'—'|escape}</td>
</tr>
<tr>
<th class="text-muted small fw-normal py-2"><i class="bi bi-building me-2 text-primary"></i> {#LOGIN_YOUR_TOWN#}</th>
<td class="py-2">{$user->city|default:'—'|escape}</td>
</tr>
<tr>
<th class="text-muted small fw-normal py-2"><i class="bi bi-geo-alt me-2 text-primary"></i> {#LOGIN_YOUR_ZIP#}</th>
<td class="py-2">{$user->zipcode|default:'—'|escape}</td>
</tr>
<tr>
<th class="text-muted small fw-normal py-2"><i class="bi bi-map me-2 text-primary"></i> {#LOGIN_YOUR_STREET#}</th>
<td class="py-2">{$user->street|default:''|escape}{if $user->street_nr|default:''}, {$user->street_nr|escape}{/if}</td>
</tr>
<tr class="border-top"><td colspan="2" class="p-0" style="height:10px;"></td></tr>
<tr>
<th class="text-muted small fw-normal py-2"><i class="bi bi-telephone me-2 text-primary"></i> {#LOGIN_YOUR_PHONE#}</th>
<td class="py-2">{$user->phone|default:'—'|escape}</td>
</tr>
<tr>
<th class="text-muted small fw-normal py-2"><i class="bi bi-briefcase me-2 text-primary"></i> {#LOGIN_YOUR_COMPANY#}</th>
<td class="py-2">{$user->company|default:'—'|escape}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,15 +1,45 @@
<div class="card shadow-sm">
{if $avatar}<img src="{$avatar}" class="card-img-top" alt="">{/if}
<div class="card-body">
<h5 class="card-title">{#LOGIN_WELCOME_TEXT#}</h5>
<p class="card-text">{$smarty.session.user_name|escape}</p>
</div>
<div class="list-group list-group-flush">
<a href="{$ABS_PATH}index.php?module=login&action=profile" class="list-group-item list-group-item-action">{#LOGIN_CHANGE_DETAILS#}</a>
<a href="{$ABS_PATH}index.php?module=login&action=info" class="list-group-item list-group-item-action">{#LOGIN_USER_PROFILE#}</a>
<a href="{$ABS_PATH}index.php?module=login&action=change" class="list-group-item list-group-item-action">{#LOGIN_CHANGE_LINK#}</a>
{if check_permission("adminpanel")}<a href="{$ABS_PATH}admin/index.php" class="list-group-item list-group-item-action" target="_blank">{#LOGIN_ADMIN_LINK#}</a>{/if}
<a href="{$ABS_PATH}index.php?module=login&action=delete" class="list-group-item list-group-item-action">{#LOGIN_DELETE_LINK#}</a>
<a href="{$ABS_PATH}index.php?module=login&action=logout" class="list-group-item list-group-item-action">{#LOGIN_LOGOUT_LINK#}</a>
</div>
<div class="nav-item dropdown">
<a class="nav-link dropdown-toggle text-success fw-bold d-flex align-items-center"
href="#" id="userMenuPanel" role="button" data-bs-toggle="dropdown" aria-expanded="false">
{if $avatar}
{* Используем переменную {$avatar}, так как она прописана в PHP *}
<img src="{$avatar}"
class="rounded-circle me-2 border border-2 border-success border-opacity-25"
style="width: 28px; height: 28px; object-fit: cover;"
alt="User">
{else}
<i class="bi bi-person-circle me-2"></i>
{/if}
<span>{$smarty.session.user_name|escape}</span>
</a>
<ul class="dropdown-menu dropdown-menu-end shadow-lg border-0 py-2"
aria-labelledby="userMenuPanel"
style="min-width: 220px; margin-top: 10px;">
<li class="px-3 py-2 border-bottom mb-2 d-flex align-items-center">
{if $avatar}
<img src="{$avatar}" class="rounded-circle me-2" style="width: 32px; height: 32px; object-fit: cover;">
{/if}
<div>
<small class="text-muted d-block">{#LOGIN_WELCOME_TEXT#},</small>
<span class="fw-bold text-dark">{$smarty.session.user_name|escape}</span>
</div>
</li>
{* ... дальше твои пункты меню без изменений ... *}
<li><a class="dropdown-item py-2" href="{$ABS_PATH}index.php?module=login&action=profile"><i class="bi bi-gear me-2 text-muted"></i> {#LOGIN_CHANGE_DETAILS#}</a></li>
<li><a class="dropdown-item py-2" href="{$ABS_PATH}index.php?module=login&action=info"><i class="bi bi-person-vcard me-2 text-muted"></i> {#LOGIN_USER_PROFILE#}</a></li>
<li><a class="dropdown-item py-2" href="{$ABS_PATH}index.php?module=login&action=change"><i class="bi bi-key me-2 text-muted"></i> {#LOGIN_CHANGE_LINK#}</a></li>
{if check_permission("adminpanel")}
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item py-2 text-primary" href="{$ABS_PATH}admin/index.php" target="_blank"><i class="bi bi-sliders me-2"></i> {#LOGIN_ADMIN_LINK#}</a></li>
{/if}
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item py-2 text-danger" href="{$ABS_PATH}index.php?module=login&action=delete"><i class="bi bi-box-arrow-right me-2"></i> {#LOGIN_DELETE_LINK#}</a></li>
<li><a class="dropdown-item py-2 text-danger" href="{$ABS_PATH}index.php?module=login&action=logout"><i class="bi bi-box-arrow-right me-2"></i> {#LOGIN_LOGOUT_LINK#}</a></li>
</ul>
</div>

View File

@@ -1,44 +1,69 @@
<form method="post" action="{$ABS_PATH}index.php?module=login&action=authorize">
<div class="card shadow-sm w-25">
<div class="card-body">
<h5 class="card-title">{#LOGIN_AUTORIZATION#}</h5>
<p class="card-text text-muted">{#LOGIN_PLEASE_LOGON#}</p>
</div>
<div class="card-body">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="user_login">
<i class="fa fa-user" style="width: 20px;"></i>
</span>
</div>
<input type="text" name="user_login" class="form-control" placeholder="" aria-label="user_login" aria-describedby="user_login" value="{$smarty.request.user_login|escape|stripslashes}">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="user_pass">
<i class="fa fa-eye-slash" style="width: 20px;"></i>
</span>
</div>
<input type="password" name="user_pass" class="form-control" placeholder="" aria-label="user_pass" aria-describedby="user_pass" value="">
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="keep_in" id="keep_in" value="1">
<label class="form-check-label" for="keep_in">
{#LOGIN_SAVE_COOKIE#} <span title="{#LOGIN_SAVE_INFO#}"><i class="fa fa-question"></i></span>
</label>
</div>
<button type="submit" class="btn btn-primary btn-block mb-3">{#LOGIN_BUTTON_LOGIN#}</button>
<a title="{#LOGIN_PASSWORD_REMIND#}" href="{$ABS_PATH}index.php?module=login&action=reminder">{#LOGIN_PASSWORD_REMIND#}</a>&nbsp;
{if $active == 1}<a title="{#LOGIN_NEW_REGISTER#}" href="{$ABS_PATH}index.php?module=login&action=register">{#LOGIN_NEW_REGISTER#}</a>{/if}
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-6 col-lg-4">
<form method="post" action="{$ABS_PATH}index.php?module=login&action=authorize">
<div class="card shadow">
<div class="card-body p-4">
<h3 class="card-title text-center mb-4">{#LOGIN_AUTORIZATION#}</h3>
{if $login == false && isset($smarty.request.user_login)}
<div class="alert alert-danger alert-dismissible fade show animate__animated animate__shakeX" role="alert">
<i class="bi bi-exclamation-triangle me-2"></i> {#LOGIN_TEXT_FALSE_INFO#}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{/if}
{if $login == false}
<div class="alert alert-danger alert-dismissible fade show mt-3" role="alert">
{#LOGIN_TEXT_FALSE_INFO#}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{/if}
</div>
</div>
</form>
<div class="mb-3">
<label class="form-label small fw-bold text-muted">{#LOGIN_YOUR_LOGIN#}</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-person text-muted"></i></span>
{* Фикс Warning: используем default:'' *}
<input type="text" name="user_login" class="form-control"
value="{$smarty.request.user_login|default:''|escape|stripslashes}" required>
</div>
</div>
<div class="mb-3">
<label class="form-label small fw-bold text-muted">{#LOGIN_PASSWORD#}</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-lock text-muted"></i></span>
<input type="password" name="user_pass" id="p_pass" class="form-control" required>
<button class="btn btn-outline-secondary toggle-password" type="button"><i class="bi bi-eye"></i></button>
</div>
</div>
<div class="form-check mb-4">
<input class="form-check-input" type="checkbox" name="keep_in" id="keep_in_main" value="1">
<label class="form-check-label small" for="keep_in_main">{#LOGIN_SAVE_COOKIE#}</label>
</div>
<button type="submit" class="btn btn-primary w-100 py-2 mb-3 fw-bold">{#LOGIN_BUTTON_LOGIN#}</button>
<div class="text-center small border-top pt-3">
<a href="{$ABS_PATH}index.php?module=login&action=reminder" class="text-decoration-none me-3">{#LOGIN_PASSWORD_REMIND#}</a>
{if $active == 1}
<a href="{$ABS_PATH}index.php?module=login&action=register" class="text-decoration-none fw-bold">{#LOGIN_NEW_REGISTER#}</a>
{/if}
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<script type="text/javascript">
document.querySelectorAll('.toggle-password').forEach(btn => {ldelim}
btn.addEventListener('click', function() {ldelim}
const input = document.getElementById('p_pass');
const icon = this.querySelector('i');
if (input.type === 'password') {ldelim}
input.type = 'text';
icon.classList.replace('bi-eye', 'bi-eye-slash');
{rdelim} else {ldelim}
input.type = 'password';
icon.classList.replace('bi-eye-slash', 'bi-eye');
{rdelim}
{rdelim});
{rdelim});
</script>

View File

@@ -1,87 +1,207 @@
<h2>{#LOGIN_CHANGE_DETAILS#}</h2>
<p class="text-muted">{#LOGIN_DETAILS_INFO#}</p>
<div class="container py-4">
<div class="row justify-content-center">
<div class="col-lg-9">
<div class="card shadow-sm border-0">
<div class="card-header bg-primary text-white py-3">
<h2 class="h5 mb-0"><i class="bi bi-pencil-square me-2"></i> {#LOGIN_CHANGE_DETAILS#}</h2>
</div>
<div class="card-body p-4">
<p class="text-muted small mb-4">{#LOGIN_DETAILS_INFO#}</p>
{if $errors}
<div class="row" id="user-info">
<div class="col-12">
<p>{#LOGIN_ERRORS#}</p>
{if $errors}
<div class="alert alert-danger shadow-sm mb-4">
<p class="fw-bold mb-2 small text-uppercase"><i class="bi bi-exclamation-triangle me-2"></i> {#LOGIN_ERRORS#}</p>
<ul class="mb-0 small">
{foreach from=$errors item=error}
<li>{$error}</li>
{/foreach}
</ul>
</div>
{/if}
{foreach from=$errors item=error}
<div class="alert alert-danger alert-dismissible fade show" role="alert">
{$error}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{/foreach}
<form method="post" action="{$ABS_PATH}index.php?module=login&action=profile" enctype="multipart/form-data">
<input type="hidden" name="sub" value="update" />
{* Группа: Аватар пользователя *}
<div class="row mb-4 align-items-center bg-light p-3 rounded-3 border">
<div class="col-auto">
<div class="position-relative" id="avatar-container">
<img src="{$user_avatar}" id="avatar-preview" alt="Avatar" class="rounded-circle img-thumbnail shadow-sm" style="width: 100px; height: 100px; object-fit: cover;">
<button type="button" id="btn-remove-avatar" class="btn btn-danger btn-sm position-absolute top-0 start-100 translate-middle rounded-circle d-none" title="Удалить фото">
<i class="bi bi-x"></i>
</button>
<input type="checkbox" name="delete_avatar" id="delete_avatar_check" class="d-none" value="1">
</div>
</div>
<div class="col">
<h5 class="text-primary small fw-bold text-uppercase mb-2">Ваше фото (Avatar)</h5>
<div class="input-group">
<label class="input-group-text bg-white shadow-sm" for="avatar-upload">
<i class="bi bi-cloud-arrow-up text-primary"></i>
</label>
<input type="file" name="avatar" class="form-control shadow-sm" id="avatar-upload" accept="image/jpeg,image/png,image/gif,image/webp">
</div>
<div class="form-text small mt-1">Поддерживаются JPG, PNG, GIF и WebP.</div>
</div>
</div>
</div>
</div>
{/if}
{* Группа: Личные данные *}
<div class="row g-3 mb-4">
<h5 class="text-primary border-bottom pb-2 mb-3 small fw-bold text-uppercase">{#LOGIN_YOUR_PRIVAT_DATA#}</h5>
<div class="col-md-6">
<label for="firstname" class="form-label fw-bold small">
<i class="bi bi-person text-muted me-1"></i> {#LOGIN_YOUR_FIRSTNAME#}
</label>
<input name="firstname" type="text" class="form-control shadow-sm" id="firstname" value="{$smarty.request.firstname|default:$row.firstname|escape|stripslashes}">
</div>
<div class="col-md-6">
<label for="lastname" class="form-label fw-bold small">
<i class="bi bi-person-vcard text-muted me-1"></i> {#LOGIN_YOUR_LASTNAME#}
</label>
<input name="lastname" type="text" class="form-control shadow-sm" id="lastname" value="{$smarty.request.lastname|default:$row.lastname|escape|stripslashes}">
</div>
<form method="post" action="{$ABS_PATH}index.php?module=login&action=profile">
<input type="hidden" name="sub" value="update" />
<div class="row" id="user-info">
<div class="col-12">
<div class="form-row">
<div class="form-group col-md-6">
<label for="firstname">{#LOGIN_YOUR_FIRSTNAME#}</label>
<input name="firstname" type="text" class="form-control" id="firstname" placeholder="" value="{$smarty.request.firstname|default:$row.firstname|escape|stripslashes}">
</div>
<div class="form-group col-md-6">
<label for="lastname">{#LOGIN_YOUR_LASTNAME#}</label>
<input name="lastname" type="text" class="form-control" id="lastname" placeholder="" value="{$smarty.request.lastname|default:$row.lastname|escape|stripslashes}">
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="email">{#LOGIN_YOUR_MAIL#}</label>
<input name="email" type="email" class="form-control" id="email" placeholder="" value="{$smarty.request.email|default:$row.email|escape|stripslashes}">
</div>
<div class="form-group col-md-6">
<label for="birthday">{#LOGIN_YOUR_BIRTHDAY#} {#LOGIN_DATE_FORMAT#}</label>
<input name="birthday" type="text" class="form-control" id="birthday" placeholder="" value="{$smarty.request.birthday|default:$row.birthday|escape|stripslashes}">
</div>
</div>
<div class="form-group">
<label for="street">{#LOGIN_YOUR_STREET#}</label>
<input name="street" type="text" class="form-control" id="street" placeholder="" value="{$smarty.request.street|default:$row.street|escape|stripslashes}">
</div>
<div class="form-group">
<label for="street_nr">{#LOGIN_YOUR_HOUSE#}</label>
<input name="street_nr" type="text" class="form-control" id="street_nr" placeholder="" value="{$smarty.request.street_nr|default:$row.street_nr|escape|stripslashes}">
</div>
<div class="form-row">
<div class="form-group col-md-5">
<label for="city">{#LOGIN_YOUR_TOWN#}</label>
<input name="city" type="text" class="form-control" id="city" value="{$smarty.request.city|default:$row.city|escape|stripslashes}">
</div>
<div class="form-group col-md-4">
<label for="country">{#LOGIN_YOUR_COUNTRY#}</label>
<select id="country" class="form-control" name="country">
{assign var=uc value=$row->country|default:$smarty.session.user_language|lower}
{foreach from=$available_countries item=land}
<option value="{$land->country_code}"{if $land->country_code == $smarty.request.country|default:$row.country|default:$smarty.session.user_language} selected="selected" {/if}>{$land->country_name}</option>
{/foreach}
</select>
</div>
<div class="form-group col-md-3">
<label for="zipcode">{#LOGIN_YOUR_ZIP#}</label>
<input name="zipcode" type="text" class="form-control" id="zipcode" value="{$smarty.request.zipcode|default:$row.zipcode|escape|stripslashes}">
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="phone">{#LOGIN_YOUR_PHONE#}</label>
<input name="phone" type="text" class="form-control" id="phone" placeholder="" value="{$smarty.request.phone|default:$row.phone|escape|stripslashes}">
</div>
<div class="form-group col-md-6">
<label for="company">{#LOGIN_YOUR_COMPANY#}</label>
<input name="company" type="text" class="form-control" id="company" placeholder="" value="{$smarty.request.company|default:$row.company|escape|stripslashes}">
</div>
</div>
<div class="col-md-6">
<label for="email" class="form-label fw-bold small">
<i class="bi bi-envelope text-muted me-1"></i> {#LOGIN_YOUR_MAIL#}
</label>
<input name="email" type="email" class="form-control shadow-sm" id="email" value="{$smarty.request.email|default:$row.email|escape|stripslashes}">
</div>
<button type="submit" class="btn btn-primary">{#LOGIN_BUTTON_CHANGE#}</button>
</div>
</div>
</form>
<div class="col-md-6">
<label for="birthday-picker" class="form-label fw-bold small">
<i class="bi bi-calendar3 text-muted me-1"></i> {#LOGIN_YOUR_BIRTHDAY#}
</label>
<div class="input-group shadow-sm">
<input name="birthday" type="text" class="form-control" id="birthday-picker" placeholder="Выберите дату" value="{$smarty.request.birthday|default:$row.birthday|escape|stripslashes}">
<span class="input-group-text bg-light text-primary border-start-0"><i class="bi bi-calendar-check"></i></span>
</div>
</div>
</div>
{* Группа: Адрес проживания *}
<div class="row g-3 mb-4">
<h5 class="text-primary border-bottom pb-2 mb-3 small fw-bold text-uppercase">{#LOGIN_YOUR_PRIVAT_ADR#}</h5>
<div class="col-md-8">
<label for="street" class="form-label fw-bold small">
<i class="bi bi-geo-alt text-muted me-1"></i> {#LOGIN_YOUR_STREET#}
</label>
<input name="street" type="text" class="form-control shadow-sm" id="street" value="{$smarty.request.street|default:$row.street|escape|stripslashes}">
</div>
<div class="col-md-4">
<label for="street_nr" class="form-label fw-bold small">
<i class="bi bi-house text-muted me-1"></i> {#LOGIN_YOUR_HOUSE#}
</label>
<input name="street_nr" type="text" class="form-control shadow-sm" id="street_nr" value="{$smarty.request.street_nr|default:$row.street_nr|escape|stripslashes}">
</div>
<div class="col-md-5">
<label for="city" class="form-label fw-bold small">
<i class="bi bi-building text-muted me-1"></i> {#LOGIN_YOUR_TOWN#}
</label>
<input name="city" type="text" class="form-control shadow-sm" id="city" value="{$smarty.request.city|default:$row.city|escape|stripslashes}">
</div>
<div class="col-md-4">
<label for="country" class="form-label fw-bold small">
<i class="bi bi-globe text-muted me-1"></i> {#LOGIN_YOUR_COUNTRY#}
</label>
<select id="country" class="form-select shadow-sm" name="country">
{foreach from=$available_countries item=land}
<option value="{$land->country_code}"{if $land->country_code == $smarty.request.country|default:$row.country|default:$smarty.session.user_language} selected="selected"{/if}>{$land->country_name}</option>
{/foreach}
</select>
</div>
<div class="col-md-3">
<label for="zipcode" class="form-label fw-bold small">
<i class="bi bi-hash text-muted me-1"></i> {#LOGIN_YOUR_ZIP#}
</label>
<input name="zipcode" type="text" class="form-control shadow-sm" id="zipcode" value="{$smarty.request.zipcode|default:$row.zipcode|escape|stripslashes}">
</div>
</div>
{* Группа: Связь и работа *}
<div class="row g-3 mb-4">
<h5 class="text-primary border-bottom pb-2 mb-3 small fw-bold text-uppercase">{#LOGIN_YOUR_PRIVAT_JOB#}</h5>
<div class="col-md-6">
<label for="phone" class="form-label fw-bold small">
<i class="bi bi-telephone text-muted me-1"></i> {#LOGIN_YOUR_PHONE#}
</label>
<input name="phone" type="text" class="form-control shadow-sm" id="phone" value="{$smarty.request.phone|default:$row.phone|escape|stripslashes}">
</div>
<div class="col-md-6">
<label for="company" class="form-label fw-bold small">
<i class="bi bi-briefcase text-muted me-1"></i> {#LOGIN_YOUR_COMPANY#}
</label>
<input name="company" type="text" class="form-control shadow-sm" id="company" value="{$smarty.request.company|default:$row.company|escape|stripslashes}">
</div>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-start pt-3 border-top">
<button type="submit" class="btn btn-primary btn-lg px-5 fw-bold shadow">
<i class="bi bi-save me-2"></i> {#LOGIN_BUTTON_CHANGE#}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
{assign var="current_lang" value=$smarty.session.user_language|default:'ru'|lower}
{if $current_lang == 'ua'}{assign var="current_lang" value="uk"}{/if}
<script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/l10n/{$current_lang}.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
flatpickr("#birthday-picker", {
locale: "{$current_lang}",
dateFormat: "d.m.Y",
allowInput: true,
maxDate: "today"
});
const uploadInput = document.getElementById('avatar-upload');
const previewImg = document.getElementById('avatar-preview');
const removeBtn = document.getElementById('btn-remove-avatar');
const deleteCheck = document.getElementById('delete_avatar_check');
// Логика инициализации: показываем крестик только если аватар НЕ дефолтный
if (previewImg && previewImg.src.indexOf('default.png') === -1 && previewImg.src !== '' && !previewImg.src.startsWith('data:')) {
removeBtn.classList.remove('d-none');
}
uploadInput.addEventListener('change', function() {
if (this.files && this.files[0]) {
const reader = new FileReader();
reader.onload = function(e) {
previewImg.src = e.target.result;
removeBtn.classList.remove('d-none');
deleteCheck.checked = false;
}
reader.readAsDataURL(this.files[0]);
}
});
removeBtn.addEventListener('click', function() {
// Устанавливаем дефолтное изображение с timestamp для сброса кеша
previewImg.src = '{$ABS_PATH}uploads/avatars/default.png?t=' + new Date().getTime();
uploadInput.value = '';
deleteCheck.checked = true;
this.classList.add('d-none'); // Скрываем крестик, так как теперь там дефолт
});
});
</script>

View File

@@ -1,86 +1,138 @@
<div class="container py-4">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="card shadow-sm border-0">
<div class="card-header bg-primary text-white py-3">
<h2 class="h5 mb-0"><i class="bi bi-person-plus me-2"></i> {#LOGIN_TEXT_REGISTER#}</h2>
</div>
<div class="card-body p-4">
{if $errors}
<div class="alert alert-danger shadow-sm">
<ul class="mb-0">
{foreach from=$errors item=error}
<li class="regerror">{$error}</li>
{/foreach}
</ul>
</div>
{/if}
<h2 id="page-heading">{#LOGIN_TEXT_REGISTER#}</h2>
<div id="checkResultUsername"></div>
<div id="checkResultEmail"></div>
<div class="block" id="forms">
{if $errors}
<ul>
{foreach from=$errors item=error}
<li class="regerror">{$error}</li>
{/foreach}
</ul>
{/if}
<span id="checkResultUsername"></span>
<span id="checkResultEmail"></span>
<form method="post" action="{$ABS_PATH}index.php?module=login&action=register">
<input type="hidden" name="sub" value="register" />
<form method="post" action="{$ABS_PATH}index.php?module=login&action=register">
<input type="hidden" name="sub" value="register" />
<fieldset class="login">
<legend>{#LOGIN_TEXT_AUTHORIZATION#}</legend>
{if $smarty.session.loginza_auth==1}
<input name="user_name" id="username" value="{$smarty.post.user_name|escape|stripslashes}" type="hidden">
{/if}
{if $smarty.session.loginza_auth!=1}
<p>
<label><span id="checkUsername" style="display:none"><img src="{$ABS_PATH}modules/login/img/ajax-loader.gif" border="0" /></span>{#LOGIN_YOUR_LOGIN#}</label>
<input name="user_name" id="username" value="{$smarty.post.user_name|escape|stripslashes}" type="text">
</p>
<p>
<label>{#LOGIN_PASSWORD#}</label>
<input name="reg_pass" type="password" value="{$smarty.post.reg_pass|escape|stripslashes}">
</p>
{/if}
<p>
<label><span id="checkEmail" style="display:none"><img src="{$ABS_PATH}modules/login/img/ajax-loader.gif" border="0" /></span>{#LOGIN_YOUR_MAIL#}</label>
<input name="reg_email" id="email" value="{$smarty.post.reg_email|escape|stripslashes}" type="text">
</p>
</fieldset>
<div class="mb-4">
<h5 class="text-primary border-bottom pb-2 mb-3 small fw-bold text-uppercase">{#LOGIN_TEXT_AUTHORIZATION#}</h5>
<div class="mb-3">
<label class="form-label fw-bold small">
<span id="checkUsername" style="display:none" class="me-1">
<img src="{$ABS_PATH}modules/login/img/ajax-loader.gif" alt="loading" />
</span>
{#LOGIN_YOUR_LOGIN#} <span class="text-danger">*</span>
</label>
<input name="user_name" id="username" value="{$smarty.post.user_name|default:''|escape|stripslashes}" type="text" class="form-control shadow-sm" placeholder="Придумайте логин">
<div class="form-text mt-1 text-muted" style="font-size: 0.75rem;">
<i class="bi bi-info-circle me-1"></i> {#LOGIN_WRONG_FIELD_LOGIN#}
</div>
</div>
<fieldset class="login">
<legend>{#LOGIN_TEXT_USER_INFO#}</legend>
{if $firstname==1}
<p>
<label>{#LOGIN_YOUR_FIRSTNAME#}</label>
<input name="reg_firstname" value="{$smarty.post.reg_firstname|escape|stripslashes}" type="text">
</p>
{/if}
{if $lastname==1}
<p>
<label>{#LOGIN_YOUR_LASTNAME#}</label>
<input name="reg_lastname" value="{$smarty.post.reg_lastname|escape|stripslashes}" type="text">
</p>
{/if}
{if $company==1}
<p>
<label>{#LOGIN_YOUR_COMPANY#}</label>
<input name="company" value="{$smarty.post.company|escape|stripslashes}" type="text">
</p>
{/if}
<p>
<label>{#LOGIN_YOUR_COUNTRY#}</label>
<select name="country">
{if $smarty.request.action=='register' && $smarty.request.sub == 'register'}
{assign var=sL value=$smarty.request.country|lower}
{else}
{assign var=sL value=$row->country|default:$smarty.session.user_language|lower}
{/if}
{foreach from=$available_countries item=land}
<option value="{$land->country_code}"{if $sL==$land->country_code} selected{/if}>{$land->country_name}</option>
{/foreach}
</select>
</p>
{if $im}
<p>
<label>{#LOGIN_SECURITY_CODE#}</label>
<div style="margin-bottom:1em" id="captcha">
<img src="{$ABS_PATH}inc/captcha.php" alt="" width="120" height="60" border="0" />
</div>
</p>
<p>
<label>{#LOGIN_SECURITY_CODER#}</label>
<input style="width:114px" name="reg_secure" type="text" value="" />
</p>
{/if}
<input class="confirm button" value="{#LOGIN_BUTTON_SUBMIT#}" type="submit">
</fieldset>
</form>
</div>
<div class="mb-3">
<label class="form-label fw-bold small">
<span id="checkEmail" style="display:none" class="me-1">
<img src="{$ABS_PATH}modules/login/img/ajax-loader.gif" alt="loading" />
</span>
{#LOGIN_YOUR_MAIL#} <span class="text-danger">*</span>
</label>
<input name="reg_email" id="email" value="{$smarty.post.reg_email|default:''|escape|stripslashes}" type="email" class="form-control shadow-sm" placeholder="email@example.com">
</div>
<div class="mb-3">
<label class="form-label fw-bold small">{#LOGIN_PASSWORD#} <span class="text-danger">*</span></label>
<input name="reg_pass" type="password" class="form-control shadow-sm" placeholder="минимум 6 символов">
</div>
</div>
<div class="mb-4">
{if ($firstname|default:0 == 1) || ($lastname|default:0 == 1) || ($company|default:0 == 1) || ($country|default:0 == 1)}
<h5 class="text-primary border-bottom pb-2 mb-3 small fw-bold text-uppercase">{#LOGIN_TEXT_USER_INFO#}</h5>
{/if}
<div class="row">
{if $firstname|default:0 == 1}
<div class="col-md-6 mb-3">
<label class="form-label fw-bold small">{#LOGIN_YOUR_FIRSTNAME#}</label>
<input name="reg_firstname" value="{$smarty.post.reg_firstname|default:''|escape|stripslashes}" type="text" class="form-control">
</div>
{/if}
{if $lastname|default:0 == 1}
<div class="col-md-6 mb-3">
<label class="form-label fw-bold small">{#LOGIN_YOUR_LASTNAME#}</label>
<input name="reg_lastname" value="{$smarty.post.reg_lastname|default:''|escape|stripslashes}" type="text" class="form-control">
</div>
{/if}
</div>
{if $company|default:0 == 1}
<div class="mb-3">
<label class="form-label fw-bold small">{#LOGIN_YOUR_COMPANY#}</label>
<input name="company" value="{$smarty.post.company|default:''|escape|stripslashes}" type="text" class="form-control">
</div>
{/if}
{if $country|default:0 == 1}
<div class="mb-3">
<label class="form-label fw-bold small">{#LOGIN_YOUR_COUNTRY#}</label>
<select name="country" class="form-select shadow-sm">
{if $smarty.request.action|default:'' == 'register' && $smarty.request.sub|default:'' == 'register'}
{assign var=sL value=$smarty.request.country|default:''|lower}
{else}
{assign var=sL value=$row->country|default:($smarty.session.user_language|default:'ru')|lower}
{/if}
{foreach from=$available_countries item=land}
<option value="{$land->country_code}" {if $sL == $land->country_code|lower}selected{/if}>{$land->country_name}</option>
{/foreach}
</select>
</div>
{/if}
</div>
{if $im|default:0}
<div class="bg-light p-3 border rounded mb-4 shadow-sm">
<label class="form-label fw-bold text-dark small mb-2"><i class="bi bi-shield-check me-1"></i> {#LOGIN_SECURITY_CODE#}</label>
<div class="d-flex align-items-center mb-3" id="captcha">
<img src="{$ABS_PATH}inc/captcha.php"
id="captcha-img"
alt="captcha"
width="120" height="60"
class="rounded border shadow-sm me-3"
style="cursor: pointer;"
title="Нажмите, чтобы обновить"
onclick="this.src='{$ABS_PATH}inc/captcha.php?r=' + Math.random();" />
<div class="flex-grow-1">
<label class="form-label small mb-1">{#LOGIN_SECURITY_CODER#}</label>
<input name="reg_secure" type="text" value="" class="form-control form-control-lg fw-bold text-center" style="letter-spacing: 3px;" maxlength="6">
</div>
</div>
<div class="form-text small text-muted">
<i class="bi bi-arrow-clockwise me-1"></i> {#LOGIN_CAPTCHA_UPD#}
</div>
</div>
{/if}
<div class="d-grid pt-2">
<button class="btn btn-primary btn-lg fw-bold shadow-sm" type="submit">
{#LOGIN_BUTTON_SUBMIT#}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,22 +1,68 @@
<h2 id="page-heading">{#LOGIN_TEXT_REGISTER#}</h2>
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="card shadow border-0">
<div class="card-header bg-primary text-white py-3 text-center">
<h2 class="h5 mb-0"><i class="bi bi-shield-lock me-2"></i> {#LOGIN_TEXT_REGISTER#}</h2>
</div>
<div class="card-body p-4 p-md-5">
{if $final == "ok"}
<div class="text-center">
<div class="mb-4">
<i class="bi bi-check-circle-fill text-success" style="font-size: 4rem;"></i>
</div>
<h3 class="h4 fw-bold mb-3">{#LOGIN_MESSAGE_OK#}</h3>
<p class="text-muted">{#LOGIN_REGISTER_OK_SP_L#}</p>
{if $smarty.session.referer != ''}
<meta http-equiv="refresh" content="5;URL={$smarty.session.referer}" />
<div class="mt-4">
<div class="spinner-border text-primary spinner-border-sm" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
{/if}
</div>
{else}
<div class="mb-4 text-center">
<i class="bi bi-key text-primary" style="font-size: 3rem;"></i>
</div>
<p class="text-center text-muted mb-4">
{#LOGIN_MESSAGE_TEXT#}
</p>
<div class="block" id="forms">
<fieldset class="login">
{if $final == "ok"}
<p>{#LOGIN_MESSAGE_OK#}</p>
{if $smarty.session.referer != ''}
<meta http-equiv="refresh" content="5;URL={$smarty.session.referer}" />
{/if}
{else}
<p>{#LOGIN_MESSAGE_TEXT#}</p>
<form method="post" action="{$ABS_PATH}index.php?module=login&action=register">
<input type="hidden" name="sub" value="final" />
<p>
<label>{#LOGIN_CODE_FROM_MAIL#}</label>
<input type="text" name="emc" />
</p>
<input class="confirm button" value="{#LOGIN_BUTTON_FINAL#}" type="submit">
</form>
{/if}
</fieldset>
<form method="post" action="{$ABS_PATH}index.php?module=login&action=register">
<input type="hidden" name="sub" value="final" />
<div class="mb-4">
<label class="form-label fw-bold small text-uppercase text-secondary">{#LOGIN_CODE_FROM_MAIL#}</label>
<div class="input-group">
<span class="input-group-text bg-light"><i class="bi bi-hash"></i></span>
<input type="text" name="emc" class="form-control form-control-lg text-center fw-bold"
autocomplete="off" required>
</div>
</div>
<div class="d-grid">
<button class="btn btn-primary btn-lg fw-bold shadow-sm" type="submit">
<i class="bi bi-check2-square me-2"></i> {#LOGIN_BUTTON_FINAL#}
</button>
</div>
</form>
{/if}
</div>
</div>
{if $final != "ok"}
<div class="text-center mt-4">
<p class="small text-muted">
{#LOGIN_REGISTER_OK_SP_N#} <a href="#" class="text-decoration-none" onclick="window.location.reload();">{#LOGIN_REGISTER_OK_SP_O#}</a>.
</p>
</div>
{/if}
</div>
</div>
</div>

View File

@@ -1,8 +1,34 @@
<h2 id="page-heading">{#LOGIN_TEXT_REGISTER#}</h2>
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-7">
<div class="card shadow border-0 text-center">
<div class="card-body p-5">
<div class="mb-4">
<i class="bi bi-envelope-check text-success" style="font-size: 4rem;"></i>
</div>
<h2 class="h4 fw-bold text-dark mb-3">
{#LOGIN_REGISTER_OK#}
</h2>
<p class="text-muted fs-5 mb-4">
{#LOGIN_THANKYOU_TEXT#}
</p>
<div class="block" id="forms">
<fieldset class="login">
<legend>{#LOGIN_REGISTER_OK#}</legend>
<p>{#LOGIN_THANKYOU_TEXT#}</p>
</fieldset>
<hr class="my-4 opacity-25">
<div class="d-grid gap-2 d-sm-flex justify-content-sm-center">
<a href="{$ABS_PATH}index.php?id=1" class="btn btn-primary btn-lg px-4 gap-3 shadow-sm">
<i class="bi bi-house-door me-2"></i> {#LOGIN_REGISTER_OK_SP_M#}
</a>
</div>
</div>
</div>
<div class="text-center mt-4 text-muted small">
<i class="bi bi-info-circle me-1"></i>
{#LOGIN_REGISTER_OK_SP#}
</div>
</div>
</div>
</div>

View File

@@ -1,34 +1,97 @@
<script type="text/javascript">
function check_email() {ldelim}
if (document.getElementById('l_mailreminder').value == '') {ldelim}
alert("{#LOGIN_ENTER_EMAIL#}");
document.getElementById('l_mailreminder').focus();
return false;
{rdelim}
return true;
const errorBlock = document.getElementById('js-error-block');
const errorText = document.getElementById('js-error-text');
// Сбрасываем состояние
errorBlock.classList.add('d-none');
if (document.getElementById('l_mailreminder').value == '') {ldelim}
errorText.innerText = "{#LOGIN_ENTER_EMAIL#}";
errorBlock.classList.remove('d-none');
// Эффект тряски
errorBlock.classList.add('animate__shakeX');
setTimeout(() => errorBlock.classList.remove('animate__shakeX'), 500);
document.getElementById('l_mailreminder').focus();
return false;
{rdelim}
return true;
{rdelim}
</script>
<h2 id="page-heading">{#LOGIN_REMIND#}</h2>
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-5">
{* Блок для JS-ошибок *}
<div id="js-error-block" class="alert alert-danger shadow-sm border-0 mb-4 d-none animate__animated">
<div class="d-flex align-items-center">
<i class="bi bi-exclamation-circle fs-5 me-3"></i>
<div id="js-error-text"></div>
</div>
</div>
<div class="block" id="forms">
{if $smarty.request.sub=='send'}
<fieldset>
<p>{#LOGIN_REMINDER_INFO3#}</p>
</fieldset>
{else}
<form method="post" action="{$ABS_PATH}index.php?module=login&action=reminder" onsubmit="return check_email();">
<input type="hidden" name="sub" value="send" />
<fieldset class="login">
<legend>{#LOGIN_REMINDER_INFO4#}</legend>
<p>{#LOGIN_REMINDER_INFO2#}</p>
<p>
<label>{#LOGIN_YOUR_MAIL#}</label>
<input name="f_mailreminder" id="l_mailreminder" value="" type="text">
</p>
<input class="confirm button" value="{#LOGIN_BUTTON_NEWPASS#}" type="submit">
</fieldset>
</form>
{/if}
</div>
{* Сообщение после отправки письма *}
{if $smarty.request.sub|default:'' == 'send'}
<div class="card shadow-lg border-0 animate__animated animate__fadeIn">
<div class="card-body p-5 text-center">
<div class="mb-4">
<i class="bi bi-send-check fa-4x text-success opacity-25" style="font-size: 4rem;"></i>
</div>
<h2 class="h4 fw-bold mb-3">Письмо отправлено!</h2>
<p class="text-muted mb-4">{#LOGIN_REMINDER_INFO3#}</p>
<a href="index.php?module=login&action=authorize" class="btn btn-primary shadow-sm px-4">
<i class="bi bi-arrow-left me-2"></i> Вернуться к входу
</a>
</div>
</div>
{else}
<div class="card shadow-sm border-0">
<div class="card-header bg-primary text-white py-3">
<h2 class="h5 mb-0 text-center text-uppercase fw-bold" style="letter-spacing: 1px;">
<i class="bi bi-life-preserver me-2"></i> {#LOGIN_REMIND#}
</h2>
</div>
<div class="card-body p-4">
<div class="text-center mb-4">
<p class="text-muted small px-3">{#LOGIN_REMINDER_INFO2#}</p>
</div>
<form method="post" action="{$ABS_PATH}index.php?module=login&action=reminder" onsubmit="return check_email();">
<input type="hidden" name="sub" value="send" />
<div class="mb-4">
<label class="form-label small fw-bold text-muted text-uppercase">{#LOGIN_YOUR_MAIL#}</label>
<div class="input-group">
<span class="input-group-text bg-light border-end-0">
<i class="bi bi-envelope text-muted"></i>
</span>
<input name="f_mailreminder" id="l_mailreminder"
class="form-control border-start-0 ps-0"
placeholder="example@mail.com"
type="email">
</div>
</div>
<div class="d-grid gap-2">
<button class="btn btn-primary btn-lg shadow-sm fw-bold" type="submit">
{#LOGIN_BUTTON_NEWPASS#}
</button>
<a href="index.php?module=login&action=authorize" class="btn btn-link btn-sm text-decoration-none text-muted">
Я вспомнил пароль
</a>
</div>
</form>
</div>
<div class="card-footer bg-light border-0 py-3 text-center">
<span class="small text-muted">{#LOGIN_REMINDER_INFO4#}</span>
</div>
</div>
{/if}
</div>
</div>
</div>

View File

@@ -1,8 +1,34 @@
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="card shadow border-0 text-center">
<div class="card-body p-5">
<div class="mb-4">
<i class="bi bi-shield-check text-success" style="font-size: 4rem;"></i>
</div>
<h2 class="h4 fw-bold text-dark mb-3" id="page-heading">
{#LOGIN_REMIND#}
</h2>
<p class="text-muted fs-5 mb-4">
{#LOGIN_PASSWORD_RESTOR#}
</p>
<h2 id="page-heading">{#LOGIN_REMIND#}</h2>
<hr class="my-4 opacity-25">
<div class="block" id="forms">
<fieldset class="login">
<p>{#LOGIN_PASSWORD_RESTOR#}</p>
</fieldset>
<div class="d-grid">
<a href="{$ABS_PATH}index.php?module=login&action=authorize" class="btn btn-primary btn-lg shadow-sm">
<i class="bi bi-box-arrow-in-right me-2"></i> {#LOGIN_SUBJECT_REMIND_AK#}
</a>
</div>
</div>
</div>
<div class="text-center mt-4 text-muted small">
<i class="bi bi-info-circle me-1"></i>
{#LOGIN_SUBJECT_REMIND_OK#}
</div>
</div>
</div>
</div>

View File

@@ -9,7 +9,7 @@
$module_sql_deinstall[] = "DROP TABLE IF EXISTS `%%PRFX%%_module_login`;";
//Установка модуля
$module_sql_install[] = "CREATE TABLE `%%PRFX%%_module_login` (
$module_sql_install[] = "CREATE TABLE `%%PRFX%%_module_login` (
`Id` tinyint(1) unsigned NOT NULL auto_increment,
`login_reg_type` enum('now','email','byadmin') NOT NULL default 'now',
`login_antispam` enum('0','1') NOT NULL default '0',
@@ -19,10 +19,11 @@
`login_require_company` enum('0','1') NOT NULL default '0',
`login_require_firstname` enum('0','1') NOT NULL default '0',
`login_require_lastname` enum('0','1') NOT NULL default '0',
`login_require_country` enum('0','1') NOT NULL default '0',
PRIMARY KEY (Id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
$module_sql_install[] = "INSERT INTO `%%PRFX%%_module_login` VALUES (1, 'email', 1, 1, 'domain.ru', 'name@domain.ru',0,0,0);";
$module_sql_install[] = "INSERT INTO `%%PRFX%%_module_login` VALUES (1, 'email', 1, 1, 'domain.ru', 'name@domain.ru',0,0,0,0);";
// Обновление модуля
$module_sql_update[] = "