diff --git a/index.html b/index.html
index c00191a..1e694ff 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,14 @@ body{
.btn-outline:hover{border-color:var(--cyan); color:var(--cyan)}
.btn-sm{padding:6px 14px; font-size:12px}
.btn-block{width:100%}
-.login-error{color:var(--red); font-size:13px; text-align:center; margin-top:12px; display:none}
+ .login-error{color:var(--red); font-size:13px; text-align:center; margin-top:12px; display:none}
+.login-tabs{display:flex; gap:0; margin-bottom:24px; border-radius:var(--radius); overflow:hidden; border:2px solid var(--gray-200)}
+.login-tab{flex:1; padding:10px; text-align:center; font-size:14px; font-weight:700; cursor:pointer; background:var(--white); color:var(--gray-500); transition:all .2s; border:none; font-family:inherit}
+.login-tab.active{background:var(--cyan); color:var(--white); border-color:var(--cyan)}
+.login-tab:first-child{border-right:1px solid var(--gray-200)}
+.login-form{display:none}
+.login-form.active{display:block}
+.register-success{background:var(--green-bg); border:1px solid var(--green); border-radius:var(--radius); padding:12px 16px; color:var(--green); font-weight:600; text-align:center; margin-top:12px; display:none}
/* ===== APP ===== */
.app-screen{display:none}
@@ -261,19 +268,50 @@ body{
Поведенческий аудит безопасности
Система учёта и аналитики ПАБ
-
@@ -481,13 +519,19 @@ const CATEGORIES = [
}
];
-// ========== USERS ==========
-const USERS = {
+// ========== USERS (predefined + registered) ==========
+const PREDEFINED_USERS = {
admin:{pass:'admin',name:'Администратор',role:'Руководитель'},
auditor:{pass:'auditor',name:'Петров П.П.',role:'Аудитор'},
ivanov:{pass:'1234',name:'Иванов И.И.',role:'Бригадир'}
};
+function getRegisteredUsers(){
+ try{return JSON.parse(localStorage.getItem('safetyAuditRegisteredUsers')||'{}')}catch(e){return{}}
+}
+function saveRegisteredUsers(data){localStorage.setItem('safetyAuditRegisteredUsers',JSON.stringify(data))}
+function getAllUsers(){return{...getRegisteredUsers(),...PREDEFINED_USERS}}
+
// ========== STATE ==========
let currentUser=null,currentPanel='newAudit',editId=null,charts={};
@@ -503,6 +547,9 @@ function init(){
}
document.getElementById('loginUser').addEventListener('keydown',function(e){if(e.key==='Enter')doLogin();});
document.getElementById('loginPass').addEventListener('keydown',function(e){if(e.key==='Enter')doLogin();});
+ document.getElementById('regLogin').addEventListener('keydown',function(e){if(e.key==='Enter')doRegister();});
+ document.getElementById('regPass').addEventListener('keydown',function(e){if(e.key==='Enter')doRegister();});
+ document.getElementById('regName').addEventListener('keydown',function(e){if(e.key==='Enter')doRegister();});
}
init();
@@ -759,14 +806,49 @@ function resetAuditForm(){
function getAudits(){try{return JSON.parse(localStorage.getItem('safetyAudits')||'[]')}catch(e){return[]}}
function saveAudits(data){localStorage.setItem('safetyAudits',JSON.stringify(data))}
-// ========== LOGIN ==========
+// ========== LOGIN / REGISTER ==========
+function switchLoginTab(tab){
+ document.querySelectorAll('.login-tab').forEach(t=>t.classList.toggle('active',t.textContent===(tab==='login'?'Вход':'Регистрация')));
+ document.getElementById('formLogin').classList.toggle('active',tab==='login');
+ document.getElementById('formRegister').classList.toggle('active',tab==='register');
+ document.getElementById('loginError').style.display='none';
+ document.getElementById('regError').style.display='none';
+ document.getElementById('regSuccess').style.display='none';
+}
+
+function doRegister(){
+ const login=document.getElementById('regLogin').value.trim().toLowerCase();
+ const pass=document.getElementById('regPass').value.trim();
+ const name=document.getElementById('regName').value.trim();
+ const role=document.getElementById('regRole').value;
+ const err=document.getElementById('regError');
+ const ok=document.getElementById('regSuccess');
+ ok.style.display='none';
+ if(!login||login.length<2){err.textContent='Логин должен быть минимум 2 символа';err.style.display='block';return;}
+ if(!pass||pass.length<3){err.textContent='Пароль должен быть минимум 3 символа';err.style.display='block';return;}
+ if(!name){err.textContent='Укажите ФИО';err.style.display='block';return;}
+ const allUsers=getAllUsers();
+ if(allUsers[login]){err.textContent='Такой логин уже занят';err.style.display='block';return;}
+ err.style.display='none';
+ const users=getRegisteredUsers();
+ users[login]={pass:pass,name:name,role:role};
+ saveRegisteredUsers(users);
+ ok.style.display='block';
+ document.getElementById('regLogin').value='';
+ document.getElementById('regPass').value='';
+ document.getElementById('regName').value='';
+ document.getElementById('loginUser').value=login;
+ setTimeout(()=>{switchLoginTab('login');ok.style.display='none';},2000);
+}
+
function doLogin(){
const u=document.getElementById('loginUser').value.trim().toLowerCase();
const p=document.getElementById('loginPass').value.trim();
const err=document.getElementById('loginError');
- if(!USERS[u]||USERS[u].pass!==p){err.style.display='block';return;}
+ const allUsers=getAllUsers();
+ if(!allUsers[u]||allUsers[u].pass!==p){err.style.display='block';return;}
err.style.display='none';
- currentUser={login:u,...USERS[u]};
+ currentUser={login:u,...allUsers[u]};
localStorage.setItem('safetyAuditUser',JSON.stringify(currentUser));
document.getElementById('pabObserver').value=currentUser.name;
showApp();
@@ -776,6 +858,8 @@ function doLogout(){
document.getElementById('loginScreen').style.display='flex';
document.getElementById('appScreen').style.display='none';
document.getElementById('loginUser').value='';document.getElementById('loginPass').value='';
+ document.getElementById('regLogin').value='';document.getElementById('regPass').value='';document.getElementById('regName').value='';
+ document.getElementById('loginError').style.display='none';document.getElementById('regError').style.display='none';document.getElementById('regSuccess').style.display='none';
}
function showApp(){
document.getElementById('loginScreen').style.display='none';