/* global React, Card, Button, Input, Ic, VS */
// Zakładka "Użytkownicy" — admin-only.
// Zarządzanie użytkownikami logującymi się do aplikacji (tabela {S}.users).
// Pola: login (username), Imię i nazwisko (display_name), email, rola, hasło.
function UsersScreen() {
const role = VS.getRole();
const isAdmin = role === 'admin';
if (!isAdmin) {
return (
Użytkownicy
Dostęp tylko dla administratora.
);
}
const [list, setList] = React.useState(null);
const [err, setErr] = React.useState('');
const [msg, setMsg] = React.useState('');
const [showAdd, setShowAdd] = React.useState(false);
const [nLogin, setNLogin] = React.useState('');
const [nName, setNName] = React.useState('');
const [nEmail, setNEmail] = React.useState('');
const [nPass, setNPass] = React.useState('');
const [nRole, setNRole] = React.useState('pracownik');
const [adding, setAdding] = React.useState(false);
const load = React.useCallback(() => {
VS.adminUsers()
.then(r => setList(r || []))
.catch(e => setErr(e.message));
}, []);
React.useEffect(() => { load(); }, [load]);
function flash(text) { setMsg(text); setTimeout(() => setMsg(''), 2200); }
async function addUser() {
if (!nLogin.trim() || !nPass.trim()) { flash('Login i hasło wymagane'); return; }
setAdding(true);
try {
await VS.adminAddUser({
username: nLogin.trim(),
password: nPass,
display_name: nName.trim(),
email: nEmail.trim(),
role: nRole,
});
setNLogin(''); setNName(''); setNEmail(''); setNPass(''); setNRole('pracownik');
setShowAdd(false);
load();
flash('Dodano użytkownika.');
} catch (e) {
flash('Błąd: ' + e.message);
} finally { setAdding(false); }
}
async function removeUser(u) {
if (!confirm(`Usunąć użytkownika "${u.username}"?`)) return;
try { await VS.adminDeleteUser(u.id); load(); flash('Usunięto.'); }
catch (e) { flash('Błąd: ' + e.message); }
}
return (
Administracja
Użytkownicy
Lista osób logujących się do aplikacji. Imię i nazwisko pojawia się w dropdownach Operator / Zatwierdził.
{list ? `${list.length} użytkowników` : ''}
} onClick={() => setShowAdd(s => !s)}>
{showAdd ? 'Ukryj' : 'Nowy użytkownik'}
{showAdd && (
Dodaj użytkownika
Rola
setNRole(e.target.value)} style={inputStyle}>
pracownik
admin
} onClick={addUser} disabled={adding}>
{adding ? 'Dodaję…' : 'Zapisz'}
setShowAdd(false)}>Anuluj
{msg && {msg} }
)}
{err && (
{err}
)}
{!err && !list &&
Ładowanie…
}
{!err && list && list.length === 0 && (
Brak użytkowników.
)}
{!err && list && list.length > 0 && (
Login
Imię i nazwisko
E-mail
Rola
Akcje
{list.map((u, i) => (
removeUser(u)} />
))}
)}
{!showAdd && msg && (
{msg}
)}
);
}
function UserRow({ user, last, onChange, onRemove }) {
const [editing, setEditing] = React.useState(false);
const [name, setName] = React.useState(user.display_name || '');
const [email, setEmail] = React.useState(user.email || '');
const [role, setRole] = React.useState(user.role || 'pracownik');
const [pass, setPass] = React.useState('');
const [busy, setBusy] = React.useState(false);
const [msg, setMsg] = React.useState('');
React.useEffect(() => {
setName(user.display_name || '');
setEmail(user.email || '');
setRole(user.role || 'pracownik');
setPass('');
}, [user.id, user.display_name, user.email, user.role]);
async function save() {
setBusy(true); setMsg('');
try {
const data = { display_name: name, email, role };
if (pass.trim()) data.password = pass;
await VS.adminUpdateUser(user.id, data);
setEditing(false);
setPass('');
onChange && onChange();
} catch (e) { setMsg('Błąd: ' + e.message); }
finally { setBusy(false); }
}
if (!editing) {
return (
{user.username}
{user.display_name || — }
{user.email || — }
{user.role}
} onClick={() => setEditing(true)}>Edytuj
} onClick={onRemove}>Usuń
);
}
return (
);
}
const inputStyle = {
width: '100%', height: 28, padding: '0 8px',
background: 'var(--surface)', border: '1px solid var(--border-strong)',
borderRadius: 'var(--r-sm)', fontSize: 12, color: 'var(--fg)', fontFamily: 'inherit', outline: 'none',
};
Object.assign(window, { UsersScreen });