1307 lines
55 KiB
HTML
1307 lines
55 KiB
HTML
<!-- public/admin-doc.html -->
|
||
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Управление группами пользователей | CRM</title>
|
||
<link rel="stylesheet" href="/styles.css">
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||
<style>
|
||
:root {
|
||
--admin-color: #e74c3c;
|
||
--secretary-color: #3498db;
|
||
--help-color: #27ae60;
|
||
--doc-color: #9b59b6;
|
||
--ahch-color: #e67e22;
|
||
}
|
||
|
||
.container {
|
||
max-width: 1400px;
|
||
margin: 0 auto;
|
||
padding: 20px;
|
||
}
|
||
|
||
.header {
|
||
background: white;
|
||
padding: 20px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.header h1 {
|
||
margin: 0;
|
||
color: #333;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
}
|
||
|
||
.header-actions {
|
||
display: flex;
|
||
gap: 10px;
|
||
margin-top: 15px;
|
||
}
|
||
|
||
.tabs {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 5px;
|
||
margin-bottom: 20px;
|
||
background: white;
|
||
padding: 5px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.tab {
|
||
padding: 12px 20px;
|
||
border: none;
|
||
background: none;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
border-radius: 6px;
|
||
transition: all 0.3s;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.tab:hover {
|
||
background: #f5f5f5;
|
||
}
|
||
|
||
.tab.active {
|
||
color: white;
|
||
}
|
||
|
||
.tab.secretary.active { background: var(--secretary-color); }
|
||
.tab.administration.active { background: var(--admin-color); }
|
||
.tab.help.active { background: var(--help-color); }
|
||
.tab.doc.active { background: var(--doc-color); }
|
||
.tab.ahch.active { background: var(--ahch-color); }
|
||
.tab.all-users.active { background: #2c3e50; }
|
||
|
||
.content-section {
|
||
display: none;
|
||
background: white;
|
||
padding: 20px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.content-section.active {
|
||
display: block;
|
||
}
|
||
|
||
.group-info {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
margin-bottom: 20px;
|
||
padding: 15px;
|
||
background: #f9f9f9;
|
||
border-radius: 6px;
|
||
}
|
||
|
||
.group-color {
|
||
width: 20px;
|
||
height: 20px;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.group-color.admin { background: var(--admin-color); }
|
||
.group-color.secretary { background: var(--secretary-color); }
|
||
.group-color.help { background: var(--help-color); }
|
||
.group-color.doc { background: var(--doc-color); }
|
||
.group-color.ahch { background: var(--ahch-color); }
|
||
|
||
.users-container {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||
gap: 15px;
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.user-card {
|
||
background: white;
|
||
border: 1px solid #e0e0e0;
|
||
border-radius: 8px;
|
||
padding: 15px;
|
||
transition: all 0.3s;
|
||
position: relative;
|
||
}
|
||
|
||
.user-card:hover {
|
||
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
.user-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.user-avatar {
|
||
width: 40px;
|
||
height: 40px;
|
||
background: #3498db;
|
||
color: white;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.user-name {
|
||
font-weight: bold;
|
||
color: #333;
|
||
}
|
||
|
||
.user-role {
|
||
font-size: 12px;
|
||
color: #666;
|
||
margin-top: 2px;
|
||
}
|
||
|
||
.user-details {
|
||
font-size: 14px;
|
||
color: #666;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.group-badges {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 5px;
|
||
margin: 10px 0;
|
||
}
|
||
|
||
.group-badge {
|
||
padding: 4px 8px;
|
||
border-radius: 4px;
|
||
font-size: 11px;
|
||
color: white;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
}
|
||
|
||
.group-badge.admin { background: var(--admin-color); }
|
||
.group-badge.secretary { background: var(--secretary-color); }
|
||
.group-badge.help { background: var(--help-color); }
|
||
.group-badge.doc { background: var(--doc-color); }
|
||
.group-badge.ahch { background: var(--ahch-color); }
|
||
|
||
.user-actions {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
margin-top: 10px;
|
||
}
|
||
|
||
.btn {
|
||
padding: 6px 12px;
|
||
border: none;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
font-size: 12px;
|
||
transition: all 0.3s;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
}
|
||
|
||
.btn-primary {
|
||
background: #3498db;
|
||
color: white;
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
background: #2980b9;
|
||
}
|
||
|
||
.btn-danger {
|
||
background: #e74c3c;
|
||
color: white;
|
||
}
|
||
|
||
.btn-danger:hover {
|
||
background: #c0392b;
|
||
}
|
||
|
||
.btn-success {
|
||
background: #27ae60;
|
||
color: white;
|
||
}
|
||
|
||
.btn-success:hover {
|
||
background: #229954;
|
||
}
|
||
|
||
.btn-help { background: var(--help-color); color: white; }
|
||
.btn-help:hover { background: #219653; }
|
||
|
||
.btn-doc { background: var(--doc-color); color: white; }
|
||
.btn-doc:hover { background: #8e44ad; }
|
||
|
||
.btn-ahch { background: var(--ahch-color); color: white; }
|
||
.btn-ahch:hover { background: #d35400; }
|
||
|
||
.loading {
|
||
text-align: center;
|
||
padding: 40px;
|
||
color: #666;
|
||
}
|
||
|
||
.loading i {
|
||
font-size: 24px;
|
||
margin-bottom: 10px;
|
||
color: #3498db;
|
||
}
|
||
|
||
.search-box {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.search-input {
|
||
width: 100%;
|
||
padding: 10px 15px;
|
||
border: 1px solid #ddd;
|
||
border-radius: 6px;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.stats {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
||
gap: 15px;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.stat-card {
|
||
background: white;
|
||
padding: 15px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||
text-align: center;
|
||
}
|
||
|
||
.stat-number {
|
||
font-size: 24px;
|
||
font-weight: bold;
|
||
margin: 10px 0;
|
||
}
|
||
|
||
.stat-label {
|
||
color: #666;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.no-users {
|
||
text-align: center;
|
||
padding: 40px;
|
||
color: #666;
|
||
}
|
||
|
||
.all-groups-badges {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 5px;
|
||
margin-top: 5px;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.users-container {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.user-actions {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.tab {
|
||
padding: 10px 15px;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.stats {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
.stats {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.tab {
|
||
padding: 8px 12px;
|
||
font-size: 12px;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<div class="header">
|
||
<h1><i class="fas fa-users-cog"></i> Управление группами пользователей</h1>
|
||
<div class="header-actions">
|
||
<button class="btn btn-primary" onclick="refreshAllData()">
|
||
<i class="fas fa-sync-alt"></i> Обновить
|
||
</button>
|
||
<button class="btn btn-success" onclick="goBack()">
|
||
<i class="fas fa-arrow-left"></i> Назад в CRM
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="tabs">
|
||
<button class="tab secretary active" onclick="showTab('secretary')">
|
||
<i class="fas fa-file-signature"></i> Секретари
|
||
</button>
|
||
<button class="tab administration" onclick="showTab('administration')">
|
||
<i class="fas fa-user-shield"></i> Администрация
|
||
</button>
|
||
<button class="tab help" onclick="showTab('help')">
|
||
<i class="fas fa-hands-helping"></i> Help
|
||
</button>
|
||
<button class="tab doc" onclick="showTab('doc')">
|
||
<i class="fas fa-file-alt"></i> Doc
|
||
</button>
|
||
<button class="tab ahch" onclick="showTab('ahch')">
|
||
<i class="fas fa-school"></i> AHCH
|
||
</button>
|
||
<button class="tab all-users" onclick="showTab('all-users')">
|
||
<i class="fas fa-users"></i> Все пользователи
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Секретари -->
|
||
<div id="secretary-section" class="content-section active">
|
||
<div class="group-info">
|
||
<div class="group-color secretary"></div>
|
||
<div>
|
||
<h3>Группа "Секретарь"</h3>
|
||
<p>Пользователи этой группы могут согласовывать документы в системе</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="search-box">
|
||
<input type="text" id="secretary-search" class="search-input"
|
||
placeholder="Поиск пользователей..." onkeyup="filterUsers('secretary')">
|
||
</div>
|
||
|
||
<div class="stats">
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="secretary-count">0</div>
|
||
<div class="stat-label">Всего пользователей</div>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="secretary-in-group">0</div>
|
||
<div class="stat-label">В группе "Секретарь"</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="secretary-users" class="users-container">
|
||
<div class="loading">
|
||
<i class="fas fa-spinner fa-spin"></i>
|
||
<p>Загрузка пользователей...</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Администрация -->
|
||
<div id="administration-section" class="content-section">
|
||
<div class="group-info">
|
||
<div class="group-color admin"></div>
|
||
<div>
|
||
<h3>Группа "Администрация"</h3>
|
||
<p>Пользователи этой группы имеют права администратора в системе</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="search-box">
|
||
<input type="text" id="admin-search" class="search-input"
|
||
placeholder="Поиск пользователей..." onkeyup="filterUsers('admin')">
|
||
</div>
|
||
|
||
<div class="stats">
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="admin-count">0</div>
|
||
<div class="stat-label">Всего пользователей</div>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="admin-in-group">0</div>
|
||
<div class="stat-label">В группе "Администрация"</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="admin-users" class="users-container">
|
||
<div class="loading">
|
||
<i class="fas fa-spinner fa-spin"></i>
|
||
<p>Загрузка пользователей...</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Help группа -->
|
||
<div id="help-section" class="content-section">
|
||
<div class="group-info">
|
||
<div class="group-color help"></div>
|
||
<div>
|
||
<h3>Группа "Help"</h3>
|
||
<p>Пользователи этой группы получают заявки поддержки</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="search-box">
|
||
<input type="text" id="help-search" class="search-input"
|
||
placeholder="Поиск пользователей..." onkeyup="filterUsers('help')">
|
||
</div>
|
||
|
||
<div class="stats">
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="help-count">0</div>
|
||
<div class="stat-label">Всего пользователей</div>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="help-in-group">0</div>
|
||
<div class="stat-label">В группе "Help"</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="help-users" class="users-container">
|
||
<div class="loading">
|
||
<i class="fas fa-spinner fa-spin"></i>
|
||
<p>Загрузка пользователей...</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Doc группа -->
|
||
<div id="doc-section" class="content-section">
|
||
<div class="group-info">
|
||
<div class="group-color doc"></div>
|
||
<div>
|
||
<h3>Группа "Doc"</h3>
|
||
<p>Пользователи этой группы работают с документами</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="search-box">
|
||
<input type="text" id="doc-search" class="search-input"
|
||
placeholder="Поиск пользователей..." onkeyup="filterUsers('doc')">
|
||
</div>
|
||
|
||
<div class="stats">
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="doc-count">0</div>
|
||
<div class="stat-label">Всего пользователей</div>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="doc-in-group">0</div>
|
||
<div class="stat-label">В группе "Doc"</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="doc-users" class="users-container">
|
||
<div class="loading">
|
||
<i class="fas fa-spinner fa-spin"></i>
|
||
<p>Загрузка пользователей...</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- AHCH группа -->
|
||
<div id="ahch-section" class="content-section">
|
||
<div class="group-info">
|
||
<div class="group-color ahch"></div>
|
||
<div>
|
||
<h3>Группа "AHCH"</h3>
|
||
<p>Пользователи этой группы работают с AHCH задачами</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="search-box">
|
||
<input type="text" id="ahch-search" class="search-input"
|
||
placeholder="Поиск пользователей..." onkeyup="filterUsers('ahch')">
|
||
</div>
|
||
|
||
<div class="stats">
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="ahch-count">0</div>
|
||
<div class="stat-label">Всего пользователей</div>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="ahch-in-group">0</div>
|
||
<div class="stat-label">В группе "AHCH"</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="ahch-users" class="users-container">
|
||
<div class="loading">
|
||
<i class="fas fa-spinner fa-spin"></i>
|
||
<p>Загрузка пользователей...</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Все пользователи -->
|
||
<div id="all-users-section" class="content-section">
|
||
<div class="search-box">
|
||
<input type="text" id="all-search" class="search-input"
|
||
placeholder="Поиск пользователей..." onkeyup="filterUsers('all')">
|
||
</div>
|
||
|
||
<div class="stats">
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="total-users">0</div>
|
||
<div class="stat-label">Всего пользователей</div>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="admins-count">0</div>
|
||
<div class="stat-label">Администрация</div>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="secretaries-count">0</div>
|
||
<div class="stat-label">Секретари</div>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="help-count-all">0</div>
|
||
<div class="stat-label">Help</div>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="doc-count-all">0</div>
|
||
<div class="stat-label">Doc</div>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="stat-number" id="ahch-count-all">0</div>
|
||
<div class="stat-label">AHCH</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="all-users" class="users-container">
|
||
<div class="loading">
|
||
<i class="fas fa-spinner fa-spin"></i>
|
||
<p>Загрузка пользователей...</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
let currentTab = 'secretary';
|
||
let allUsers = [];
|
||
let groupIds = {
|
||
'secretary': null,
|
||
'admin': null,
|
||
'help': null,
|
||
'doc': null,
|
||
'ahch': null
|
||
};
|
||
|
||
// Проверка авторизации
|
||
async function checkAuth() {
|
||
try {
|
||
const response = await fetch('/api/user');
|
||
if (response.status === 401) {
|
||
window.location.href = '/';
|
||
return false;
|
||
}
|
||
const data = await response.json();
|
||
if (data.user.role !== 'admin') {
|
||
alert('Доступ запрещен. Требуются права администратора.');
|
||
window.location.href = '/';
|
||
return false;
|
||
}
|
||
return true;
|
||
} catch (error) {
|
||
console.error('Ошибка проверки авторизации:', error);
|
||
window.location.href = '/';
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// Загрузка данных
|
||
async function loadData() {
|
||
if (!await checkAuth()) return;
|
||
|
||
try {
|
||
// Загружаем группы
|
||
const groupsResponse = await fetch('/api/groups');
|
||
const groups = await groupsResponse.json();
|
||
|
||
// Находим ID всех групп
|
||
groupIds.secretary = groups.find(g => g.name === 'Секретарь')?.id;
|
||
groupIds.admin = groups.find(g => g.name === 'Администрация')?.id;
|
||
groupIds.help = groups.find(g => g.name === 'help')?.id;
|
||
groupIds.doc = groups.find(g => g.name === 'doc')?.id;
|
||
groupIds.ahch = groups.find(g => g.name === 'ahch')?.id;
|
||
|
||
// Загружаем всех пользователей
|
||
const usersResponse = await fetch('/api/users/all');
|
||
const users = await usersResponse.json();
|
||
|
||
allUsers = users;
|
||
|
||
// Обновляем статистику
|
||
updateStats();
|
||
|
||
// Отображаем пользователей
|
||
renderUsers();
|
||
|
||
} catch (error) {
|
||
console.error('Ошибка загрузки данных:', error);
|
||
showError('Не удалось загрузить данные');
|
||
}
|
||
}
|
||
|
||
// Обновление статистики
|
||
function updateStats() {
|
||
// Статистика для секретарей
|
||
const secretaryUsers = allUsers.filter(u => u.groups?.some(g => g.group_name === 'Секретарь'));
|
||
document.getElementById('secretary-count').textContent = allUsers.length;
|
||
document.getElementById('secretary-in-group').textContent = secretaryUsers.length;
|
||
|
||
// Статистика для администрации
|
||
const adminUsers = allUsers.filter(u => u.groups?.some(g => g.group_name === 'Администрация'));
|
||
document.getElementById('admin-count').textContent = allUsers.length;
|
||
document.getElementById('admin-in-group').textContent = adminUsers.length;
|
||
|
||
// Статистика для help
|
||
const helpUsers = allUsers.filter(u => u.groups?.some(g => g.group_name === 'help'));
|
||
document.getElementById('help-count').textContent = allUsers.length;
|
||
document.getElementById('help-in-group').textContent = helpUsers.length;
|
||
|
||
// Статистика для doc
|
||
const docUsers = allUsers.filter(u => u.groups?.some(g => g.group_name === 'doc'));
|
||
document.getElementById('doc-count').textContent = allUsers.length;
|
||
document.getElementById('doc-in-group').textContent = docUsers.length;
|
||
|
||
// Статистика для ahch
|
||
const ahchUsers = allUsers.filter(u => u.groups?.some(g => g.group_name === 'ahch'));
|
||
document.getElementById('ahch-count').textContent = allUsers.length;
|
||
document.getElementById('ahch-in-group').textContent = ahchUsers.length;
|
||
|
||
// Общая статистика
|
||
document.getElementById('total-users').textContent = allUsers.length;
|
||
document.getElementById('admins-count').textContent = adminUsers.length;
|
||
document.getElementById('secretaries-count').textContent = secretaryUsers.length;
|
||
document.getElementById('help-count-all').textContent = helpUsers.length;
|
||
document.getElementById('doc-count-all').textContent = docUsers.length;
|
||
document.getElementById('ahch-count-all').textContent = ahchUsers.length;
|
||
}
|
||
|
||
// Отображение пользователей
|
||
function renderUsers() {
|
||
renderSecretaryUsers();
|
||
renderAdminUsers();
|
||
renderHelpUsers();
|
||
renderDocUsers();
|
||
renderAhchUsers();
|
||
renderAllUsers();
|
||
}
|
||
|
||
// Проверка, состоит ли пользователь в группе
|
||
function isUserInGroup(user, groupName) {
|
||
return user.groups?.some(g => g.group_name === groupName);
|
||
}
|
||
|
||
// Получение иконки для группы
|
||
function getGroupIcon(groupName) {
|
||
const icons = {
|
||
'Секретарь': 'fa-file-signature',
|
||
'Администрация': 'fa-user-shield',
|
||
'help': 'fa-hands-helping',
|
||
'doc': 'fa-file-alt',
|
||
'ahch': 'fa-school'
|
||
};
|
||
return icons[groupName] || 'fa-users';
|
||
}
|
||
|
||
// Отображение пользователей для секретарей
|
||
function renderSecretaryUsers() {
|
||
const container = document.getElementById('secretary-users');
|
||
const searchTerm = document.getElementById('secretary-search').value.toLowerCase();
|
||
|
||
const filteredUsers = allUsers.filter(user =>
|
||
user.name.toLowerCase().includes(searchTerm) ||
|
||
user.login.toLowerCase().includes(searchTerm) ||
|
||
user.email.toLowerCase().includes(searchTerm)
|
||
);
|
||
|
||
if (filteredUsers.length === 0) {
|
||
container.innerHTML = `
|
||
<div class="no-users">
|
||
<i class="fas fa-users-slash" style="font-size: 48px; color: #ccc; margin-bottom: 15px;"></i>
|
||
<p>Пользователи не найдены</p>
|
||
</div>
|
||
`;
|
||
return;
|
||
}
|
||
|
||
container.innerHTML = filteredUsers.map(user => {
|
||
const isSecretary = isUserInGroup(user, 'Секретарь');
|
||
const isAdmin = isUserInGroup(user, 'Администрация');
|
||
const isHelp = isUserInGroup(user, 'help');
|
||
const isDoc = isUserInGroup(user, 'doc');
|
||
const isAhch = isUserInGroup(user, 'ahch');
|
||
|
||
return `
|
||
<div class="user-card">
|
||
<div class="user-header">
|
||
<div class="user-avatar">${user.name.charAt(0).toUpperCase()}</div>
|
||
<div>
|
||
<div class="user-name">${user.name}</div>
|
||
<div class="user-role">${user.role === 'admin' ? 'Администратор' : 'Пользователь'}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="user-details">
|
||
<div><i class="fas fa-user"></i> ${user.login}</div>
|
||
<div><i class="fas fa-envelope"></i> ${user.email}</div>
|
||
</div>
|
||
|
||
<div class="group-badges">
|
||
${isSecretary ? '<span class="group-badge secretary"><i class="fas fa-file-signature"></i> Секретарь</span>' : ''}
|
||
${isAdmin ? '<span class="group-badge admin"><i class="fas fa-user-shield"></i> Администрация</span>' : ''}
|
||
${isHelp ? '<span class="group-badge help"><i class="fas fa-hands-helping"></i> help</span>' : ''}
|
||
${isDoc ? '<span class="group-badge doc"><i class="fas fa-file-alt"></i> doc</span>' : ''}
|
||
${isAhch ? '<span class="group-badge ahch"><i class="fas fa-school"></i> ahch</span>' : ''}
|
||
</div>
|
||
|
||
<div class="user-actions">
|
||
${isSecretary ?
|
||
`<button class="btn btn-danger" onclick="removeFromGroup(${user.id}, 'secretary')">
|
||
<i class="fas fa-user-minus"></i> Убрать
|
||
</button>` :
|
||
`<button class="btn btn-success" onclick="addToGroup(${user.id}, 'secretary')">
|
||
<i class="fas fa-user-plus"></i> Добавить
|
||
</button>`
|
||
}
|
||
</div>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
}
|
||
|
||
// Отображение пользователей для администрации
|
||
function renderAdminUsers() {
|
||
const container = document.getElementById('admin-users');
|
||
const searchTerm = document.getElementById('admin-search').value.toLowerCase();
|
||
|
||
const filteredUsers = allUsers.filter(user =>
|
||
user.name.toLowerCase().includes(searchTerm) ||
|
||
user.login.toLowerCase().includes(searchTerm) ||
|
||
user.email.toLowerCase().includes(searchTerm)
|
||
);
|
||
|
||
if (filteredUsers.length === 0) {
|
||
container.innerHTML = `
|
||
<div class="no-users">
|
||
<i class="fas fa-users-slash" style="font-size: 48px; color: #ccc; margin-bottom: 15px;"></i>
|
||
<p>Пользователи не найдены</p>
|
||
</div>
|
||
`;
|
||
return;
|
||
}
|
||
|
||
container.innerHTML = filteredUsers.map(user => {
|
||
const isSecretary = isUserInGroup(user, 'Секретарь');
|
||
const isAdmin = isUserInGroup(user, 'Администрация');
|
||
const isHelp = isUserInGroup(user, 'help');
|
||
const isDoc = isUserInGroup(user, 'doc');
|
||
const isAhch = isUserInGroup(user, 'ahch');
|
||
|
||
return `
|
||
<div class="user-card">
|
||
<div class="user-header">
|
||
<div class="user-avatar">${user.name.charAt(0).toUpperCase()}</div>
|
||
<div>
|
||
<div class="user-name">${user.name}</div>
|
||
<div class="user-role">${user.role === 'admin' ? 'Администратор' : 'Пользователь'}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="user-details">
|
||
<div><i class="fas fa-user"></i> ${user.login}</div>
|
||
<div><i class="fas fa-envelope"></i> ${user.email}</div>
|
||
</div>
|
||
|
||
<div class="group-badges">
|
||
${isSecretary ? '<span class="group-badge secretary"><i class="fas fa-file-signature"></i> Секретарь</span>' : ''}
|
||
${isAdmin ? '<span class="group-badge admin"><i class="fas fa-user-shield"></i> Администрация</span>' : ''}
|
||
${isHelp ? '<span class="group-badge help"><i class="fas fa-hands-helping"></i> help</span>' : ''}
|
||
${isDoc ? '<span class="group-badge doc"><i class="fas fa-file-alt"></i> doc</span>' : ''}
|
||
${isAhch ? '<span class="group-badge ahch"><i class="fas fa-school"></i> ahch</span>' : ''}
|
||
</div>
|
||
|
||
<div class="user-actions">
|
||
${isAdmin ?
|
||
`<button class="btn btn-danger" onclick="removeFromGroup(${user.id}, 'admin')">
|
||
<i class="fas fa-user-minus"></i> Убрать
|
||
</button>` :
|
||
`<button class="btn btn-success" onclick="addToGroup(${user.id}, 'admin')">
|
||
<i class="fas fa-user-plus"></i> Добавить
|
||
</button>`
|
||
}
|
||
</div>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
}
|
||
|
||
// Отображение пользователей для help
|
||
function renderHelpUsers() {
|
||
const container = document.getElementById('help-users');
|
||
const searchTerm = document.getElementById('help-search').value.toLowerCase();
|
||
|
||
const filteredUsers = allUsers.filter(user =>
|
||
user.name.toLowerCase().includes(searchTerm) ||
|
||
user.login.toLowerCase().includes(searchTerm) ||
|
||
user.email.toLowerCase().includes(searchTerm)
|
||
);
|
||
|
||
if (filteredUsers.length === 0) {
|
||
container.innerHTML = `
|
||
<div class="no-users">
|
||
<i class="fas fa-users-slash" style="font-size: 48px; color: #ccc; margin-bottom: 15px;"></i>
|
||
<p>Пользователи не найдены</p>
|
||
</div>
|
||
`;
|
||
return;
|
||
}
|
||
|
||
container.innerHTML = filteredUsers.map(user => {
|
||
const isSecretary = isUserInGroup(user, 'Секретарь');
|
||
const isAdmin = isUserInGroup(user, 'Администрация');
|
||
const isHelp = isUserInGroup(user, 'help');
|
||
const isDoc = isUserInGroup(user, 'doc');
|
||
const isAhch = isUserInGroup(user, 'ahch');
|
||
|
||
return `
|
||
<div class="user-card">
|
||
<div class="user-header">
|
||
<div class="user-avatar">${user.name.charAt(0).toUpperCase()}</div>
|
||
<div>
|
||
<div class="user-name">${user.name}</div>
|
||
<div class="user-role">${user.role === 'admin' ? 'Администратор' : 'Пользователь'}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="user-details">
|
||
<div><i class="fas fa-user"></i> ${user.login}</div>
|
||
<div><i class="fas fa-envelope"></i> ${user.email}</div>
|
||
</div>
|
||
|
||
<div class="group-badges">
|
||
${isSecretary ? '<span class="group-badge secretary"><i class="fas fa-file-signature"></i> Секретарь</span>' : ''}
|
||
${isAdmin ? '<span class="group-badge admin"><i class="fas fa-user-shield"></i> Администрация</span>' : ''}
|
||
${isHelp ? '<span class="group-badge help"><i class="fas fa-hands-helping"></i> help</span>' : ''}
|
||
${isDoc ? '<span class="group-badge doc"><i class="fas fa-file-alt"></i> doc</span>' : ''}
|
||
${isAhch ? '<span class="group-badge ahch"><i class="fas fa-school"></i> ahch</span>' : ''}
|
||
</div>
|
||
|
||
<div class="user-actions">
|
||
${isHelp ?
|
||
`<button class="btn btn-danger" onclick="removeFromGroup(${user.id}, 'help')">
|
||
<i class="fas fa-user-minus"></i> Убрать
|
||
</button>` :
|
||
`<button class="btn btn-help" onclick="addToGroup(${user.id}, 'help')">
|
||
<i class="fas fa-user-plus"></i> Добавить
|
||
</button>`
|
||
}
|
||
</div>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
}
|
||
|
||
// Отображение пользователей для doc
|
||
function renderDocUsers() {
|
||
const container = document.getElementById('doc-users');
|
||
const searchTerm = document.getElementById('doc-search').value.toLowerCase();
|
||
|
||
const filteredUsers = allUsers.filter(user =>
|
||
user.name.toLowerCase().includes(searchTerm) ||
|
||
user.login.toLowerCase().includes(searchTerm) ||
|
||
user.email.toLowerCase().includes(searchTerm)
|
||
);
|
||
|
||
if (filteredUsers.length === 0) {
|
||
container.innerHTML = `
|
||
<div class="no-users">
|
||
<i class="fas fa-users-slash" style="font-size: 48px; color: #ccc; margin-bottom: 15px;"></i>
|
||
<p>Пользователи не найдены</p>
|
||
</div>
|
||
`;
|
||
return;
|
||
}
|
||
|
||
container.innerHTML = filteredUsers.map(user => {
|
||
const isSecretary = isUserInGroup(user, 'Секретарь');
|
||
const isAdmin = isUserInGroup(user, 'Администрация');
|
||
const isHelp = isUserInGroup(user, 'help');
|
||
const isDoc = isUserInGroup(user, 'doc');
|
||
const isAhch = isUserInGroup(user, 'ahch');
|
||
|
||
return `
|
||
<div class="user-card">
|
||
<div class="user-header">
|
||
<div class="user-avatar">${user.name.charAt(0).toUpperCase()}</div>
|
||
<div>
|
||
<div class="user-name">${user.name}</div>
|
||
<div class="user-role">${user.role === 'admin' ? 'Администратор' : 'Пользователь'}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="user-details">
|
||
<div><i class="fas fa-user"></i> ${user.login}</div>
|
||
<div><i class="fas fa-envelope"></i> ${user.email}</div>
|
||
</div>
|
||
|
||
<div class="group-badges">
|
||
${isSecretary ? '<span class="group-badge secretary"><i class="fas fa-file-signature"></i> Секретарь</span>' : ''}
|
||
${isAdmin ? '<span class="group-badge admin"><i class="fas fa-user-shield"></i> Администрация</span>' : ''}
|
||
${isHelp ? '<span class="group-badge help"><i class="fas fa-hands-helping"></i> help</span>' : ''}
|
||
${isDoc ? '<span class="group-badge doc"><i class="fas fa-file-alt"></i> doc</span>' : ''}
|
||
${isAhch ? '<span class="group-badge ahch"><i class="fas fa-school"></i> ahch</span>' : ''}
|
||
</div>
|
||
|
||
<div class="user-actions">
|
||
${isDoc ?
|
||
`<button class="btn btn-danger" onclick="removeFromGroup(${user.id}, 'doc')">
|
||
<i class="fas fa-user-minus"></i> Убрать
|
||
</button>` :
|
||
`<button class="btn btn-doc" onclick="addToGroup(${user.id}, 'doc')">
|
||
<i class="fas fa-user-plus"></i> Добавить
|
||
</button>`
|
||
}
|
||
</div>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
}
|
||
|
||
// Отображение пользователей для ahch
|
||
function renderAhchUsers() {
|
||
const container = document.getElementById('ahch-users');
|
||
const searchTerm = document.getElementById('ahch-search').value.toLowerCase();
|
||
|
||
const filteredUsers = allUsers.filter(user =>
|
||
user.name.toLowerCase().includes(searchTerm) ||
|
||
user.login.toLowerCase().includes(searchTerm) ||
|
||
user.email.toLowerCase().includes(searchTerm)
|
||
);
|
||
|
||
if (filteredUsers.length === 0) {
|
||
container.innerHTML = `
|
||
<div class="no-users">
|
||
<i class="fas fa-users-slash" style="font-size: 48px; color: #ccc; margin-bottom: 15px;"></i>
|
||
<p>Пользователи не найдены</p>
|
||
</div>
|
||
`;
|
||
return;
|
||
}
|
||
|
||
container.innerHTML = filteredUsers.map(user => {
|
||
const isSecretary = isUserInGroup(user, 'Секретарь');
|
||
const isAdmin = isUserInGroup(user, 'Администрация');
|
||
const isHelp = isUserInGroup(user, 'help');
|
||
const isDoc = isUserInGroup(user, 'doc');
|
||
const isAhch = isUserInGroup(user, 'ahch');
|
||
|
||
return `
|
||
<div class="user-card">
|
||
<div class="user-header">
|
||
<div class="user-avatar">${user.name.charAt(0).toUpperCase()}</div>
|
||
<div>
|
||
<div class="user-name">${user.name}</div>
|
||
<div class="user-role">${user.role === 'admin' ? 'Администратор' : 'Пользователь'}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="user-details">
|
||
<div><i class="fas fa-user"></i> ${user.login}</div>
|
||
<div><i class="fas fa-envelope"></i> ${user.email}</div>
|
||
</div>
|
||
|
||
<div class="group-badges">
|
||
${isSecretary ? '<span class="group-badge secretary"><i class="fas fa-file-signature"></i> Секретарь</span>' : ''}
|
||
${isAdmin ? '<span class="group-badge admin"><i class="fas fa-user-shield"></i> Администрация</span>' : ''}
|
||
${isHelp ? '<span class="group-badge help"><i class="fas fa-hands-helping"></i> help</span>' : ''}
|
||
${isDoc ? '<span class="group-badge doc"><i class="fas fa-file-alt"></i> doc</span>' : ''}
|
||
${isAhch ? '<span class="group-badge ahch"><i class="fas fa-school"></i> ahch</span>' : ''}
|
||
</div>
|
||
|
||
<div class="user-actions">
|
||
${isAhch ?
|
||
`<button class="btn btn-danger" onclick="removeFromGroup(${user.id}, 'ahch')">
|
||
<i class="fas fa-user-minus"></i> Убрать
|
||
</button>` :
|
||
`<button class="btn btn-ahch" onclick="addToGroup(${user.id}, 'ahch')">
|
||
<i class="fas fa-user-plus"></i> Добавить
|
||
</button>`
|
||
}
|
||
</div>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
}
|
||
|
||
// Отображение всех пользователей
|
||
function renderAllUsers() {
|
||
const container = document.getElementById('all-users');
|
||
const searchTerm = document.getElementById('all-search').value.toLowerCase();
|
||
|
||
const filteredUsers = allUsers.filter(user =>
|
||
user.name.toLowerCase().includes(searchTerm) ||
|
||
user.login.toLowerCase().includes(searchTerm) ||
|
||
user.email.toLowerCase().includes(searchTerm)
|
||
);
|
||
|
||
if (filteredUsers.length === 0) {
|
||
container.innerHTML = `
|
||
<div class="no-users">
|
||
<i class="fas fa-users-slash" style="font-size: 48px; color: #ccc; margin-bottom: 15px;"></i>
|
||
<p>Пользователи не найдены</p>
|
||
</div>
|
||
`;
|
||
return;
|
||
}
|
||
|
||
container.innerHTML = filteredUsers.map(user => {
|
||
const isSecretary = isUserInGroup(user, 'Секретарь');
|
||
const isAdmin = isUserInGroup(user, 'Администрация');
|
||
const isHelp = isUserInGroup(user, 'help');
|
||
const isDoc = isUserInGroup(user, 'doc');
|
||
const isAhch = isUserInGroup(user, 'ahch');
|
||
|
||
return `
|
||
<div class="user-card">
|
||
<div class="user-header">
|
||
<div class="user-avatar">${user.name.charAt(0).toUpperCase()}</div>
|
||
<div>
|
||
<div class="user-name">${user.name}</div>
|
||
<div class="user-role">${user.role === 'admin' ? 'Администратор' : 'Пользователь'}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="user-details">
|
||
<div><i class="fas fa-user"></i> ${user.login}</div>
|
||
<div><i class="fas fa-envelope"></i> ${user.email}</div>
|
||
</div>
|
||
|
||
<div class="all-groups-badges">
|
||
${isSecretary ? '<span class="group-badge secretary"><i class="fas fa-file-signature"></i> Секретарь</span>' : ''}
|
||
${isAdmin ? '<span class="group-badge admin"><i class="fas fa-user-shield"></i> Администрация</span>' : ''}
|
||
${isHelp ? '<span class="group-badge help"><i class="fas fa-hands-helping"></i> help</span>' : ''}
|
||
${isDoc ? '<span class="group-badge doc"><i class="fas fa-file-alt"></i> doc</span>' : ''}
|
||
${isAhch ? '<span class="group-badge ahch"><i class="fas fa-school"></i> ahch</span>' : ''}
|
||
</div>
|
||
|
||
<div class="user-actions">
|
||
${isSecretary ?
|
||
`<button class="btn btn-danger" onclick="removeFromGroup(${user.id}, 'secretary')" title="Убрать из секретарей">
|
||
<i class="fas fa-user-minus"></i>
|
||
</button>` :
|
||
`<button class="btn btn-success" onclick="addToGroup(${user.id}, 'secretary')" title="Добавить в секретари">
|
||
<i class="fas fa-user-plus"></i>
|
||
</button>`
|
||
}
|
||
${isAdmin ?
|
||
`<button class="btn btn-danger" onclick="removeFromGroup(${user.id}, 'admin')" title="Убрать из администрации">
|
||
<i class="fas fa-user-minus"></i>
|
||
</button>` :
|
||
`<button class="btn btn-primary" onclick="addToGroup(${user.id}, 'admin')" title="Добавить в администрацию">
|
||
<i class="fas fa-user-plus"></i>
|
||
</button>`
|
||
}
|
||
${isHelp ?
|
||
`<button class="btn btn-danger" onclick="removeFromGroup(${user.id}, 'help')" title="Убрать из help">
|
||
<i class="fas fa-user-minus"></i>
|
||
</button>` :
|
||
`<button class="btn btn-help" onclick="addToGroup(${user.id}, 'help')" title="Добавить в help">
|
||
<i class="fas fa-user-plus"></i>
|
||
</button>`
|
||
}
|
||
${isDoc ?
|
||
`<button class="btn btn-danger" onclick="removeFromGroup(${user.id}, 'doc')" title="Убрать из doc">
|
||
<i class="fas fa-user-minus"></i>
|
||
</button>` :
|
||
`<button class="btn btn-doc" onclick="addToGroup(${user.id}, 'doc')" title="Добавить в doc">
|
||
<i class="fas fa-user-plus"></i>
|
||
</button>`
|
||
}
|
||
${isAhch ?
|
||
`<button class="btn btn-danger" onclick="removeFromGroup(${user.id}, 'ahch')" title="Убрать из ahch">
|
||
<i class="fas fa-user-minus"></i>
|
||
</button>` :
|
||
`<button class="btn btn-ahch" onclick="addToGroup(${user.id}, 'ahch')" title="Добавить в ahch">
|
||
<i class="fas fa-user-plus"></i>
|
||
</button>`
|
||
}
|
||
</div>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
}
|
||
|
||
// Фильтрация пользователей
|
||
function filterUsers(section) {
|
||
switch(section) {
|
||
case 'secretary':
|
||
renderSecretaryUsers();
|
||
break;
|
||
case 'admin':
|
||
renderAdminUsers();
|
||
break;
|
||
case 'help':
|
||
renderHelpUsers();
|
||
break;
|
||
case 'doc':
|
||
renderDocUsers();
|
||
break;
|
||
case 'ahch':
|
||
renderAhchUsers();
|
||
break;
|
||
case 'all':
|
||
renderAllUsers();
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Показать вкладку
|
||
function showTab(tabName) {
|
||
currentTab = tabName;
|
||
|
||
// Обновляем активные вкладки
|
||
document.querySelectorAll('.tab').forEach(tab => {
|
||
tab.classList.remove('active');
|
||
});
|
||
document.querySelectorAll('.content-section').forEach(section => {
|
||
section.classList.remove('active');
|
||
});
|
||
|
||
// Активируем выбранную вкладку
|
||
document.querySelector(`.tab.${tabName}`).classList.add('active');
|
||
document.getElementById(`${tabName}-section`).classList.add('active');
|
||
}
|
||
|
||
// Добавить пользователя в группу
|
||
async function addToGroup(userId, groupType) {
|
||
if (!await checkAuth()) return;
|
||
|
||
const groupNames = {
|
||
'secretary': 'Секретарь',
|
||
'admin': 'Администрация',
|
||
'help': 'help',
|
||
'doc': 'doc',
|
||
'ahch': 'ahch'
|
||
};
|
||
|
||
const groupName = groupNames[groupType];
|
||
const groupId = groupIds[groupType];
|
||
|
||
if (!groupId) {
|
||
showError(`Группа "${groupName}" не найдена`);
|
||
return;
|
||
}
|
||
|
||
if (!confirm(`Добавить пользователя в группу "${groupName}"?`)) return;
|
||
|
||
try {
|
||
const response = await fetch(`/api/groups/${groupId}/users/${userId}`, {
|
||
method: 'POST'
|
||
});
|
||
|
||
if (response.ok) {
|
||
showSuccess(`Пользователь добавлен в группу "${groupName}"`);
|
||
await refreshAllData();
|
||
} else {
|
||
const error = await response.text();
|
||
showError(error);
|
||
}
|
||
} catch (error) {
|
||
console.error('Ошибка добавления в группу:', error);
|
||
showError('Не удалось добавить пользователя в группу');
|
||
}
|
||
}
|
||
|
||
// Удалить пользователя из группы
|
||
async function removeFromGroup(userId, groupType) {
|
||
if (!await checkAuth()) return;
|
||
|
||
const groupNames = {
|
||
'secretary': 'Секретарь',
|
||
'admin': 'Администрация',
|
||
'help': 'help',
|
||
'doc': 'doc',
|
||
'ahch': 'ahch'
|
||
};
|
||
|
||
const groupName = groupNames[groupType];
|
||
const groupId = groupIds[groupType];
|
||
|
||
if (!groupId) {
|
||
showError(`Группа "${groupName}" не найдена`);
|
||
return;
|
||
}
|
||
|
||
if (!confirm(`Убрать пользователя из группы "${groupName}"?`)) return;
|
||
|
||
try {
|
||
const response = await fetch(`/api/groups/${groupId}/users/${userId}`, {
|
||
method: 'DELETE'
|
||
});
|
||
|
||
if (response.ok) {
|
||
showSuccess(`Пользователь убран из группы "${groupName}"`);
|
||
await refreshAllData();
|
||
} else {
|
||
const error = await response.text();
|
||
showError(error);
|
||
}
|
||
} catch (error) {
|
||
console.error('Ошибка удаления из группы:', error);
|
||
showError('Не удалось убрать пользователя из группы');
|
||
}
|
||
}
|
||
|
||
// Обновить все данные
|
||
async function refreshAllData() {
|
||
await loadData();
|
||
showSuccess('Данные обновлены');
|
||
}
|
||
|
||
// Показать сообщение об ошибке
|
||
function showError(message) {
|
||
alert('Ошибка: ' + message);
|
||
}
|
||
|
||
// Показать сообщение об успехе
|
||
function showSuccess(message) {
|
||
// Можно заменить на более красивый toast
|
||
alert('Успех: ' + message);
|
||
}
|
||
|
||
// Вернуться в CRM
|
||
function goBack() {
|
||
window.location.href = '/';
|
||
}
|
||
|
||
// Инициализация
|
||
document.addEventListener('DOMContentLoaded', async () => {
|
||
if (await checkAuth()) {
|
||
await loadData();
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |