// 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}
>
);
}
function SettingToggle({ title, sub, on, onChange }) {
return (
);
}
// ---- 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()}>
Новый пользователь
Учётная запись с ролью доступа
setName(e.target.value)} />
«Связать с ФИО» — для исполнителя: он видит только поручения, где ответственный = это ФИО (точно как в реестре).
{error &&
{error}
}
);
}
window.SettingsPage = SettingsPage;