@burdenoff/microfe-auth 2026.830.1 → 2026.830.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/auth/AuthRoot.js +43 -41
  2. package/dist/auth/AuthRoot.js.map +1 -1
  3. package/dist/auth/components/AuthLayout.js +65 -67
  4. package/dist/auth/components/AuthLayout.js.map +1 -1
  5. package/dist/auth/components/CaptchaV2.js +21 -24
  6. package/dist/auth/components/CaptchaV2.js.map +1 -1
  7. package/dist/auth/components/ConfirmActionDialog.js +33 -32
  8. package/dist/auth/components/ConfirmActionDialog.js.map +1 -1
  9. package/dist/auth/components/profile/UserProfileMenu.js +44 -46
  10. package/dist/auth/components/profile/UserProfileMenu.js.map +1 -1
  11. package/dist/auth/components/workspace/WorkspaceSelector.js +62 -68
  12. package/dist/auth/components/workspace/WorkspaceSelector.js.map +1 -1
  13. package/dist/auth/pages/AuditLogPage.js +65 -68
  14. package/dist/auth/pages/AuditLogPage.js.map +1 -1
  15. package/dist/auth/pages/EmailVerifyPage.js +51 -54
  16. package/dist/auth/pages/EmailVerifyPage.js.map +1 -1
  17. package/dist/auth/pages/LoginPage.js +223 -225
  18. package/dist/auth/pages/LoginPage.js.map +1 -1
  19. package/dist/auth/pages/MagicLinkPage.js +67 -69
  20. package/dist/auth/pages/MagicLinkPage.js.map +1 -1
  21. package/dist/auth/pages/MfaSetupPage.js +85 -88
  22. package/dist/auth/pages/MfaSetupPage.js.map +1 -1
  23. package/dist/auth/pages/MfaVerifyPage.js +60 -63
  24. package/dist/auth/pages/MfaVerifyPage.js.map +1 -1
  25. package/dist/auth/pages/OAuthCallbackPage.js +37 -40
  26. package/dist/auth/pages/OAuthCallbackPage.js.map +1 -1
  27. package/dist/auth/pages/PasswordResetPage.js +102 -105
  28. package/dist/auth/pages/PasswordResetPage.js.map +1 -1
  29. package/dist/auth/pages/ReactivatePage.js +54 -57
  30. package/dist/auth/pages/ReactivatePage.js.map +1 -1
  31. package/dist/auth/pages/RegisterPage.js +171 -174
  32. package/dist/auth/pages/RegisterPage.js.map +1 -1
  33. package/dist/auth/pages/SSOClearPage.js +21 -20
  34. package/dist/auth/pages/SSOClearPage.js.map +1 -1
  35. package/dist/auth/pages/SSODepositPage.js +27 -26
  36. package/dist/auth/pages/SSODepositPage.js.map +1 -1
  37. package/dist/auth/pages/SSORelayCallbackPage.js +19 -18
  38. package/dist/auth/pages/SSORelayCallbackPage.js.map +1 -1
  39. package/dist/auth/pages/SecurityPage.js +247 -250
  40. package/dist/auth/pages/SecurityPage.js.map +1 -1
  41. package/dist/auth/pages/SessionsPage.js +95 -98
  42. package/dist/auth/pages/SessionsPage.js.map +1 -1
  43. package/dist/auth/pages/SsoCallbackPage.js +53 -56
  44. package/dist/auth/pages/SsoCallbackPage.js.map +1 -1
  45. package/dist/auth/pages/SsoConfigPage.js +296 -299
  46. package/dist/auth/pages/SsoConfigPage.js.map +1 -1
  47. package/dist/auth/pages/SsoLoginPage.js +65 -68
  48. package/dist/auth/pages/SsoLoginPage.js.map +1 -1
  49. package/dist/auth/pages/UserDetailsPage.js +124 -127
  50. package/dist/auth/pages/UserDetailsPage.js.map +1 -1
  51. package/dist/auth/pages/UserProfilePage.js +171 -174
  52. package/dist/auth/pages/UserProfilePage.js.map +1 -1
  53. package/dist/auth/pages/UsersPage.js +322 -325
  54. package/dist/auth/pages/UsersPage.js.map +1 -1
  55. package/dist/index.d.ts +1 -0
  56. package/dist/index.js +2 -1
  57. package/dist/shared/hooks/index.d.ts +1 -6
  58. package/dist/shared/hooks/useTr.d.ts +16 -0
  59. package/dist/shared/hooks/useTr.js +14 -0
  60. package/dist/shared/hooks/useTr.js.map +1 -0
  61. package/dist/translations/en.d.ts +806 -248
  62. package/dist/translations/en.js +870 -0
  63. package/dist/translations/en.js.map +1 -0
  64. package/package.json +1 -1
@@ -1,43 +1,40 @@
1
1
  import { useAuthStore as e } from "../store/authStore.js";
2
- import { AlertIcon as t, SpinnerIcon as n } from "../components/AuthIcons.js";
3
- import { useMfaOperations as r } from "../hooks/useMfaOperations.js";
4
- import { ConfirmActionDialog as i } from "../components/ConfirmActionDialog.js";
5
- import { QRCodeSVG as a } from "../../node_modules/qrcode.react/lib/esm/index.js";
6
- import { nativeCopyText as o, nativeImpact as s, nativeNotify as c } from "../../utils/nativeBridge.js";
7
- import { useState as l } from "react";
8
- import { useNavigate as u } from "react-router";
9
- import { useI18n as d } from "@burdenoff/fe-libs/shared/providers/shell";
2
+ import { useTr as t } from "../../shared/hooks/useTr.js";
3
+ import { AlertIcon as n, SpinnerIcon as r } from "../components/AuthIcons.js";
4
+ import { useMfaOperations as i } from "../hooks/useMfaOperations.js";
5
+ import { ConfirmActionDialog as a } from "../components/ConfirmActionDialog.js";
6
+ import { QRCodeSVG as o } from "../../node_modules/qrcode.react/lib/esm/index.js";
7
+ import { nativeCopyText as s, nativeImpact as c, nativeNotify as l } from "../../utils/nativeBridge.js";
8
+ import { useState as u } from "react";
9
+ import { useNavigate as d } from "react-router";
10
10
  import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
11
11
  import { Button as h } from "@burdenoff/fe-libs/button";
12
12
  import { NextSteps as g, PagePurpose as _ } from "@burdenoff/fe-libs/ui";
13
13
  //#region src/auth/pages/MfaSetupPage.tsx
