Кабинет
@@ -4249,7 +4311,10 @@ window.addEventListener('DOMContentLoaded', checkReturning);
var _origGo2 = window.go;
window.go = function(id) {
if (_origGo2) _origGo2(id);
- if (id === 'cabinet') setTimeout(render, 80);
+ if (id === 'cabinet') {
+ setTimeout(render, 80);
+ if (typeof _initOrgUser === 'function') setTimeout(_initOrgUser, 120);
+ }
};
window.addEventListener('DOMContentLoaded', function(){
var el = document.getElementById('ct-tbody');
@@ -7469,6 +7534,7 @@ function tab(name){
if(name==='shab' && typeof renderContextTemplates==='function') renderContextTemplates();
if(name==='requisites' && typeof _loadRequisites==='function') _loadRequisites();
if(name==='casemap' && typeof renderCaseMap==='function') renderCaseMap();
+ if(name==='team' && typeof renderTeamDashboard==='function') renderTeamDashboard();
if(name==='docs') {
var contracts = typeof _getContracts === 'function' ? _getContracts() : [];
if (contracts.length && typeof renderDocChecklist === 'function') renderDocChecklist(contracts[0].type);
@@ -7782,6 +7848,234 @@ function _compressAsync(showToast) {
.catch(function(){});
}
+// ── МУЛЬТИПОЛЬЗОВАТЕЛЬ / ОРГАНИЗАЦИЯ ────────────────────────────────────────
+
+var _ORG_KEY = 'zashita_org'; // {org_id, name}
+var _USER_KEY = 'zashita_user'; // {user_id, name, role, token, org_id}
+
+function _getOrgUser() {
+ try { return JSON.parse(localStorage.getItem(_USER_KEY) || 'null'); } catch(e){ return null; }
+}
+
+function _setOrgUser(user) {
+ try { localStorage.setItem(_USER_KEY, JSON.stringify(user)); } catch(e){}
+}
+
+function _orgHeaders() {
+ var u = _getOrgUser();
+ return u ? {'Content-Type':'application/json','X-User-Token': u.token} : {'Content-Type':'application/json'};
+}
+
+// Регистрация организации
+function _registerOrg() {
+ var orgName = (document.getElementById('reg-org-name') ||{}).value||'';
+ var inn = (document.getElementById('reg-inn') ||{}).value||'';
+ var adminName = (document.getElementById('reg-admin-name') ||{}).value||'';
+ var adminEmail = (document.getElementById('reg-admin-email')||{}).value||'';
+ var adminPhone = (document.getElementById('reg-admin-phone')||{}).value||'';
+
+ if (!orgName || !adminName) { toast('Заполните название организации и имя'); return; }
+
+ fetch(API_BASE + '/api/org/register', {
+ method: 'POST', headers: {'Content-Type':'application/json'},
+ body: JSON.stringify({org_name:orgName, inn:inn, admin_name:adminName,
+ admin_email:adminEmail, admin_phone:adminPhone})
+ })
+ .then(function(r){ return r.json(); })
+ .then(function(d) {
+ if (d.error) { toast('Ошибка: ' + d.error); return; }
+ _setOrgUser({user_id:d.user_id, org_id:d.org_id, role:d.role, token:d.token,
+ name:adminName, org_name:orgName});
+ _afterOrgLogin(d.role);
+ toast('✅ Организация зарегистрирована');
+ }).catch(function(e){ toast('Ошибка: ' + e.message); });
+}
+
+// Вход по токену
+function _loginByToken() {
+ var token = (document.getElementById('org-token-inp')||{}).value||'';
+ if (!token.trim()) { toast('Введите токен'); return; }
+
+ fetch(API_BASE + '/api/org/me', {
+ method: 'POST', headers: {'Content-Type':'application/json'},
+ body: JSON.stringify({token: token.trim()})
+ })
+ .then(function(r){ return r.json(); })
+ .then(function(d) {
+ if (d.error) { toast('Токен не найден'); return; }
+ var u = d.user; var o = d.org;
+ _setOrgUser({user_id:u.id, org_id:u.org_id, role:u.role, token:token.trim(),
+ name:u.name, org_name:o.name||''});
+ _afterOrgLogin(u.role);
+ toast('✅ Добро пожаловать, ' + u.name);
+ }).catch(function(){ toast('Ошибка входа'); });
+}
+
+function _afterOrgLogin(role) {
+ // Показываем вкладку Команда для manager/admin
+ var teamTab = document.getElementById('t-team');
+ if (teamTab) teamTab.style.display = (role === 'manager' || role === 'admin') ? '' : 'none';
+
+ // Обновляем нижнюю панель кабинета
+ _updateSidebarUser();
+ go('cabinet');
+}
+
+function _showOrgLogin() {
+ var f = document.getElementById('org-login-form');
+ if (f) f.style.display = f.style.display === 'none' ? '' : 'none';
+}
+
+function _updateSidebarUser() {
+ var u = _getOrgUser();
+ if (!u) return;
+ // Обновляем имя в сайдбаре
+ var nameEl = document.querySelector('.side-user-name');
+ if (nameEl) nameEl.textContent = u.name;
+ var orgEl = document.querySelector('.side-user-plan');
+ if (orgEl) orgEl.textContent = u.org_name || 'Организация';
+}
+
+// Дашборд команды
+function renderTeamDashboard() {
+ var el = document.getElementById('team-dashboard');
+ if (!el) return;
+ var u = _getOrgUser();
+ if (!u || (u.role !== 'manager' && u.role !== 'admin')) {
+ el.innerHTML = '
Только для менеджеров
';
+ return;
+ }
+
+ el.innerHTML = '
Загружаю данные...
';
+
+ fetch(API_BASE + '/api/org/dashboard', {
+ method: 'POST', headers: _orgHeaders(), body: JSON.stringify({token: u.token})
+ })
+ .then(function(r){ return r.json(); })
+ .then(function(d) {
+ if (d.error) { el.innerHTML = '
' + d.error + '
'; return; }
+
+ var html = '
' +
+ '
👥
' + d.users.length + '
Сотрудников
' +
+ '
📁
' + d.active_cases + '
Активных дел
' +
+ '
⚠️
' + d.urgent_cases + '
Срочных
' +
+ '
';
+
+ d.users.forEach(function(usr) {
+ var roleLabel = {user:'Сотрудник', manager:'Менеджер', admin:'Администратор'}[usr.role]||usr.role;
+ var lastSeen = usr.last_seen ? new Date(usr.last_seen).toLocaleDateString('ru-RU') : 'не заходил';
+ html += '
' +
+ '
' +
+ '
' +
+ (usr.name||'?')[0].toUpperCase() +
+ '
' +
+ '
' +
+ '
' + (usr.name||'—') + '
' +
+ '
' + roleLabel +
+ (usr.department ? ' · ' + usr.department : '') + ' · последний вход: ' + lastSeen +
+ '
' +
+ '
' +
+ '
' +
+ '' +
+ usr.cases_active + ' дел' + (usr.cases_urgent ? ' ⚠️'+usr.cases_urgent : '') +
+ '' +
+ '
' +
+ '
';
+
+ if (usr.cases.length) {
+ html += '
';
+ usr.cases.slice(0,3).forEach(function(c){
+ var riskColor = {high:'#dc2626',medium:'#d97706',low:'#16a34a'}[c.risk_level]||'#6b7280';
+ html += '
' +
+ '●' +
+ '' + (c.title||'Без названия') + '' +
+ '' + (c.type||'') + '' +
+ '
';
+ });
+ html += '
';
+ }
+ html += '
';
+ });
+
+ html += '
';
+ el.innerHTML = html;
+ })
+ .catch(function(){ el.innerHTML = '
Ошибка загрузки
'; });
+}
+
+// Приглашение сотрудника
+function _showInviteModal() {
+ var old = document.getElementById('invite-modal'); if(old) old.remove();
+ var u = _getOrgUser(); if (!u) return;
+ var modal = document.createElement('div');
+ modal.id = 'invite-modal';
+ modal.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:1000;display:flex;align-items:flex-end;justify-content:center';
+ modal.innerHTML =
+ '
';
+ document.body.appendChild(modal);
+ setTimeout(function(){ var i=document.getElementById('inv-name'); if(i) i.focus(); }, 200);
+}
+
+function _doInvite() {
+ var u = _getOrgUser(); if (!u) return;
+ var name = (document.getElementById('inv-name')||{}).value||'';
+ if (!name) { toast('Введите имя'); return; }
+
+ fetch(API_BASE + '/api/org/invite', {
+ method: 'POST', headers: _orgHeaders(),
+ body: JSON.stringify({
+ token: u.token,
+ name: name,
+ email: (document.getElementById('inv-email')||{}).value||'',
+ phone: (document.getElementById('inv-phone')||{}).value||'',
+ department: (document.getElementById('inv-dept') ||{}).value||'',
+ role: (document.getElementById('inv-role') ||{}).value||'user',
+ })
+ })
+ .then(function(r){ return r.json(); })
+ .then(function(d) {
+ if (d.error) { toast('Ошибка: '+d.error); return; }
+ var res = document.getElementById('invite-result');
+ if (res) res.innerHTML =
+ '
' +
+ '
✅ Приглашение создано
' +
+ '
Токен для входа:
' +
+ '
' +
+ d.invite_token +
+ '
' +
+ '
' +
+ '
';
+ renderTeamDashboard();
+ }).catch(function(){ toast('Ошибка'); });
+}
+
+// Инициализация мультипользователя при загрузке кабинета
+function _initOrgUser() {
+ var u = _getOrgUser();
+ if (!u) return;
+ var teamTab = document.getElementById('t-team');
+ if (teamTab) teamTab.style.display = (u.role==='manager'||u.role==='admin') ? '' : 'none';
+ _updateSidebarUser();
+}
+
// ── КАРТА ДЕЛА ───────────────────────────────────────────────────────────────
var _CASE_NOTES_KEY = 'zashita_case_notes';