diff --git a/mockup.html b/mockup.html index ab3019e..5b5211e 100644 --- a/mockup.html +++ b/mockup.html @@ -1241,7 +1241,10 @@ body{font-family:var(--font-ui);background:var(--surf);color:var(--ink);line-hei
🔒 Без регистрации · данные у вас · первые 3 риска бесплатно
-
+
+ + +
+ +
+
ЗАЩИТА + Регистрация организации + ← назад +
+
+
+
Корпоративный доступ. Один кабинет на всю компанию — каждому сотруднику свой доступ, руководителю — общий дашборд.
+
+ +
+
+
Организация
+ +
+
+
ИНН
+ +
+
+
Администратор (вы)
+
+ + + +
+
+ +
+ Уже зарегистрированы? Войти по токену +
+
+ + + +
+
+
ЗАЩИТАВыбор варианта← назад
@@ -1727,6 +1777,7 @@ body{font-family:var(--font-ui);background:var(--surf);color:var(--ink);line-hei ✍️ Составить документ ✅ Мои документы 📝 Карта дела + 🖊️ Реквизиты 💳 Баланс и оплата ↩ Выйти (в начало) @@ -2268,6 +2319,17 @@ body{font-family:var(--font-ui);background:var(--surf);color:var(--ink);line-hei + +
+
+

👥 Команда

+ +
+
+
Загрузка...
+
+
+
Кабинет
@@ -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';