14
14
  function v() {
15
- let { t: v } = d(), y = (e, t) => {
16
- let n = v(e);
17
- return n === e ? t : n;
18
- }, b = u(), { setupMFA: x, enableMFA: S, disableMFA: C, isLoading: w } = r(), T = e((e) => e.user), E = e((e) => e.isAuthenticated), [D, O] = l(null), [k, A] = l(""), [j, M] = l(null), [N, P] = l(null), [F, I] = l(!1), [L, R] = l(!1), z = async (e) => {
15
+ let v = t(), y = d(), { setupMFA: b, enableMFA: x, disableMFA: S, isLoading: C } = i(), w = e((e) => e.user), T = e((e) => e.isAuthenticated), [E, D] = u(null), [O, k] = u(""), [A, j] = u(null), [M, N] = u(null), [P, F] = u(!1), [I, L] = u(!1), R = async (e) => {
19
16
  try {
20
- M(null), P(null), O(await x(e));
17
+ j(null), N(null), D(await b(e));
21
18
  } catch (e) {
22
- console.error("Failed to setup MFA:", e), M(e instanceof Error ? e.message : "Failed to setup MFA. Please try again.");
19
+ console.error("Failed to setup MFA:", e), j(e instanceof Error ? e.message : "Failed to setup MFA. Please try again.");
23
20
  }
24
21
  };
25
- return E ? /* @__PURE__ */ m("div", {
22
+ return T ? /* @__PURE__ */ m("div", {
26
23
  className: "max-w-2xl mx-auto p-6",
27
24
  children: [
28
- /* @__PURE__ */ p(i, {
29
- open: L,
30
- onOpenChange: R,
31
- title: y("auth.mfaSetup.disableTitle", "Disable two-factor authentication?"),
32
- description: y("auth.mfaSetup.disableDesc", "Your account will become less secure and future sign-ins will only require your password until MFA is re-enabled."),
33
- confirmText: y("auth.mfaSetup.disableConfirm", "Disable MFA"),
25
+ /* @__PURE__ */ p(a, {
26
+ open: I,
27
+ onOpenChange: L,
28
+ title: v("auth.mfaSetup.disableTitle", "Disable two-factor authentication?"),
29
+ description: v("auth.mfaSetup.disableDesc", "Your account will become less secure and future sign-ins will only require your password until MFA is re-enabled."),
30
+ confirmText: v("auth.mfaSetup.disableConfirm", "Disable MFA"),
34
31
  variant: "warning",
35
- isPending: w,
32
+ isPending: C,
36
33
  onConfirm: async () => {
37
34
  try {
38
- M(null), P(null), await C(), P(y("auth.mfaSetup.disableSuccess", "Two-factor authentication has been disabled.")), R(!1);
35
+ j(null), N(null), await S(), N(v("auth.mfaSetup.disableSuccess", "Two-factor authentication has been disabled.")), L(!1);
39
36
  } catch (e) {
40
- console.error("Failed to disable MFA:", e), M(e instanceof Error ? e.message : "Failed to disable MFA. Please try again.");
37
+ console.error("Failed to disable MFA:", e), j(e instanceof Error ? e.message : "Failed to disable MFA. Please try again.");
41
38
  }
42
39
  }
43
40
  }),
@@ -46,19 +43,19 @@ function v() {
46
43
  children: [
47
44
  /* @__PURE__ */ p("h1", {
48
45
  className: "text-3xl font-semibold text-[var(--color-text-primary)]",
49
- children: y("auth.mfaSetup.title", "Two-Factor Authentication")
46
+ children: v("auth.mfaSetup.title", "Two-Factor Authentication")
50
47
  }),
51
48
  /* @__PURE__ */ p("p", {
52
49
  className: "text-[var(--color-text-secondary)] mt-2",
53
- children: y("auth.mfaSetup.subtitle", "Add an extra layer of security to your account")
50
+ children: v("auth.mfaSetup.subtitle", "Add an extra layer of security to your account")
54
51
  }),
55
52
  /* @__PURE__ */ p(_, {
56
53
  className: "mt-3",
57
- children: y("auth.mfaSetup.purpose", "Two-factor authentication (2FA) asks for a one-time code from an authenticator app at sign-in, so your account stays safe even if your password leaks. Set it up here and keep your backup codes somewhere safe.")
54
+ children: v("auth.mfaSetup.purpose", "Two-factor authentication (2FA) asks for a one-time code from an authenticator app at sign-in, so your account stays safe even if your password leaks. Set it up here and keep your backup codes somewhere safe.")
58
55
  })
59
56
  ]
60
57
  }),
61
- N && /* @__PURE__ */ p("div", {
58
+ M && /* @__PURE__ */ p("div", {
62
59
  className: "mb-6 p-4 rounded-xl bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)]",
63
60
  children: /* @__PURE__ */ m("div", {
64
61
  className: "flex items-center gap-3",
@@ -75,26 +72,26 @@ function v() {
75
72
  })
76
73
  }), /* @__PURE__ */ p("p", {
77
74
  className: "text-[var(--color-status-success-text)]",
78
- children: N
75
+ children: M
79
76
  })]
80
77
  })
81
78
  }),
82
- j && /* @__PURE__ */ m("div", {
79
+ A && /* @__PURE__ */ m("div", {
83
80
  className: "mb-6 flex items-start gap-3 p-4 rounded-xl bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)]",
84
- children: [/* @__PURE__ */ p(t, { className: "size-5 text-[var(--color-status-error-text)] flex-shrink-0 mt-0.5" }), /* @__PURE__ */ m("div", {
81
+ children: [/* @__PURE__ */ p(n, { className: "size-5 text-[var(--color-status-error-text)] flex-shrink-0 mt-0.5" }), /* @__PURE__ */ m("div", {
85
82
  className: "flex-1",
86
83
  children: [/* @__PURE__ */ p("p", {
87
84
  className: "text-sm text-[var(--color-status-error-text)]",
88
- children: j
85
+ children: A
89
86
  }), /* @__PURE__ */ p("button", {
90
87
  type: "button",
91
- onClick: () => M(null),
88
+ onClick: () => j(null),
92
89
  className: "mt-2 text-sm text-[var(--color-status-error-text)] hover:underline transition-colors duration-200",
93
- children: y("auth.mfaSetup.dismiss", "Dismiss")
90
+ children: v("auth.mfaSetup.dismiss", "Dismiss")
94
91
  })]
95
92
  })]
96
93
  }),
97
- D ? /* @__PURE__ */ m("div", {
94
+ E ? /* @__PURE__ */ m("div", {
98
95
  className: "p-6 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-sm",
99
96
  children: [/* @__PURE__ */ m("div", {
100
97
  className: "flex items-center gap-3 mb-6",
@@ -114,20 +111,20 @@ function v() {
114
111
  })
115
112
  }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("h2", {
116
113
  className: "text-xl font-semibold text-[var(--color-text-primary)]",
117
- children: y("auth.mfaSetup.setupAuthApp", "Setup Authenticator App")
114
+ children: v("auth.mfaSetup.setupAuthApp", "Setup Authenticator App")
118
115
  }), /* @__PURE__ */ p("p", {
119
116
  className: "text-sm text-[var(--color-text-secondary)]",
120
- children: y("auth.mfaSetup.scanQr", "Scan the QR code with your authenticator app")
117
+ children: v("auth.mfaSetup.scanQr", "Scan the QR code with your authenticator app")
121
118
  })] })]
122
119
  }), /* @__PURE__ */ m("div", {
123
120
  className: "space-y-6",
124
121
  children: [
125
- D.qrCode && /* @__PURE__ */ p("div", {
122
+ E.qrCode && /* @__PURE__ */ p("div", {
126
123
  className: "flex justify-center",
127
124
  children: /* @__PURE__ */ p("div", {
128
125
  className: "p-4 bg-[var(--color-bg-surface)] rounded-xl border border-[var(--color-border-default)]",
129
- children: /* @__PURE__ */ p(a, {
130
- value: D.qrCode,
126
+ children: /* @__PURE__ */ p(o, {
127
+ value: E.qrCode,
131
128
  size: 192,
132
129
  level: "M",
133
130
  includeMargin: !1,
@@ -135,14 +132,14 @@ function v() {
135
132
  })
136
133
  })
137
134
  }),
138
- D.secret && /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
135
+ E.secret && /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
139
136
  className: "text-sm text-[var(--color-text-secondary)] mb-2",
140
- children: y("auth.mfaSetup.cantScan", "Can't scan the QR code? Enter this key manually:")
137
+ children: v("auth.mfaSetup.cantScan", "Can't scan the QR code? Enter this key manually:")
141
138
  }), /* @__PURE__ */ p("code", {
142
139
  className: "block p-3 rounded-lg bg-[var(--color-bg-muted)] text-[var(--color-text-primary)] font-mono text-sm break-all select-all",
143
- children: D.secret
140
+ children: E.secret
144
141
  })] }),
145
- D.backupCodes && D.backupCodes.length > 0 && /* @__PURE__ */ m("div", {
142
+ E.backupCodes && E.backupCodes.length > 0 && /* @__PURE__ */ m("div", {
146
143
  className: "p-4 rounded-xl bg-[var(--color-status-warning-bg-subtle)] border border-[var(--color-status-warning-border)]",
147
144
  children: [
148
145
  /* @__PURE__ */ m("div", {
@@ -160,15 +157,15 @@ function v() {
160
157
  })
161
158
  }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("h3", {
162
159
  className: "font-medium text-[var(--color-status-warning-text)]",
163
- children: y("auth.mfaSetup.saveBackupCodes", "Save your backup codes")
160
+ children: v("auth.mfaSetup.saveBackupCodes", "Save your backup codes")
164
161
  }), /* @__PURE__ */ p("p", {
165
162
  className: "text-sm text-[var(--color-status-warning-text)]",
166
- children: y("auth.mfaSetup.storeCodesSafely", "Store these codes safely. You can use them to access your account if you lose your authenticator device.")
163
+ children: v("auth.mfaSetup.storeCodesSafely", "Store these codes safely. You can use them to access your account if you lose your authenticator device.")
167
164
  })] })]
168
165
  }),
169
166
  /* @__PURE__ */ p("div", {
170
167
  className: "p-3 rounded-lg bg-[var(--color-bg-surface)] grid grid-cols-2 gap-2 mb-3",
171
- children: D.backupCodes.map((e, t) => /* @__PURE__ */ m("code", {
168
+ children: E.backupCodes.map((e, t) => /* @__PURE__ */ m("code", {
172
169
  className: "text-sm text-[var(--color-text-primary)] font-mono",
173
170
  children: [
174
171
  t + 1,
@@ -180,26 +177,26 @@ function v() {
180
177
  /* @__PURE__ */ p("button", {
181
178
  type: "button",
182
179
  onClick: async () => {
183
- D?.backupCodes && (s("light"), await o(D.backupCodes.join("\n")) ? (I(!0), c("success"), setTimeout(() => I(!1), 2e3)) : c("error"));
180
+ E?.backupCodes && (c("light"), await s(E.backupCodes.join("\n")) ? (F(!0), l("success"), setTimeout(() => F(!1), 2e3)) : l("error"));
184
181
  },
185
182
  className: "text-sm font-medium text-[var(--color-status-warning-text)] hover:underline transition-colors duration-200",
186
- children: F ? y("auth.mfaSetup.copied", "Copied!") : y("auth.mfaSetup.copyBackupCodes", "Copy backup codes")
183
+ children: P ? v("auth.mfaSetup.copied", "Copied!") : v("auth.mfaSetup.copyBackupCodes", "Copy backup codes")
187
184
  })
188
185
  ]
189
186
  }),
190
187
  /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("label", {
191
188
  htmlFor: "mfa-verification-code",
192
189
  className: "block text-sm font-medium text-[var(--color-text-primary)] mb-2",
193
- children: y("auth.mfaSetup.enterCode", "Enter the 6-digit code from your app")
190
+ children: v("auth.mfaSetup.enterCode", "Enter the 6-digit code from your app")
194
191
  }), /* @__PURE__ */ p("input", {
195
192
  id: "mfa-verification-code",
196
193
  type: "text",
197
194
  inputMode: "numeric",
198
195
  maxLength: 6,
199
- value: k,
200
- onChange: (e) => A(e.target.value.replace(/\D/g, "")),
201
- placeholder: y("auth.mfa.verificationCodePlaceholder", "000000"),
202
- "aria-label": y("auth.mfaSetup.enterCode", "Enter the 6-digit code from your app"),
196
+ value: O,
197
+ onChange: (e) => k(e.target.value.replace(/\D/g, "")),
198
+ placeholder: v("auth.mfa.verificationCodePlaceholder", "000000"),
199
+ "aria-label": v("auth.mfaSetup.enterCode", "Enter the 6-digit code from your app"),
203
200
  "aria-required": "true",
204
201
  autoComplete: "one-time-code",
205
202
  className: "block w-full px-4 py-3 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] text-center text-2xl tracking-widest font-mono focus:outline-none focus:ring-2 focus:ring-action-primary-bg/20 focus:border-action-primary-bg transition-all duration-300"
@@ -209,35 +206,35 @@ function v() {
209
206
  children: [/* @__PURE__ */ p("button", {
210
207
  type: "button",
211
208
  onClick: () => {
212
- O(null), A(""), M(null);
209
+ D(null), k(""), j(null);
213
210
  },
214
211
  className: "flex-1 py-3 px-4 rounded-xl border border-[var(--color-border-default)] text-[var(--color-text-secondary)] font-medium hover:bg-[var(--color-bg-muted)] transition-colors duration-200",
215
- children: y("auth.mfaSetup.cancel", "Cancel")
212
+ children: v("auth.mfaSetup.cancel", "Cancel")
216
213
  }), /* @__PURE__ */ p(h, {
217
214
  type: "button",
218
215
  onClick: async () => {
219
- if (k.length !== 6) {
220
- M(y("auth.mfaSetup.enter6Digit", "Please enter a 6-digit code"));
216
+ if (O.length !== 6) {
217
+ j(v("auth.mfaSetup.enter6Digit", "Please enter a 6-digit code"));
221
218
  return;
222
219
  }
223
220
  try {
224
- M(null), await S(k) && (O(null), A(""), P(y("auth.mfaSetup.enableSuccess", "Two-factor authentication has been enabled successfully!")));
221
+ j(null), await x(O) && (D(null), k(""), N(v("auth.mfaSetup.enableSuccess", "Two-factor authentication has been enabled successfully!")));
225
222
  } catch (e) {
226
- console.error("Failed to verify MFA code:", e), M(e instanceof Error ? e.message : "Invalid verification code. Please try again.");
223
+ console.error("Failed to verify MFA code:", e), j(e instanceof Error ? e.message : "Invalid verification code. Please try again.");
227
224
  }
228
225
  },
229
- disabled: w || k.length !== 6,
226
+ disabled: C || O.length !== 6,
230
227
  variant: "default",
231
228
  size: "lg",
232
229
  className: "flex-1 font-semibold",
233
- children: w ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(n, { className: "size-5 animate-spin" }), /* @__PURE__ */ p("span", { children: y("auth.mfa.verifying", "Verifying...") })] }) : y("auth.mfaSetup.enable2fa", "Enable 2FA")
230
+ children: C ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(r, { className: "size-5 animate-spin" }), /* @__PURE__ */ p("span", { children: v("auth.mfa.verifying", "Verifying...") })] }) : v("auth.mfaSetup.enable2fa", "Enable 2FA")
234
231
  })]
235
232
  })
236
233
  ]
237
234
  })]
238
235
  }) : /* @__PURE__ */ p("div", {
239
236
  className: "p-6 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-sm",
240
- children: T?.mfaEnabled ? /* @__PURE__ */ m(f, { children: [
237
+ children: w?.mfaEnabled ? /* @__PURE__ */ m(f, { children: [
241
238
  /* @__PURE__ */ m("div", {
242
239
  className: "flex items-center gap-4 mb-6",
243
240
  children: [/* @__PURE__ */ p("div", {
@@ -256,25 +253,25 @@ function v() {
256
253
  })
257
254
  }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("h2", {
258
255
  className: "text-xl font-semibold text-[var(--color-text-primary)]",
259
- children: y("auth.mfaSetup.twoFactorOn", "Two-Factor Authentication is On")
256
+ children: v("auth.mfaSetup.twoFactorOn", "Two-Factor Authentication is On")
260
257
  }), /* @__PURE__ */ p("p", {
261
258
  className: "text-[var(--color-text-secondary)]",
262
- children: y("auth.mfaSetup.protected", "Your account is protected with an authenticator app")
259
+ children: v("auth.mfaSetup.protected", "Your account is protected with an authenticator app")
263
260
  })] })]
264
261
  }),
265
262
  /* @__PURE__ */ p("div", {
266
263
  className: "mb-6 p-4 rounded-lg bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)]",
267
264
  children: /* @__PURE__ */ p("p", {
268
265
  className: "text-sm text-[var(--color-status-success-text)]",
269
- children: y("auth.mfaSetup.verificationOnSignIn", "You'll be asked for a verification code from your authenticator app when signing in.")
266
+ children: v("auth.mfaSetup.verificationOnSignIn", "You'll be asked for a verification code from your authenticator app when signing in.")
270
267
  })
271
268
  }),
272
269
  /* @__PURE__ */ p("button", {
273
270
  type: "button",
274
- onClick: () => R(!0),
275
- disabled: w,
271
+ onClick: () => L(!0),
272
+ disabled: C,
276
273
  className: "w-full py-3 px-4 rounded-xl border border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] font-medium bg-[var(--color-bg-surface)] hover:bg-[var(--color-status-error-bg-subtle)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200 flex items-center justify-center gap-2",
277
- children: w ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(n, { className: "size-5 animate-spin" }), /* @__PURE__ */ p("span", { children: y("auth.mfa.disabling", "Disabling...") })] }) : y("auth.mfaSetup.disableTwoFactor", "Disable Two-Factor Authentication")
274
+ children: C ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(r, { className: "size-5 animate-spin" }), /* @__PURE__ */ p("span", { children: v("auth.mfa.disabling", "Disabling...") })] }) : v("auth.mfaSetup.disableTwoFactor", "Disable Two-Factor Authentication")
278
275
  }),
279
276
  /* @__PURE__ */ p(g, {
280
277
  className: "mt-6",
@@ -282,21 +279,21 @@ function v() {
282
279
  steps: [
283
280
  {
284
281
  id: "review-sessions",
285
- label: y("auth.mfaSetup.nextReviewSessions", "Review your active sessions"),
286
- description: y("auth.mfaSetup.nextReviewSessionsDesc", "Sign out any device you no longer recognise."),
287
- onClick: () => b("/auth/sessions")
282
+ label: v("auth.mfaSetup.nextReviewSessions", "Review your active sessions"),
283
+ description: v("auth.mfaSetup.nextReviewSessionsDesc", "Sign out any device you no longer recognise."),
284
+ onClick: () => y("/auth/sessions")
288
285
  },
289
286
  {
290
287
  id: "security-center",
291
- label: y("auth.mfaSetup.nextSecurityCenter", "Visit the Security Center"),
292
- description: y("auth.mfaSetup.nextSecurityCenterDesc", "Check your password and account protection at a glance."),
293
- onClick: () => b("/auth/security")
288
+ label: v("auth.mfaSetup.nextSecurityCenter", "Visit the Security Center"),
289
+ description: v("auth.mfaSetup.nextSecurityCenterDesc", "Check your password and account protection at a glance."),
290
+ onClick: () => y("/auth/security")
294
291
  },
295
292
  {
296
293
  id: "update-profile",
297
- label: y("auth.mfaSetup.nextProfile", "Keep your profile up to date"),
298
- description: y("auth.mfaSetup.nextProfileDesc", "Confirm your recovery email and contact details."),
299
- onClick: () => b("/auth/profile")
294
+ label: v("auth.mfaSetup.nextProfile", "Keep your profile up to date"),
295
+ description: v("auth.mfaSetup.nextProfileDesc", "Confirm your recovery email and contact details."),
296
+ onClick: () => y("/auth/profile")
300
297
  }
301
298
  ]
302
299
  })
@@ -319,17 +316,17 @@ function v() {
319
316
  })
320
317
  }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("h2", {
321
318
  className: "text-xl font-semibold text-[var(--color-text-primary)]",
322
- children: y("auth.mfaSetup.twoFactorOff", "Two-Factor Authentication is Off")
319
+ children: v("auth.mfaSetup.twoFactorOff", "Two-Factor Authentication is Off")
323
320
  }), /* @__PURE__ */ p("p", {
324
321
  className: "text-[var(--color-text-secondary)]",
325
- children: y("auth.mfaSetup.notProtected", "Your account is not protected with 2FA")
322
+ children: v("auth.mfaSetup.notProtected", "Your account is not protected with 2FA")
326
323
  })] })]
327
324
  }),
328
325
  /* @__PURE__ */ m("div", {
329
326
  className: "mb-6 p-4 rounded-lg bg-[var(--color-bg-accent)] border border-[var(--color-border-default)]",
330
327
  children: [/* @__PURE__ */ p("h3", {
331
328
  className: "font-medium text-[var(--color-text-link)] mb-2",
332
- children: y("auth.mfaSetup.whyEnable", "Why enable 2FA?")
329
+ children: v("auth.mfaSetup.whyEnable", "Why enable 2FA?")
333
330
  }), /* @__PURE__ */ m("ul", {
334
331
  className: "text-sm text-[var(--color-text-link)] space-y-1",
335
332
  children: [
@@ -341,12 +338,12 @@ function v() {
341
338
  }),
342
339
  /* @__PURE__ */ p(h, {
343
340
  type: "button",
344
- onClick: () => z("TOTP"),
345
- disabled: w,
341
+ onClick: () => R("TOTP"),
342
+ disabled: C,
346
343
  variant: "default",
347
344
  size: "lg",
348
345
  className: "w-full font-semibold",
349
- children: w ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(n, { className: "size-5 animate-spin" }), /* @__PURE__ */ p("span", { children: y("auth.mfa.settingUp", "Setting up...") })] }) : /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("svg", {
346
+ children: C ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(r, { className: "size-5 animate-spin" }), /* @__PURE__ */ p("span", { children: v("auth.mfa.settingUp", "Setting up...") })] }) : /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("svg", {
350
347
  className: "size-5",
351
348
  fill: "none",
352
349
  viewBox: "0 0 24 24",
@@ -357,7 +354,7 @@ function v() {
357
354
  strokeWidth: 2,
358
355
  d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
359
356
  })
360
- }), /* @__PURE__ */ p("span", { children: y("auth.mfaSetup.enableTwoFactor", "Enable Two-Factor Authentication") })] })
357
+ }), /* @__PURE__ */ p("span", { children: v("auth.mfaSetup.enableTwoFactor", "Enable Two-Factor Authentication") })] })
361
358
  })
