diff --git a/services/web-ui/public/screens-admin.jsx b/services/web-ui/public/screens-admin.jsx
index 522fa2d..64c5a61 100644
--- a/services/web-ui/public/screens-admin.jsx
+++ b/services/web-ui/public/screens-admin.jsx
@@ -124,6 +124,7 @@ function Users() {
const [editingUser, setEditingUser] = React.useState(null);
const [resetUser, setResetUser] = React.useState(null);
const [menuFor, setMenuFor] = React.useState(null); // row id whose menu is open
+ const [confirm, confirmModal] = window.useConfirm();
const refreshUsers = React.useCallback(() => {
window.ZAMPP_API.fetch('/users')
@@ -169,9 +170,9 @@ function Users() {
const onCreated = () => { refreshUsers(); setShowInvite(false); };
- const deleteUser = (u) => {
+ const deleteUser = async (u) => {
setMenuFor(null);
- if (!confirm(`Delete user "${u.name}" (@${u.username})?\nThis cannot be undone.`)) return;
+ if (!(await confirm({ title: 'Delete user?', message: `Delete user "${u.name}" (@${u.username})?\nThis cannot be undone.` }))) return;
window.ZAMPP_API.fetch('/users/' + u.id, { method: 'DELETE' })
.then(refreshUsers)
.catch(e => alert('Delete failed: ' + e.message));
@@ -188,6 +189,7 @@ function Users() {
return (
+ {confirmModal}
Users & Groups
@@ -296,6 +298,7 @@ function Users() {
function PoliciesPanel({ users, onChange }) {
const [expandedId, setExpandedId] = React.useState(null);
const [err, setErr] = React.useState(null);
+ const [confirm, confirmModal] = window.useConfirm();
const changeRole = (u, newRole) => {
if (u.role === newRole) return;
@@ -307,8 +310,8 @@ function PoliciesPanel({ users, onChange }) {
// Reset 2FA uses a raw fetch because ZAMPP_API.fetch throws on the 204 (no JSON
// body). Mirrors the disable() pattern in TotpSection.
- const resetTotp = (u) => {
- if (!confirm(`Reset two-factor for "${u.name}" (@${u.username})?\nThey will be able to sign in without a code until they re-enrol.`)) return;
+ const resetTotp = async (u) => {
+ if (!(await confirm({ title: 'Reset two-factor?', message: `Reset two-factor for "${u.name}" (@${u.username})?\nThey will be able to sign in without a code until they re-enrol.`, confirmLabel: 'Reset 2FA' }))) return;
setErr(null);
fetch('/api/v1/users/' + u.id + '/totp/disable', {
method: 'POST',
@@ -324,6 +327,7 @@ function PoliciesPanel({ users, onChange }) {
return (
+ {confirmModal}
{/* Access-model explainer (kept from the old static tab, condensed) */}