// Settings — persisted to the backend (/api/settings). function SettingsPage() { const [section, setSection] = React.useState("Общие"); const [s, setS] = React.useState(null); const [saved, setSaved] = React.useState(false); const sections = ["Общие", "Уведомления", "ИИ-ассистент", "Команда", "Биллинг", "Безопасность"]; React.useEffect(() => { if (window.API && window.API.getSettings) { window.API.getSettings().then(setS).catch(() => setS({})); } else { setS({}); } }, []); const save = (patch) => { setS(prev => ({ ...(prev || {}), ...patch })); if (window.API) { window.API.putSettings(patch).then(() => { setSaved(true); setTimeout(() => setSaved(false), 1500); }).catch(() => {}); } }; const toggle = (key) => save({ [key]: !(s && s[key]) }); if (!s) { return (

Настройки

загрузка…

); } return (

Настройки

Рабочее пространство · {s.companyName || "—"}{saved ? " · ✓ сохранено" : ""}

{sections.map(x => (
setSection(x)}>{x}
))}
toggle("emailNotif")} /> toggle("aiSummary")} /> toggle("autoTag")} /> toggle("overdueAlert")} /> toggle("twoFa")} />
Активные сессии
Управление устройствами
Журнал доступа
История действий
); } function CompanyProfileCard({ s, onSave }) { const [name, setName] = React.useState(s.companyName || ""); const [inn, setInn] = React.useState(s.inn || ""); const [plan, setPlan] = React.useState(s.plan || ""); const [created, setCreated] = React.useState(s.created || ""); const dirty = name !== (s.companyName || "") || inn !== (s.inn || "") || plan !== (s.plan || "") || created !== (s.created || ""); return ( onSave({ companyName: name, inn, plan, created })}> Сохранить : null} >
setName(e.target.value)} />
setInn(e.target.value)} />
setPlan(e.target.value)} />
setCreated(e.target.value)} />
); } function SettingToggle({ title, sub, on, onChange }) { return (
{title}
{sub}
); } // ---- Users & access (admin) ---- function UsersCard() { const [users, setUsers] = React.useState([]); const [open, setOpen] = React.useState(false); const depts = (typeof DEPARTMENTS !== "undefined") ? DEPARTMENTS : []; const load = () => { if (window.API && window.API.listUsers) window.API.listUsers().then(setUsers).catch(() => {}); }; React.useEffect(() => { load(); }, []); const roleLabel = { admin: "Администратор", controller: "Отдел контроля", executor: "Исполнитель" }; return ( setOpen(true)}> Добавить} bodyStyle={{ padding: 0 }} > {users.map(u => (
{u.name || u.login} · {u.login}
{roleLabel[u.role] || u.role}{u.person ? ` · ${u.person}` : ""}
{u.role}
))} {users.length === 0 &&
Загрузка…
} {open && setOpen(false)} onAdded={() => { setOpen(false); load(); }} />}
); } function AddUserModal({ onClose, onAdded }) { const [login, setLogin] = React.useState(""); const [name, setName] = React.useState(""); const [role, setRole] = React.useState("executor"); const [person, setPerson] = React.useState(""); const [password, setPassword] = React.useState(""); const [busy, setBusy] = React.useState(false); const [error, setError] = React.useState(""); const submit = async () => { if (!login.trim() || password.length < 6) { setError("Логин и пароль (≥ 6 символов) обязательны"); return; } setBusy(true); setError(""); try { await window.API.createUser({ login: login.trim(), name: name.trim(), role, person: person.trim(), password }); onAdded(); } catch (e) { setError(String((e && e.message) || e)); } finally { setBusy(false); } }; return (
e.stopPropagation()}>

Новый пользователь

Учётная запись с ролью доступа

setLogin(e.target.value)} />
setPassword(e.target.value)} />
setName(e.target.value)} />
setPerson(e.target.value)} />
«Связать с ФИО» — для исполнителя: он видит только поручения, где ответственный = это ФИО (точно как в реестре).
{error &&
{error}
}
); } window.SettingsPage = SettingsPage;