362
359
  ] })
363
360
  })
@@ -369,15 +366,15 @@ function v() {
369
366
  children: [
370
367
  /* @__PURE__ */ p("div", {
371
368
  className: "size-16 mx-auto mb-4 rounded-full bg-status-warning-bg-subtle flex items-center justify-center",
372
- children: /* @__PURE__ */ p(t, { className: "size-8 text-status-warning-text" })
369
+ children: /* @__PURE__ */ p(n, { className: "size-8 text-status-warning-text" })
373
370
  }),
374
371
  /* @__PURE__ */ p("h2", {
375
372
  className: "text-xl font-semibold text-text-primary mb-2",
376
- children: y("auth.mfaSetup.authRequired", "Authentication Required")
373
+ children: v("auth.mfaSetup.authRequired", "Authentication Required")
377
374
  }),
378
375
  /* @__PURE__ */ p("p", {
379
376
  className: "text-text-secondary",
380
- children: y("auth.mfaSetup.signInToManage", "Please sign in to manage MFA settings")
377
+ children: v("auth.mfaSetup.signInToManage", "Please sign in to manage MFA settings")
381
378
  })
382
379
  ]
383
380
  })
@@ -1 +1 @@
1
- {"version":3,"file":"MfaSetupPage.js","names":[],"sources":["../../../src/auth/pages/MfaSetupPage.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { useNavigate } from \"react-router\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell\";\nimport { Button } from \"@burdenoff/fe-libs/button\";\nimport { PagePurpose, NextSteps } from \"@burdenoff/fe-libs/ui\";\nimport { QRCodeSVG } from \"qrcode.react\";\nimport { useMfaOperations } from \"../hooks/useMfaOperations\";\nimport { useAuthStore } from \"../store/authStore\";\nimport { ConfirmActionDialog } from \"../components/ConfirmActionDialog\";\nimport { SpinnerIcon, AlertIcon } from \"../components/AuthIcons\";\nimport type { MFAMethod, MFASetupResult } from \"../types\";\nimport {\n nativeCopyText,\n nativeImpact,\n nativeNotify,\n} from \"../../utils/nativeBridge\";\n\n/**\n * MFA setup and management page with professional UI\n */\nexport function MfaSetupPage() {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n\n const navigate = useNavigate();\n const { setupMFA, enableMFA, disableMFA, isLoading } = useMfaOperations();\n const user = useAuthStore((state) => state.user);\n const isAuthenticated = useAuthStore((state) => state.isAuthenticated);\n const [setupData, setSetupData] = useState<MFASetupResult | null>(null);\n const [verificationCode, setVerificationCode] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n const [backupCodesCopied, setBackupCodesCopied] = useState(false);\n const [showDisableDialog, setShowDisableDialog] = useState(false);\n\n const handleSetupMfa = async (method: MFAMethod) => {\n try {\n setError(null);\n setSuccessMessage(null);\n const data = await setupMFA(method);\n setSetupData(data);\n } catch (err) {\n console.error(\"Failed to setup MFA:\", err);\n setError(\n err instanceof Error\n ? err.message\n : \"Failed to setup MFA. Please try again.\",\n );\n }\n };\n\n const handleVerifyAndEnable = async () => {\n if (verificationCode.length !== 6) {\n setError(tr(\"auth.mfaSetup.enter6Digit\", \"Please enter a 6-digit code\"));\n return;\n }\n\n try {\n setError(null);\n const success = await enableMFA(verificationCode);\n if (success) {\n setSetupData(null);\n setVerificationCode(\"\");\n setSuccessMessage(\n tr(\n \"auth.mfaSetup.enableSuccess\",\n \"Two-factor authentication has been enabled successfully!\",\n ),\n );\n }\n } catch (err) {\n console.error(\"Failed to verify MFA code:\", err);\n setError(\n err instanceof Error\n ? err.message\n : \"Invalid verification code. Please try again.\",\n );\n }\n };\n\n const handleDisableMfa = async () => {\n try {\n setError(null);\n setSuccessMessage(null);\n await disableMFA();\n setSuccessMessage(\n tr(\n \"auth.mfaSetup.disableSuccess\",\n \"Two-factor authentication has been disabled.\",\n ),\n );\n setShowDisableDialog(false);\n } catch (err) {\n console.error(\"Failed to disable MFA:\", err);\n setError(\n err instanceof Error\n ? err.message\n : \"Failed to disable MFA. Please try again.\",\n );\n }\n };\n\n const copyBackupCodes = async () => {\n if (setupData?.backupCodes) {\n void nativeImpact(\"light\");\n const ok = await nativeCopyText(setupData.backupCodes.join(\"\\n\"));\n if (ok) {\n setBackupCodesCopied(true);\n void nativeNotify(\"success\");\n setTimeout(() => setBackupCodesCopied(false), 2000);\n } else {\n void nativeNotify(\"error\");\n }\n }\n };\n\n const cancelSetup = () => {\n setSetupData(null);\n setVerificationCode(\"\");\n setError(null);\n };\n\n // Authentication check\n if (!isAuthenticated) {\n return (\n <div className=\"max-w-2xl mx-auto p-6\">\n <div className=\"text-center py-16 border-2 border-dashed border-border-default rounded-xl\">\n <div className=\"size-16 mx-auto mb-4 rounded-full bg-status-warning-bg-subtle flex items-center justify-center\">\n <AlertIcon className=\"size-8 text-status-warning-text\" />\n </div>\n <h2 className=\"text-xl font-semibold text-text-primary mb-2\">\n {tr(\"auth.mfaSetup.authRequired\", \"Authentication Required\")}\n </h2>\n <p className=\"text-text-secondary\">\n {tr(\n \"auth.mfaSetup.signInToManage\",\n \"Please sign in to manage MFA settings\",\n )}\n </p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"max-w-2xl mx-auto p-6\">\n <ConfirmActionDialog\n open={showDisableDialog}\n onOpenChange={setShowDisableDialog}\n title={tr(\n \"auth.mfaSetup.disableTitle\",\n \"Disable two-factor authentication?\",\n )}\n description={tr(\n \"auth.mfaSetup.disableDesc\",\n \"Your account will become less secure and future sign-ins will only require your password until MFA is re-enabled.\",\n )}\n confirmText={tr(\"auth.mfaSetup.disableConfirm\", \"Disable MFA\")}\n variant=\"warning\"\n isPending={isLoading}\n onConfirm={handleDisableMfa}\n />\n {/* Header */}\n <div className=\"mb-8\">\n <h1 className=\"text-3xl font-semibold text-[var(--color-text-primary)]\">\n {tr(\"auth.mfaSetup.title\", \"Two-Factor Authentication\")}\n </h1>\n <p className=\"text-[var(--color-text-secondary)] mt-2\">\n {tr(\n \"auth.mfaSetup.subtitle\",\n \"Add an extra layer of security to your account\",\n )}\n </p>\n <PagePurpose className=\"mt-3\">\n {tr(\n \"auth.mfaSetup.purpose\",\n \"Two-factor authentication (2FA) asks for a one-time code from an authenticator app at sign-in, so your account stays safe even if your password leaks. Set it up here and keep your backup codes somewhere safe.\",\n )}\n </PagePurpose>\n </div>\n\n {/* Success Message */}\n {successMessage && (\n <div className=\"mb-6 p-4 rounded-xl bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)]\">\n <div className=\"flex items-center gap-3\">\n <svg\n className=\"size-5 text-[var(--color-status-success-text)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <p className=\"text-[var(--color-status-success-text)]\">\n {successMessage}\n </p>\n </div>\n </div>\n )}\n\n {/* Error Message */}\n {error && (\n <div className=\"mb-6 flex items-start gap-3 p-4 rounded-xl bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)]\">\n <AlertIcon className=\"size-5 text-[var(--color-status-error-text)] flex-shrink-0 mt-0.5\" />\n <div className=\"flex-1\">\n <p className=\"text-sm text-[var(--color-status-error-text)]\">\n {error}\n </p>\n <button\n type=\"button\"\n onClick={() => setError(null)}\n className=\"mt-2 text-sm text-[var(--color-status-error-text)] hover:underline transition-colors duration-200\"\n >\n {tr(\"auth.mfaSetup.dismiss\", \"Dismiss\")}\n </button>\n </div>\n </div>\n )}\n\n {setupData ? (\n /* Setup Flow */\n <div className=\"p-6 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-sm\">\n <div className=\"flex items-center gap-3 mb-6\">\n <div className=\"size-10 rounded-full bg-[var(--color-bg-accent)] flex items-center justify-center\">\n <svg\n className=\"size-5 text-[var(--color-text-link)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n </div>\n <div>\n <h2 className=\"text-xl font-semibold text-[var(--color-text-primary)]\">\n {tr(\"auth.mfaSetup.setupAuthApp\", \"Setup Authenticator App\")}\n </h2>\n <p className=\"text-sm text-[var(--color-text-secondary)]\">\n {tr(\n \"auth.mfaSetup.scanQr\",\n \"Scan the QR code with your authenticator app\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"space-y-6\">\n {/* QR Code */}\n {setupData.qrCode && (\n <div className=\"flex justify-center\">\n <div className=\"p-4 bg-[var(--color-bg-surface)] rounded-xl border border-[var(--color-border-default)]\">\n <QRCodeSVG\n value={setupData.qrCode}\n size={192}\n level=\"M\"\n includeMargin={false}\n className=\"size-48\"\n />\n </div>\n </div>\n )}\n\n {/* Manual Secret */}\n {setupData.secret && (\n <div>\n <p className=\"text-sm text-[var(--color-text-secondary)] mb-2\">\n {tr(\n \"auth.mfaSetup.cantScan\",\n \"Can't scan the QR code? Enter this key manually:\",\n )}\n </p>\n <code className=\"block p-3 rounded-lg bg-[var(--color-bg-muted)] text-[var(--color-text-primary)] font-mono text-sm break-all select-all\">\n {setupData.secret}\n </code>\n </div>\n )}\n\n {/* Backup Codes */}\n {setupData.backupCodes && setupData.backupCodes.length > 0 && (\n <div className=\"p-4 rounded-xl bg-[var(--color-status-warning-bg-subtle)] border border-[var(--color-status-warning-border)]\">\n <div className=\"flex items-start gap-3 mb-3\">\n <svg\n className=\"size-5 text-[var(--color-status-warning-text)] flex-shrink-0 mt-0.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n <div>\n <h3 className=\"font-medium text-[var(--color-status-warning-text)]\">\n {tr(\n \"auth.mfaSetup.saveBackupCodes\",\n \"Save your backup codes\",\n )}\n </h3>\n <p className=\"text-sm text-[var(--color-status-warning-text)]\">\n {tr(\n \"auth.mfaSetup.storeCodesSafely\",\n \"Store these codes safely. You can use them to access your account if you lose your authenticator device.\",\n )}\n </p>\n </div>\n </div>\n <div className=\"p-3 rounded-lg bg-[var(--color-bg-surface)] grid grid-cols-2 gap-2 mb-3\">\n {setupData.backupCodes.map((code, i) => (\n <code\n key={code}\n className=\"text-sm text-[var(--color-text-primary)] font-mono\"\n >\n {i + 1}. {code}\n </code>\n ))}\n </div>\n <button\n type=\"button\"\n onClick={copyBackupCodes}\n className=\"text-sm font-medium text-[var(--color-status-warning-text)] hover:underline transition-colors duration-200\"\n >\n {backupCodesCopied\n ? tr(\"auth.mfaSetup.copied\", \"Copied!\")\n : tr(\"auth.mfaSetup.copyBackupCodes\", \"Copy backup codes\")}\n </button>\n </div>\n )}\n\n {/* Verification Code Input */}\n <div>\n <label\n htmlFor=\"mfa-verification-code\"\n className=\"block text-sm font-medium text-[var(--color-text-primary)] mb-2\"\n >\n {tr(\n \"auth.mfaSetup.enterCode\",\n \"Enter the 6-digit code from your app\",\n )}\n </label>\n <input\n id=\"mfa-verification-code\"\n type=\"text\"\n inputMode=\"numeric\"\n maxLength={6}\n value={verificationCode}\n onChange={(e) =>\n setVerificationCode(e.target.value.replace(/\\D/g, \"\"))\n }\n placeholder={tr(\n \"auth.mfa.verificationCodePlaceholder\",\n \"000000\",\n )}\n aria-label={tr(\n \"auth.mfaSetup.enterCode\",\n \"Enter the 6-digit code from your app\",\n )}\n aria-required=\"true\"\n autoComplete=\"one-time-code\"\n className=\"block w-full px-4 py-3 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] text-center text-2xl tracking-widest font-mono focus:outline-none focus:ring-2 focus:ring-action-primary-bg/20 focus:border-action-primary-bg transition-all duration-300\"\n />\n </div>\n\n {/* Action Buttons */}\n <div className=\"flex gap-3\">\n <button\n type=\"button\"\n onClick={cancelSetup}\n className=\"flex-1 py-3 px-4 rounded-xl border border-[var(--color-border-default)] text-[var(--color-text-secondary)] font-medium hover:bg-[var(--color-bg-muted)] transition-colors duration-200\"\n >\n {tr(\"auth.mfaSetup.cancel\", \"Cancel\")}\n </button>\n <Button\n type=\"button\"\n onClick={handleVerifyAndEnable}\n disabled={isLoading || verificationCode.length !== 6}\n variant=\"default\"\n size=\"lg\"\n className=\"flex-1 font-semibold\"\n >\n {isLoading ? (\n <>\n <SpinnerIcon className=\"size-5 animate-spin\" />\n <span>{tr(\"auth.mfa.verifying\", \"Verifying...\")}</span>\n </>\n ) : (\n tr(\"auth.mfaSetup.enable2fa\", \"Enable 2FA\")\n )}\n </Button>\n </div>\n </div>\n </div>\n ) : (\n /* Status Display */\n <div className=\"p-6 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-sm\">\n {!user?.mfaEnabled ? (\n /* MFA Not Enabled */\n <>\n <div className=\"flex items-center gap-4 mb-6\">\n <div className=\"size-12 rounded-full bg-[var(--color-bg-muted)] flex items-center justify-center\">\n <svg\n className=\"size-6 text-[var(--color-text-tertiary)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n />\n </svg>\n </div>\n <div>\n <h2 className=\"text-xl font-semibold text-[var(--color-text-primary)]\">\n {tr(\n \"auth.mfaSetup.twoFactorOff\",\n \"Two-Factor Authentication is Off\",\n )}\n </h2>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\n \"auth.mfaSetup.notProtected\",\n \"Your account is not protected with 2FA\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"mb-6 p-4 rounded-lg bg-[var(--color-bg-accent)] border border-[var(--color-border-default)]\">\n <h3 className=\"font-medium text-[var(--color-text-link)] mb-2\">\n {tr(\"auth.mfaSetup.whyEnable\", \"Why enable 2FA?\")}\n </h3>\n <ul className=\"text-sm text-[var(--color-text-link)] space-y-1\">\n <li>\n • Protects your account even if your password is compromised\n </li>\n <li>• Adds a second verification step during sign-in</li>\n <li>\n • Works with popular authenticator apps (Google, Authy,\n etc.)\n </li>\n </ul>\n </div>\n\n <Button\n type=\"button\"\n onClick={() => handleSetupMfa(\"TOTP\")}\n disabled={isLoading}\n variant=\"default\"\n size=\"lg\"\n className=\"w-full font-semibold\"\n >\n {isLoading ? (\n <>\n <SpinnerIcon className=\"size-5 animate-spin\" />\n <span>{tr(\"auth.mfa.settingUp\", \"Setting up...\")}</span>\n </>\n ) : (\n <>\n <svg\n className=\"size-5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n <span>\n {tr(\n \"auth.mfaSetup.enableTwoFactor\",\n \"Enable Two-Factor Authentication\",\n )}\n </span>\n </>\n )}\n </Button>\n </>\n ) : (\n /* MFA Enabled */\n <>\n <div className=\"flex items-center gap-4 mb-6\">\n <div className=\"size-12 rounded-full bg-[var(--color-status-success-bg-subtle)] flex items-center justify-center\">\n <svg\n className=\"size-6 text-[var(--color-status-success-text)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n />\n </svg>\n </div>\n <div>\n <h2 className=\"text-xl font-semibold text-[var(--color-text-primary)]\">\n {tr(\n \"auth.mfaSetup.twoFactorOn\",\n \"Two-Factor Authentication is On\",\n )}\n </h2>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\n \"auth.mfaSetup.protected\",\n \"Your account is protected with an authenticator app\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"mb-6 p-4 rounded-lg bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)]\">\n <p className=\"text-sm text-[var(--color-status-success-text)]\">\n {tr(\n \"auth.mfaSetup.verificationOnSignIn\",\n \"You'll be asked for a verification code from your authenticator app when signing in.\",\n )}\n </p>\n </div>\n\n <button\n type=\"button\"\n onClick={() => setShowDisableDialog(true)}\n disabled={isLoading}\n className=\"w-full py-3 px-4 rounded-xl border border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] font-medium bg-[var(--color-bg-surface)] hover:bg-[var(--color-status-error-bg-subtle)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200 flex items-center justify-center gap-2\"\n >\n {isLoading ? (\n <>\n <SpinnerIcon className=\"size-5 animate-spin\" />\n <span>{tr(\"auth.mfa.disabling\", \"Disabling...\")}</span>\n </>\n ) : (\n tr(\n \"auth.mfaSetup.disableTwoFactor\",\n \"Disable Two-Factor Authentication\",\n )\n )}\n </button>\n\n <NextSteps\n className=\"mt-6\"\n storageKey=\"auth-mfa-enabled\"\n steps={[\n {\n id: \"review-sessions\",\n label: tr(\n \"auth.mfaSetup.nextReviewSessions\",\n \"Review your active sessions\",\n ),\n description: tr(\n \"auth.mfaSetup.nextReviewSessionsDesc\",\n \"Sign out any device you no longer recognise.\",\n ),\n onClick: () => navigate(\"/auth/sessions\"),\n },\n {\n id: \"security-center\",\n label: tr(\n \"auth.mfaSetup.nextSecurityCenter\",\n \"Visit the Security Center\",\n ),\n description: tr(\n \"auth.mfaSetup.nextSecurityCenterDesc\",\n \"Check your password and account protection at a glance.\",\n ),\n onClick: () => navigate(\"/auth/security\"),\n },\n {\n id: \"update-profile\",\n label: tr(\n \"auth.mfaSetup.nextProfile\",\n \"Keep your profile up to date\",\n ),\n description: tr(\n \"auth.mfaSetup.nextProfileDesc\",\n \"Confirm your recovery email and contact details.\",\n ),\n onClick: () => navigate(\"/auth/profile\"),\n },\n ]}\n />\n </>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MfaSetupPage.js","names":[],"sources":["../../../src/auth/pages/MfaSetupPage.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { useNavigate } from \"react-router\";\nimport { useTr } from \"../../shared/hooks/useTr\";\nimport { Button } from \"@burdenoff/fe-libs/button\";\nimport { PagePurpose, NextSteps } from \"@burdenoff/fe-libs/ui\";\nimport { QRCodeSVG } from \"qrcode.react\";\nimport { useMfaOperations } from \"../hooks/useMfaOperations\";\nimport { useAuthStore } from \"../store/authStore\";\nimport { ConfirmActionDialog } from \"../components/ConfirmActionDialog\";\nimport { SpinnerIcon, AlertIcon } from \"../components/AuthIcons\";\nimport type { MFAMethod, MFASetupResult } from \"../types\";\nimport {\n nativeCopyText,\n nativeImpact,\n nativeNotify,\n} from \"../../utils/nativeBridge\";\n\n/**\n * MFA setup and management page with professional UI\n */\nexport function MfaSetupPage() {\n const tr = useTr();\n\n const navigate = useNavigate();\n const { setupMFA, enableMFA, disableMFA, isLoading } = useMfaOperations();\n const user = useAuthStore((state) => state.user);\n const isAuthenticated = useAuthStore((state) => state.isAuthenticated);\n const [setupData, setSetupData] = useState<MFASetupResult | null>(null);\n const [verificationCode, setVerificationCode] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n const [backupCodesCopied, setBackupCodesCopied] = useState(false);\n const [showDisableDialog, setShowDisableDialog] = useState(false);\n\n const handleSetupMfa = async (method: MFAMethod) => {\n try {\n setError(null);\n setSuccessMessage(null);\n const data = await setupMFA(method);\n setSetupData(data);\n } catch (err) {\n console.error(\"Failed to setup MFA:\", err);\n setError(\n err instanceof Error\n ? err.message\n : \"Failed to setup MFA. Please try again.\",\n );\n }\n };\n\n const handleVerifyAndEnable = async () => {\n if (verificationCode.length !== 6) {\n setError(tr(\"auth.mfaSetup.enter6Digit\", \"Please enter a 6-digit code\"));\n return;\n }\n\n try {\n setError(null);\n const success = await enableMFA(verificationCode);\n if (success) {\n setSetupData(null);\n setVerificationCode(\"\");\n setSuccessMessage(\n tr(\n \"auth.mfaSetup.enableSuccess\",\n \"Two-factor authentication has been enabled successfully!\",\n ),\n );\n }\n } catch (err) {\n console.error(\"Failed to verify MFA code:\", err);\n setError(\n err instanceof Error\n ? err.message\n : \"Invalid verification code. Please try again.\",\n );\n }\n };\n\n const handleDisableMfa = async () => {\n try {\n setError(null);\n setSuccessMessage(null);\n await disableMFA();\n setSuccessMessage(\n tr(\n \"auth.mfaSetup.disableSuccess\",\n \"Two-factor authentication has been disabled.\",\n ),\n );\n setShowDisableDialog(false);\n } catch (err) {\n console.error(\"Failed to disable MFA:\", err);\n setError(\n err instanceof Error\n ? err.message\n : \"Failed to disable MFA. Please try again.\",\n );\n }\n };\n\n const copyBackupCodes = async () => {\n if (setupData?.backupCodes) {\n void nativeImpact(\"light\");\n const ok = await nativeCopyText(setupData.backupCodes.join(\"\\n\"));\n if (ok) {\n setBackupCodesCopied(true);\n void nativeNotify(\"success\");\n setTimeout(() => setBackupCodesCopied(false), 2000);\n } else {\n void nativeNotify(\"error\");\n }\n }\n };\n\n const cancelSetup = () => {\n setSetupData(null);\n setVerificationCode(\"\");\n setError(null);\n };\n\n // Authentication check\n if (!isAuthenticated) {\n return (\n <div className=\"max-w-2xl mx-auto p-6\">\n <div className=\"text-center py-16 border-2 border-dashed border-border-default rounded-xl\">\n <div className=\"size-16 mx-auto mb-4 rounded-full bg-status-warning-bg-subtle flex items-center justify-center\">\n <AlertIcon className=\"size-8 text-status-warning-text\" />\n </div>\n <h2 className=\"text-xl font-semibold text-text-primary mb-2\">\n {tr(\"auth.mfaSetup.authRequired\", \"Authentication Required\")}\n </h2>\n <p className=\"text-text-secondary\">\n {tr(\n \"auth.mfaSetup.signInToManage\",\n \"Please sign in to manage MFA settings\",\n )}\n </p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"max-w-2xl mx-auto p-6\">\n <ConfirmActionDialog\n open={showDisableDialog}\n onOpenChange={setShowDisableDialog}\n title={tr(\n \"auth.mfaSetup.disableTitle\",\n \"Disable two-factor authentication?\",\n )}\n description={tr(\n \"auth.mfaSetup.disableDesc\",\n \"Your account will become less secure and future sign-ins will only require your password until MFA is re-enabled.\",\n )}\n confirmText={tr(\"auth.mfaSetup.disableConfirm\", \"Disable MFA\")}\n variant=\"warning\"\n isPending={isLoading}\n onConfirm={handleDisableMfa}\n />\n {/* Header */}\n <div className=\"mb-8\">\n <h1 className=\"text-3xl font-semibold text-[var(--color-text-primary)]\">\n {tr(\"auth.mfaSetup.title\", \"Two-Factor Authentication\")}\n </h1>\n <p className=\"text-[var(--color-text-secondary)] mt-2\">\n {tr(\n \"auth.mfaSetup.subtitle\",\n \"Add an extra layer of security to your account\",\n )}\n </p>\n <PagePurpose className=\"mt-3\">\n {tr(\n \"auth.mfaSetup.purpose\",\n \"Two-factor authentication (2FA) asks for a one-time code from an authenticator app at sign-in, so your account stays safe even if your password leaks. Set it up here and keep your backup codes somewhere safe.\",\n )}\n </PagePurpose>\n </div>\n\n {/* Success Message */}\n {successMessage && (\n <div className=\"mb-6 p-4 rounded-xl bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)]\">\n <div className=\"flex items-center gap-3\">\n <svg\n className=\"size-5 text-[var(--color-status-success-text)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <p className=\"text-[var(--color-status-success-text)]\">\n {successMessage}\n </p>\n </div>\n </div>\n )}\n\n {/* Error Message */}\n {error && (\n <div className=\"mb-6 flex items-start gap-3 p-4 rounded-xl bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)]\">\n <AlertIcon className=\"size-5 text-[var(--color-status-error-text)] flex-shrink-0 mt-0.5\" />\n <div className=\"flex-1\">\n <p className=\"text-sm text-[var(--color-status-error-text)]\">\n {error}\n </p>\n <button\n type=\"button\"\n onClick={() => setError(null)}\n className=\"mt-2 text-sm text-[var(--color-status-error-text)] hover:underline transition-colors duration-200\"\n >\n {tr(\"auth.mfaSetup.dismiss\", \"Dismiss\")}\n </button>\n </div>\n </div>\n )}\n\n {setupData ? (\n /* Setup Flow */\n <div className=\"p-6 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-sm\">\n <div className=\"flex items-center gap-3 mb-6\">\n <div className=\"size-10 rounded-full bg-[var(--color-bg-accent)] flex items-center justify-center\">\n <svg\n className=\"size-5 text-[var(--color-text-link)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n </div>\n <div>\n <h2 className=\"text-xl font-semibold text-[var(--color-text-primary)]\">\n {tr(\"auth.mfaSetup.setupAuthApp\", \"Setup Authenticator App\")}\n </h2>\n <p className=\"text-sm text-[var(--color-text-secondary)]\">\n {tr(\n \"auth.mfaSetup.scanQr\",\n \"Scan the QR code with your authenticator app\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"space-y-6\">\n {/* QR Code */}\n {setupData.qrCode && (\n <div className=\"flex justify-center\">\n <div className=\"p-4 bg-[var(--color-bg-surface)] rounded-xl border border-[var(--color-border-default)]\">\n <QRCodeSVG\n value={setupData.qrCode}\n size={192}\n level=\"M\"\n includeMargin={false}\n className=\"size-48\"\n />\n </div>\n </div>\n )}\n\n {/* Manual Secret */}\n {setupData.secret && (\n <div>\n <p className=\"text-sm text-[var(--color-text-secondary)] mb-2\">\n {tr(\n \"auth.mfaSetup.cantScan\",\n \"Can't scan the QR code? Enter this key manually:\",\n )}\n </p>\n <code className=\"block p-3 rounded-lg bg-[var(--color-bg-muted)] text-[var(--color-text-primary)] font-mono text-sm break-all select-all\">\n {setupData.secret}\n </code>\n </div>\n )}\n\n {/* Backup Codes */}\n {setupData.backupCodes && setupData.backupCodes.length > 0 && (\n <div className=\"p-4 rounded-xl bg-[var(--color-status-warning-bg-subtle)] border border-[var(--color-status-warning-border)]\">\n <div className=\"flex items-start gap-3 mb-3\">\n <svg\n className=\"size-5 text-[var(--color-status-warning-text)] flex-shrink-0 mt-0.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n <div>\n <h3 className=\"font-medium text-[var(--color-status-warning-text)]\">\n {tr(\n \"auth.mfaSetup.saveBackupCodes\",\n \"Save your backup codes\",\n )}\n </h3>\n <p className=\"text-sm text-[var(--color-status-warning-text)]\">\n {tr(\n \"auth.mfaSetup.storeCodesSafely\",\n \"Store these codes safely. You can use them to access your account if you lose your authenticator device.\",\n )}\n </p>\n </div>\n </div>\n <div className=\"p-3 rounded-lg bg-[var(--color-bg-surface)] grid grid-cols-2 gap-2 mb-3\">\n {setupData.backupCodes.map((code, i) => (\n <code\n key={code}\n className=\"text-sm text-[var(--color-text-primary)] font-mono\"\n >\n {i + 1}. {code}\n </code>\n ))}\n </div>\n <button\n type=\"button\"\n onClick={copyBackupCodes}\n className=\"text-sm font-medium text-[var(--color-status-warning-text)] hover:underline transition-colors duration-200\"\n >\n {backupCodesCopied\n ? tr(\"auth.mfaSetup.copied\", \"Copied!\")\n : tr(\"auth.mfaSetup.copyBackupCodes\", \"Copy backup codes\")}\n </button>\n </div>\n )}\n\n {/* Verification Code Input */}\n <div>\n <label\n htmlFor=\"mfa-verification-code\"\n className=\"block text-sm font-medium text-[var(--color-text-primary)] mb-2\"\n >\n {tr(\n \"auth.mfaSetup.enterCode\",\n \"Enter the 6-digit code from your app\",\n )}\n </label>\n <input\n id=\"mfa-verification-code\"\n type=\"text\"\n inputMode=\"numeric\"\n maxLength={6}\n value={verificationCode}\n onChange={(e) =>\n setVerificationCode(e.target.value.replace(/\\D/g, \"\"))\n }\n placeholder={tr(\n \"auth.mfa.verificationCodePlaceholder\",\n \"000000\",\n )}\n aria-label={tr(\n \"auth.mfaSetup.enterCode\",\n \"Enter the 6-digit code from your app\",\n )}\n aria-required=\"true\"\n autoComplete=\"one-time-code\"\n className=\"block w-full px-4 py-3 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] text-center text-2xl tracking-widest font-mono focus:outline-none focus:ring-2 focus:ring-action-primary-bg/20 focus:border-action-primary-bg transition-all duration-300\"\n />\n </div>\n\n {/* Action Buttons */}\n <div className=\"flex gap-3\">\n <button\n type=\"button\"\n onClick={cancelSetup}\n className=\"flex-1 py-3 px-4 rounded-xl border border-[var(--color-border-default)] text-[var(--color-text-secondary)] font-medium hover:bg-[var(--color-bg-muted)] transition-colors duration-200\"\n >\n {tr(\"auth.mfaSetup.cancel\", \"Cancel\")}\n </button>\n <Button\n type=\"button\"\n onClick={handleVerifyAndEnable}\n disabled={isLoading || verificationCode.length !== 6}\n variant=\"default\"\n size=\"lg\"\n className=\"flex-1 font-semibold\"\n >\n {isLoading ? (\n <>\n <SpinnerIcon className=\"size-5 animate-spin\" />\n <span>{tr(\"auth.mfa.verifying\", \"Verifying...\")}</span>\n </>\n ) : (\n tr(\"auth.mfaSetup.enable2fa\", \"Enable 2FA\")\n )}\n </Button>\n </div>\n </div>\n </div>\n ) : (\n /* Status Display */\n <div className=\"p-6 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-sm\">\n {!user?.mfaEnabled ? (\n /* MFA Not Enabled */\n <>\n <div className=\"flex items-center gap-4 mb-6\">\n <div className=\"size-12 rounded-full bg-[var(--color-bg-muted)] flex items-center justify-center\">\n <svg\n className=\"size-6 text-[var(--color-text-tertiary)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n />\n </svg>\n </div>\n <div>\n <h2 className=\"text-xl font-semibold text-[var(--color-text-primary)]\">\n {tr(\n \"auth.mfaSetup.twoFactorOff\",\n \"Two-Factor Authentication is Off\",\n )}\n </h2>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\n \"auth.mfaSetup.notProtected\",\n \"Your account is not protected with 2FA\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"mb-6 p-4 rounded-lg bg-[var(--color-bg-accent)] border border-[var(--color-border-default)]\">\n <h3 className=\"font-medium text-[var(--color-text-link)] mb-2\">\n {tr(\"auth.mfaSetup.whyEnable\", \"Why enable 2FA?\")}\n </h3>\n <ul className=\"text-sm text-[var(--color-text-link)] space-y-1\">\n <li>\n • Protects your account even if your password is compromised\n </li>\n <li>• Adds a second verification step during sign-in</li>\n <li>\n • Works with popular authenticator apps (Google, Authy,\n etc.)\n </li>\n </ul>\n </div>\n\n <Button\n type=\"button\"\n onClick={() => handleSetupMfa(\"TOTP\")}\n disabled={isLoading}\n variant=\"default\"\n size=\"lg\"\n className=\"w-full font-semibold\"\n >\n {isLoading ? (\n <>\n <SpinnerIcon className=\"size-5 animate-spin\" />\n <span>{tr(\"auth.mfa.settingUp\", \"Setting up...\")}</span>\n </>\n ) : (\n <>\n <svg\n className=\"size-5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n <span>\n {tr(\n \"auth.mfaSetup.enableTwoFactor\",\n \"Enable Two-Factor Authentication\",\n )}\n </span>\n </>\n )}\n </Button>\n </>\n ) : (\n /* MFA Enabled */\n <>\n <div className=\"flex items-center gap-4 mb-6\">\n <div className=\"size-12 rounded-full bg-[var(--color-status-success-bg-subtle)] flex items-center justify-center\">\n <svg\n className=\"size-6 text-[var(--color-status-success-text)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n />\n </svg>\n </div>\n <div>\n <h2 className=\"text-xl font-semibold text-[var(--color-text-primary)]\">\n {tr(\n \"auth.mfaSetup.twoFactorOn\",\n \"Two-Factor Authentication is On\",\n )}\n </h2>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\n \"auth.mfaSetup.protected\",\n \"Your account is protected with an authenticator app\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"mb-6 p-4 rounded-lg bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)]\">\n <p className=\"text-sm text-[var(--color-status-success-text)]\">\n {tr(\n \"auth.mfaSetup.verificationOnSignIn\",\n \"You'll be asked for a verification code from your authenticator app when signing in.\",\n )}\n </p>\n </div>\n\n <button\n type=\"button\"\n onClick={() => setShowDisableDialog(true)}\n disabled={isLoading}\n className=\"w-full py-3 px-4 rounded-xl border border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] font-medium bg-[var(--color-bg-surface)] hover:bg-[var(--color-status-error-bg-subtle)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200 flex items-center justify-center gap-2\"\n >\n {isLoading ? (\n <>\n <SpinnerIcon className=\"size-5 animate-spin\" />\n <span>{tr(\"auth.mfa.disabling\", \"Disabling...\")}</span>\n </>\n ) : (\n tr(\n \"auth.mfaSetup.disableTwoFactor\",\n \"Disable Two-Factor Authentication\",\n )\n )}\n </button>\n\n <NextSteps\n className=\"mt-6\"\n storageKey=\"auth-mfa-enabled\"\n steps={[\n {\n id: \"review-sessions\",\n label: tr(\n \"auth.mfaSetup.nextReviewSessions\",\n \"Review your active sessions\",\n ),\n description: tr(\n \"auth.mfaSetup.nextReviewSessionsDesc\",\n \"Sign out any device you no longer recognise.\",\n ),\n onClick: () => navigate(\"/auth/sessions\"),\n },\n {\n id: \"security-center\",\n label: tr(\n \"auth.mfaSetup.nextSecurityCenter\",\n \"Visit the Security Center\",\n ),\n description: tr(\n \"auth.mfaSetup.nextSecurityCenterDesc\",\n \"Check your password and account protection at a glance.\",\n ),\n onClick: () => navigate(\"/auth/security\"),\n },\n {\n id: \"update-profile\",\n label: tr(\n \"auth.mfaSetup.nextProfile\",\n \"Keep your profile up to date\",\n ),\n description: tr(\n \"auth.mfaSetup.nextProfileDesc\",\n \"Confirm your recovery email and contact details.\",\n ),\n onClick: () => navigate(\"/auth/profile\"),\n },\n ]}\n />\n </>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}