@burdenoff/microfe-auth 2026.1102.1 → 2026.1107.1

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.
@@ -32,10 +32,7 @@ export declare function useAuthOperations(options?: UseAuthOperationsOptions): {
32
32
  success: boolean;
33
33
  message: string;
34
34
  }>;
35
- refetchCurrentUser: (variables?: Partial<import('@apollo/client').OperationVariables> | undefined) => Promise<{
36
- data: CurrentUserResponse | undefined;
37
- error?: import('@apollo/client').ErrorLike;
38
- }>;
35
+ refetchCurrentUser: import('@apollo/client/react/internal').RefetchFunction<CurrentUserResponse, import('@apollo/client').OperationVariables, undefined>;
39
36
  login: (input: SignInInput) => Promise<AuthResult>;
40
37
  register: (input: SignUpInput) => Promise<AuthPayload | {
41
38
  requiresEmailVerification: boolean;
@@ -21,14 +21,8 @@ export declare function useDelegationOperations(): {
21
21
  revokeDelegation: (id: string, reason?: string) => Promise<boolean>;
22
22
  getDelegationsForApp: (appId: string) => AppUserDelegation[];
23
23
  hasWorkspaceDelegation: (appId: string, workspaceId: string) => boolean;
24
- refetchDelegations: (variables?: Partial<import('@apollo/client').OperationVariables> | undefined) => Promise<{
25
- data: CurrentUserDelegationsResponse | undefined;
26
- error?: import('@apollo/client').ErrorLike;
27
- }>;
28
- refetchGrantedDelegations: (variables?: Partial<import('@apollo/client').OperationVariables> | undefined) => Promise<{
29
- data: CurrentUserGrantedDelegationsResponse | undefined;
30
- error?: import('@apollo/client').ErrorLike;
31
- }>;
24
+ refetchDelegations: import('@apollo/client/react/internal').RefetchFunction<CurrentUserDelegationsResponse, import('@apollo/client').OperationVariables, undefined>;
25
+ refetchGrantedDelegations: import('@apollo/client/react/internal').RefetchFunction<CurrentUserGrantedDelegationsResponse, import('@apollo/client').OperationVariables, undefined>;
32
26
  delegations: AppUserDelegation[];
33
27
  grantedDelegations: AppUserDelegation[];
34
28
  isLoading: boolean;
@@ -38,9 +38,6 @@ export declare function useMyWorkspaces(): {
38
38
  workspace?: Workspace;
39
39
  error?: string;
40
40
  }>;
41
- refetch: (variables?: Partial<import('@apollo/client').OperationVariables> | undefined) => Promise<{
42
- data: MyWorkspacesResponse | undefined;
43
- error?: import('@apollo/client').ErrorLike;
44
- }>;
41
+ refetch: import('@apollo/client/react/internal').RefetchFunction<MyWorkspacesResponse, import('@apollo/client').OperationVariables, undefined>;
45
42
  };
46
43
  export {};
@@ -22,24 +22,20 @@ export declare function useSessionOperations(options?: UseSessionOperationsOptio
22
22
  revokedCount: number;
23
23
  }>;
24
24
  activeSessions: {
25
- __typename?: "Session";
26
25
  id: string;
27
26
  status: import('../../generated/global-types').SessionStatus;
28
- ipAddress?: string | null;
29
- userAgent?: string | null;
30
- location?: string | null;
27
+ ipAddress: string | null;
28
+ userAgent: string | null;
29
+ location: string | null;
31
30
  lastActivityAt: string;
32
31
  expiresAt: string;
33
32
  createdAt: string;
34
33
  isCurrent: boolean;
35
34
  }[];
36
35
  sessionsLoading: boolean;
37
- refetchSessions: (variables?: Partial<import('../../generated/global-types').Exact<{
38
- pagination?: import('../../generated/global-types').InputMaybe<import('../../generated/global-types').PaginationInput>;
39
- }>> | undefined) => Promise<{
40
- data: ActiveSessionsQuery | undefined;
41
- error?: import('@apollo/client').ErrorLike;
42
- }>;
36
+ refetchSessions: import('@apollo/client/react/internal').RefetchFunction<ActiveSessionsQuery, {
37
+ pagination?: import('../../generated/global-types').PaginationInput | null | undefined;
38
+ }, undefined>;
43
39
  page: number;
44
40
  pageSize: number;
45
41
  totalCount: number;
@@ -48,9 +44,6 @@ export declare function useSessionOperations(options?: UseSessionOperationsOptio
48
44
  goToNextPage: () => void;
49
45
  goToPrevPage: () => void;
50
46
  isLoading: boolean;
51
- refetch: (variables?: Partial<import('@apollo/client').OperationVariables> | undefined) => Promise<{
52
- data: TokenInfoQueryResponse | undefined;
53
- error?: import('@apollo/client').ErrorLike;
54
- }>;
47
+ refetch: import('@apollo/client/react/internal').RefetchFunction<TokenInfoQueryResponse, import('@apollo/client').OperationVariables, undefined>;
55
48
  };
56
49
  export {};
@@ -58,9 +58,6 @@ export declare function useSsoOperations(tenantId?: string): {
58
58
  isSaving: boolean;
59
59
  isDeleting: boolean;
60
60
  isGeneratingOidcUrl: boolean;
61
- refetchConfig: (variables?: Partial<GetSSOConfigVariables> | undefined) => Promise<{
62
- data: GetSSOConfigResponse | undefined;
63
- error?: import('@apollo/client').ErrorLike;
64
- }>;
61
+ refetchConfig: import('@apollo/client/react/internal').RefetchFunction<GetSSOConfigResponse, GetSSOConfigVariables, undefined>;
65
62
  };
66
63
  export {};
@@ -3,90 +3,101 @@ import { useAuthOperations as t } from "../hooks/useAuthOperations.js";
3
3
  import { useAuthStore as n } from "../store/authStore.js";
4
4
  import { AuthLayout as r } from "../components/AuthLayout.js";
5
5
  import { SpinnerIcon as i } from "../components/AuthIcons.js";
6
- import { useCallback as a, useEffect as o, useRef as s, useState as c } from "react";
7
- import { useSearchParams as l } from "react-router";
8
- import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
9
- import { Button as p } from "@burdenoff/fe-libs/button";
6
+ import { authPathWithReturnTo as a, consumeReturnTo as o } from "../utils/pendingReturnTo.js";
7
+ import { useCallback as s, useEffect as c, useRef as l, useState as u } from "react";
8
+ import { useSearchParams as d } from "react-router";
9
+ import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
10
+ import { Button as h } from "@burdenoff/fe-libs/button";
10
11
  // src/auth/pages/EmailVerifyPage.tsx
11
- var m = 5, h = /* @__PURE__ */ new Map();
12
- function g(e) {
13
- let t = "/auth/login", n = e ? `${t}?email=${encodeURIComponent(e)}` : t;
14
- window.location.href = n;
12
+ var g = 5, _ = /* @__PURE__ */ new Map();
13
+ function v(e, t) {
14
+ window.location.href = a("/auth/login", t, e);
15
15
  }
16
- function _() {
17
- let _ = e(), [v] = l(), y = v.get("token"), b = v.get("email"), { verifyEmail: x, resendVerification: S } = t(), C = n((e) => e.user), [w, T] = c("verifying"), E = s(b || void 0), [D, O] = c(!1), [k, A] = c(!1), [j, M] = c(m), N = s(null);
18
- o(() => {
19
- if (!y) return;
16
+ function y() {
17
+ let a = e(), [y] = d(), b = y.get("token"), x = y.get("email"), { verifyEmail: S, resendVerification: C } = t(), w = n((e) => e.user), [T, E] = u("verifying"), D = l(x || void 0), [O, k] = u(!1), [A, j] = u(!1), [M, N] = u(g), P = l(null);
18
+ c(() => {
19
+ if (!b) return;
20
20
  try {
21
- window.sessionStorage.removeItem(`auth:verifyEmail:inflight:${y}`);
21
+ window.sessionStorage.removeItem(`auth:verifyEmail:inflight:${b}`);
22
22
  } catch {}
23
- if (N.current?.token !== y) {
24
- let e = h.get(y);
25
- e || (e = Promise.resolve().then(() => x(y)).finally(() => h.delete(y)), h.set(y, e)), N.current = {
26
- token: y,
23
+ if (P.current?.token !== b) {
24
+ let e = _.get(b);
25
+ e || (e = Promise.resolve().then(() => S(b)).finally(() => _.delete(b)), _.set(b, e)), P.current = {
26
+ token: b,
27
27
  request: e
28
- }, T("verifying");
28
+ }, E("verifying");
29
29
  }
30
30
  let e = !0;
31
- return N.current.request.then((t) => {
32
- e && (t.success ? (T("success"), t.email && (E.current = t.email)) : T("error"));
31
+ return P.current.request.then((t) => {
32
+ e && (t.success ? (E("success"), t.email && (D.current = t.email)) : E("error"));
33
33
  }).catch(() => {
34
- e && T("error");
34
+ e && E("error");
35
35
  }), () => {
36
36
  e = !1;
37
37
  };
38
- }, [y, x]), o(() => {
39
- if (w !== "success") return;
38
+ }, [b, S]);
39
+ let F = l(void 0), I = s(() => (F.current === void 0 && (F.current = o()), F.current), []), L = l(!1), R = s((e) => {
40
+ L.current || (L.current = !0, v(e, I()));
41
+ }, [I]);
42
+ c(() => {
43
+ if (T !== "success") return;
44
+ I();
40
45
  let e = setInterval(() => {
41
- M((t) => t <= 1 ? (clearInterval(e), g(E.current), 0) : t - 1);
46
+ N((e) => e <= 1 ? 0 : e - 1);
42
47
  }, 1e3);
43
48
  return () => clearInterval(e);
44
- }, [w]);
45
- let P = async () => {
46
- let e = b || C?.email;
49
+ }, [T, I]), c(() => {
50
+ T === "success" && M === 0 && R(D.current);
51
+ }, [
52
+ T,
53
+ M,
54
+ R
55
+ ]);
56
+ let z = async () => {
57
+ let e = x || w?.email;
47
58
  if (!e) console.error("No email available for resend");
48
59
  else {
49
- O(!0);
60
+ k(!0);
50
61
  try {
51
- await S(e), A(!0);
62
+ await C(e), j(!0);
52
63
  } catch (e) {
53
64
  console.error("Failed to resend verification:", e);
54
65
  } finally {
55
- O(!1);
66
+ k(!1);
56
67
  }
57
68
  }
58
- }, F = a(() => {
59
- g(E.current);
60
- }, []), I = a(() => {
61
- g();
62
- }, []);
63
- return w === "verifying" ? /* @__PURE__ */ d(r, {
64
- title: _("auth.emailVerify.verifyingTitle", "Verifying your email"),
65
- subtitle: _("auth.emailVerify.verifyingSubtitle", "Please wait while we confirm your email address"),
66
- children: /* @__PURE__ */ f("div", {
69
+ }, B = s(() => {
70
+ R(D.current);
71
+ }, [R]), V = s(() => {
72
+ R();
73
+ }, [R]);
74
+ return T === "verifying" ? /* @__PURE__ */ p(r, {
75
+ title: a("auth.emailVerify.verifyingTitle", "Verifying your email"),
76
+ subtitle: a("auth.emailVerify.verifyingSubtitle", "Please wait while we confirm your email address"),
77
+ children: /* @__PURE__ */ m("div", {
67
78
  className: "flex flex-col items-center justify-center py-12",
68
- children: [/* @__PURE__ */ d("div", {
79
+ children: [/* @__PURE__ */ p("div", {
69
80
  className: "size-16 rounded-full bg-[var(--color-bg-accent)] flex items-center justify-center mb-6",
70
- children: /* @__PURE__ */ d(i, { className: "size-8 text-[var(--color-text-link)] animate-spin" })
71
- }), /* @__PURE__ */ d("p", {
81
+ children: /* @__PURE__ */ p(i, { className: "size-8 text-[var(--color-text-link)] animate-spin" })
82
+ }), /* @__PURE__ */ p("p", {
72
83
  className: "text-[var(--color-text-secondary)]",
73
- children: _("auth.emailVerify.moment", "This will only take a moment...")
84
+ children: a("auth.emailVerify.moment", "This will only take a moment...")
74
85
  })]
75
86
  })
76
- }) : w === "success" ? /* @__PURE__ */ d(r, {
77
- title: _("auth.emailVerify.verifiedTitle", "Email verified!"),
78
- subtitle: _("auth.emailVerify.verifiedSubtitle", "Your email address has been confirmed"),
79
- children: /* @__PURE__ */ f("div", {
87
+ }) : T === "success" ? /* @__PURE__ */ p(r, {
88
+ title: a("auth.emailVerify.verifiedTitle", "Email verified!"),
89
+ subtitle: a("auth.emailVerify.verifiedSubtitle", "Your email address has been confirmed"),
90
+ children: /* @__PURE__ */ m("div", {
80
91
  className: "flex flex-col items-center justify-center py-6",
81
92
  children: [
82
- /* @__PURE__ */ d("div", {
93
+ /* @__PURE__ */ p("div", {
83
94
  className: "size-20 rounded-full bg-[var(--color-status-success-bg-subtle)] flex items-center justify-center mb-6",
84
- children: /* @__PURE__ */ d("svg", {
95
+ children: /* @__PURE__ */ p("svg", {
85
96
  className: "size-10 text-[var(--color-status-success-text)]",
86
97
  fill: "none",
87
98
  viewBox: "0 0 24 24",
88
99
  stroke: "currentColor",
89
- children: /* @__PURE__ */ d("path", {
100
+ children: /* @__PURE__ */ p("path", {
90
101
  strokeLinecap: "round",
91
102
  strokeLinejoin: "round",
92
103
  strokeWidth: 2,
@@ -94,47 +105,47 @@ function _() {
94
105
  })
95
106
  })
96
107
  }),
97
- /* @__PURE__ */ d("p", {
108
+ /* @__PURE__ */ p("p", {
98
109
  className: "text-center text-[var(--color-text-secondary)] mb-6",
99
- children: _("auth.emailVerify.successMessage", "Your email has been successfully verified. You can now sign in to access all features.")
110
+ children: a("auth.emailVerify.successMessage", "Your email has been successfully verified. You can now sign in to access all features.")
100
111
  }),
101
- /* @__PURE__ */ f("p", {
112
+ /* @__PURE__ */ m("p", {
102
113
  className: "text-center text-sm text-[var(--color-text-tertiary)] mb-6",
103
114
  children: [
104
- _("auth.emailVerify.redirecting", "Redirecting to sign in in"),
115
+ a("auth.emailVerify.redirecting", "Redirecting to sign in in"),
105
116
  " ",
106
- /* @__PURE__ */ d("span", {
117
+ /* @__PURE__ */ p("span", {
107
118
  className: "font-semibold text-[var(--color-text-primary)]",
108
- children: j
119
+ children: M
109
120
  }),
110
121
  " ",
111
- _("auth.emailVerify.seconds", "seconds...")
122
+ a("auth.emailVerify.seconds", "seconds...")
112
123
  ]
113
124
  }),
114
- /* @__PURE__ */ d(p, {
125
+ /* @__PURE__ */ p(h, {
115
126
  type: "button",
116
- onClick: F,
127
+ onClick: B,
117
128
  variant: "default",
118
129
  size: "lg",
119
130
  className: "w-full font-semibold",
120
- children: _("auth.emailVerify.continueSignIn", "Continue to sign in now")
131
+ children: a("auth.emailVerify.continueSignIn", "Continue to sign in now")
121
132
  })
122
133
  ]
123
134
  })
124
- }) : /* @__PURE__ */ d(r, {
125
- title: _("auth.emailVerify.failedTitle", "Verification failed"),
126
- subtitle: _("auth.emailVerify.failedSubtitle", "We couldn't verify your email address"),
127
- children: /* @__PURE__ */ f("div", {
135
+ }) : /* @__PURE__ */ p(r, {
136
+ title: a("auth.emailVerify.failedTitle", "Verification failed"),
137
+ subtitle: a("auth.emailVerify.failedSubtitle", "We couldn't verify your email address"),
138
+ children: /* @__PURE__ */ m("div", {
128
139
  className: "flex flex-col items-center justify-center py-6",
129
140
  children: [
130
- /* @__PURE__ */ d("div", {
141
+ /* @__PURE__ */ p("div", {
131
142
  className: "size-20 rounded-full bg-[var(--color-status-error-bg-subtle)] flex items-center justify-center mb-6",
132
- children: /* @__PURE__ */ d("svg", {
143
+ children: /* @__PURE__ */ p("svg", {
133
144
  className: "size-10 text-[var(--color-status-error-text)]",
134
145
  fill: "none",
135
146
  viewBox: "0 0 24 24",
136
147
  stroke: "currentColor",
137
- children: /* @__PURE__ */ d("path", {
148
+ children: /* @__PURE__ */ p("path", {
138
149
  strokeLinecap: "round",
139
150
  strokeLinejoin: "round",
140
151
  strokeWidth: 2,
@@ -142,35 +153,35 @@ function _() {
142
153
  })
143
154
  })
144
155
  }),
145
- /* @__PURE__ */ d("p", {
156
+ /* @__PURE__ */ p("p", {
146
157
  className: "text-center text-[var(--color-text-secondary)] mb-8",
147
- children: _("auth.emailVerify.invalidLink", "The verification link is invalid or has expired. Please request a new verification email.")
158
+ children: a("auth.emailVerify.invalidLink", "The verification link is invalid or has expired. Please request a new verification email.")
148
159
  }),
149
- k ? /* @__PURE__ */ d("div", {
160
+ A ? /* @__PURE__ */ p("div", {
150
161
  className: "w-full p-4 rounded-xl bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)] text-center mb-4",
151
- children: /* @__PURE__ */ d("p", {
162
+ children: /* @__PURE__ */ p("p", {
152
163
  className: "text-sm text-[var(--color-status-success-text)]",
153
- children: _("auth.emailVerify.emailSent", "Verification email sent! Please check your inbox.")
164
+ children: a("auth.emailVerify.emailSent", "Verification email sent! Please check your inbox.")
154
165
  })
155
- }) : /* @__PURE__ */ d(p, {
166
+ }) : /* @__PURE__ */ p(h, {
156
167
  type: "button",
157
- onClick: P,
158
- disabled: D,
168
+ onClick: z,
169
+ disabled: O,
159
170
  variant: "default",
160
171
  size: "lg",
161
172
  className: "mb-4 w-full font-semibold",
162
- children: D ? /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d(i, { className: "size-5 animate-spin" }), /* @__PURE__ */ d("span", { children: _("auth.emailVerify.sending", "Sending…") })] }) : _("auth.emailVerify.resend", "Resend verification email")
173
+ children: O ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(i, { className: "size-5 animate-spin" }), /* @__PURE__ */ p("span", { children: a("auth.emailVerify.sending", "Sending…") })] }) : a("auth.emailVerify.resend", "Resend verification email")
163
174
  }),
164
- /* @__PURE__ */ d("button", {
175
+ /* @__PURE__ */ p("button", {
165
176
  type: "button",
166
- onClick: I,
177
+ onClick: V,
167
178
  className: "w-full py-3 px-4 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] font-medium hover:bg-[var(--color-bg-sunken)] transition-all",
168
- children: _("auth.emailVerify.backToSignIn", "Back to sign in")
179
+ children: a("auth.emailVerify.backToSignIn", "Back to sign in")
169
180
  })
170
181
  ]
171
182
  })
172
183
  });
173
184
  }
174
- export { _ as EmailVerifyPage };
185
+ export { y as EmailVerifyPage };
175
186
 
176
187
  //# sourceMappingURL=EmailVerifyPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EmailVerifyPage.js","names":["_Fragment","REDIRECT_DELAY","pendingVerifications","navigateToLogin","baseUrl","url","email","EmailVerifyPage","tr","useTr","searchParams","useSearchParams","token","urlEmail","useAuthOperations","user","useAuthStore","state","status","setStatus","useState","verifiedEmailRef","useRef","isResending","setIsResending","resendSuccess","setResendSuccess","countdown","setCountdown","verificationRef","useEffect","request","verifyEmail","active","result","timer","prev","handleResend","resendEmail","resendVerification","err","handleContinueToLogin","useCallback","handleBackToLogin","AuthLayout","SpinnerIcon","Button","Fragment"],"sources":["../../../src/auth/pages/EmailVerifyPage.tsx"],"sourcesContent":["import { useEffect, useState, useCallback, useRef } from \"react\";\nimport { useTr } from \"../../shared/hooks/useTr\";\nimport { useSearchParams } from \"react-router\";\nimport { useAuthOperations } from \"../hooks/useAuthOperations\";\nimport { useAuthStore } from \"../store/authStore\";\nimport { AuthLayout } from \"../components/AuthLayout\";\nimport { Button } from \"@burdenoff/fe-libs/button\";\nimport { SpinnerIcon } from \"../components/AuthIcons\";\n\nconst REDIRECT_DELAY = 5; // seconds\ntype VerificationRequest = ReturnType<\n ReturnType<typeof useAuthOperations>[\"verifyEmail\"]\n>;\n// Share only pending work across remounts; never persist bearer tokens.\nconst pendingVerifications = new Map<string, VerificationRequest>();\n\n/**\n * Navigate to login page with optional email pre-fill\n * Uses window.location.href for reliable navigation (works in new tabs)\n */\nfunction navigateToLogin(email?: string) {\n const baseUrl = \"/auth/login\";\n const url = email ? `${baseUrl}?email=${encodeURIComponent(email)}` : baseUrl;\n window.location.href = url;\n}\n\n/**\n * Email verification page with professional design\n */\nexport function EmailVerifyPage() {\n const tr = useTr();\n\n const [searchParams] = useSearchParams();\n const token = searchParams.get(\"token\");\n const urlEmail = searchParams.get(\"email\");\n const { verifyEmail, resendVerification } = useAuthOperations();\n const user = useAuthStore((state) => state.user);\n const [status, setStatus] = useState<\"verifying\" | \"success\" | \"error\">(\n \"verifying\",\n );\n const verifiedEmailRef = useRef<string | undefined>(urlEmail || undefined);\n const [isResending, setIsResending] = useState(false);\n const [resendSuccess, setResendSuccess] = useState(false);\n const [countdown, setCountdown] = useState(REDIRECT_DELAY);\n\n const verificationRef = useRef<{\n token: string;\n request: VerificationRequest;\n } | null>(null);\n\n useEffect(() => {\n if (!token) return;\n try {\n // Remove the marker left by older versions, without touching other data.\n window.sessionStorage.removeItem(`auth:verifyEmail:inflight:${token}`);\n } catch {\n // Verification must also work when browser storage is unavailable.\n }\n\n if (verificationRef.current?.token !== token) {\n let request = pendingVerifications.get(token);\n if (!request) {\n request = Promise.resolve()\n .then(() => verifyEmail(token))\n .finally(() => pendingVerifications.delete(token));\n pendingVerifications.set(token, request);\n }\n verificationRef.current = { token, request };\n setStatus(\"verifying\");\n }\n\n let active = true;\n verificationRef.current.request\n .then((result) => {\n if (!active) return;\n if (result.success) {\n setStatus(\"success\");\n if (result.email) verifiedEmailRef.current = result.email;\n } else {\n setStatus(\"error\");\n }\n })\n .catch(() => {\n if (active) setStatus(\"error\");\n });\n return () => {\n active = false;\n };\n }, [token, verifyEmail]);\n\n // Auto-redirect countdown after successful verification\n useEffect(() => {\n if (status !== \"success\") return;\n\n const timer = setInterval(() => {\n setCountdown((prev) => {\n if (prev <= 1) {\n clearInterval(timer);\n navigateToLogin(verifiedEmailRef.current);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(timer);\n }, [status]);\n\n const handleResend = async () => {\n const resendEmail = urlEmail || user?.email;\n if (!resendEmail) {\n console.error(\"No email available for resend\");\n return;\n }\n setIsResending(true);\n try {\n await resendVerification(resendEmail);\n setResendSuccess(true);\n } catch (err) {\n console.error(\"Failed to resend verification:\", err);\n } finally {\n setIsResending(false);\n }\n };\n\n const handleContinueToLogin = useCallback(() => {\n navigateToLogin(verifiedEmailRef.current);\n }, []);\n\n const handleBackToLogin = useCallback(() => {\n navigateToLogin();\n }, []);\n\n if (status === \"verifying\") {\n return (\n <AuthLayout\n title={tr(\"auth.emailVerify.verifyingTitle\", \"Verifying your email\")}\n subtitle={tr(\n \"auth.emailVerify.verifyingSubtitle\",\n \"Please wait while we confirm your email address\",\n )}\n >\n {/* Loading Spinner */}\n <div className=\"flex flex-col items-center justify-center py-12\">\n <div className=\"size-16 rounded-full bg-[var(--color-bg-accent)] flex items-center justify-center mb-6\">\n <SpinnerIcon className=\"size-8 text-[var(--color-text-link)] animate-spin\" />\n </div>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\"auth.emailVerify.moment\", \"This will only take a moment...\")}\n </p>\n </div>\n </AuthLayout>\n );\n }\n\n if (status === \"success\") {\n return (\n <AuthLayout\n title={tr(\"auth.emailVerify.verifiedTitle\", \"Email verified!\")}\n subtitle={tr(\n \"auth.emailVerify.verifiedSubtitle\",\n \"Your email address has been confirmed\",\n )}\n >\n {/* Success Icon */}\n <div className=\"flex flex-col items-center justify-center py-6\">\n <div className=\"size-20 rounded-full bg-[var(--color-status-success-bg-subtle)] flex items-center justify-center mb-6\">\n <svg\n className=\"size-10 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=\"M5 13l4 4L19 7\"\n />\n </svg>\n </div>\n\n <p className=\"text-center text-[var(--color-text-secondary)] mb-6\">\n {tr(\n \"auth.emailVerify.successMessage\",\n \"Your email has been successfully verified. You can now sign in to access all features.\",\n )}\n </p>\n\n <p className=\"text-center text-sm text-[var(--color-text-tertiary)] mb-6\">\n {tr(\"auth.emailVerify.redirecting\", \"Redirecting to sign in in\")}{\" \"}\n <span className=\"font-semibold text-[var(--color-text-primary)]\">\n {countdown}\n </span>{\" \"}\n {tr(\"auth.emailVerify.seconds\", \"seconds...\")}\n </p>\n\n <Button\n type=\"button\"\n onClick={handleContinueToLogin}\n variant=\"default\"\n size=\"lg\"\n className=\"w-full font-semibold\"\n >\n {tr(\"auth.emailVerify.continueSignIn\", \"Continue to sign in now\")}\n </Button>\n </div>\n </AuthLayout>\n );\n }\n\n // Error state\n return (\n <AuthLayout\n title={tr(\"auth.emailVerify.failedTitle\", \"Verification failed\")}\n subtitle={tr(\n \"auth.emailVerify.failedSubtitle\",\n \"We couldn't verify your email address\",\n )}\n >\n <div className=\"flex flex-col items-center justify-center py-6\">\n {/* Error Icon */}\n <div className=\"size-20 rounded-full bg-[var(--color-status-error-bg-subtle)] flex items-center justify-center mb-6\">\n <svg\n className=\"size-10 text-[var(--color-status-error-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=\"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\n <p className=\"text-center text-[var(--color-text-secondary)] mb-8\">\n {tr(\n \"auth.emailVerify.invalidLink\",\n \"The verification link is invalid or has expired. Please request a new verification email.\",\n )}\n </p>\n\n {resendSuccess ? (\n <div className=\"w-full p-4 rounded-xl bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)] text-center mb-4\">\n <p className=\"text-sm text-[var(--color-status-success-text)]\">\n {tr(\n \"auth.emailVerify.emailSent\",\n \"Verification email sent! Please check your inbox.\",\n )}\n </p>\n </div>\n ) : (\n <Button\n type=\"button\"\n onClick={handleResend}\n disabled={isResending}\n variant=\"default\"\n size=\"lg\"\n className=\"mb-4 w-full font-semibold\"\n >\n {isResending ? (\n <>\n <SpinnerIcon className=\"size-5 animate-spin\" />\n <span>{tr(\"auth.emailVerify.sending\", \"Sending…\")}</span>\n </>\n ) : (\n tr(\"auth.emailVerify.resend\", \"Resend verification email\")\n )}\n </Button>\n )}\n\n <button\n type=\"button\"\n onClick={handleBackToLogin}\n className=\"w-full py-3 px-4 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] font-medium hover:bg-[var(--color-bg-sunken)] transition-all\"\n >\n {tr(\"auth.emailVerify.backToSignIn\", \"Back to sign in\")}\n </button>\n </div>\n </AuthLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"EmailVerifyPage.js","names":["_Fragment","REDIRECT_DELAY","pendingVerifications","navigateToLogin","authPathWithReturnTo","returnTo","email","EmailVerifyPage","tr","useTr","searchParams","useSearchParams","token","urlEmail","useAuthOperations","user","useAuthStore","state","status","setStatus","useState","verifiedEmailRef","useRef","isResending","setIsResending","resendSuccess","setResendSuccess","countdown","setCountdown","verificationRef","request","verifyEmail","active","result","returnToRef","pendingReturnTo","useCallback","consumeReturnTo","redirectedRef","goToLogin","useEffect","timer","prev","handleResend","resendEmail","resendVerification","err","handleContinueToLogin","handleBackToLogin","AuthLayout","SpinnerIcon","Button","Fragment"],"sources":["../../../src/auth/pages/EmailVerifyPage.tsx"],"sourcesContent":["import { useEffect, useState, useCallback, useRef } from \"react\";\nimport { useTr } from \"../../shared/hooks/useTr\";\nimport { useSearchParams } from \"react-router\";\nimport { useAuthOperations } from \"../hooks/useAuthOperations\";\nimport { useAuthStore } from \"../store/authStore\";\nimport { AuthLayout } from \"../components/AuthLayout\";\nimport { Button } from \"@burdenoff/fe-libs/button\";\nimport { SpinnerIcon } from \"../components/AuthIcons\";\nimport {\n authPathWithReturnTo,\n consumeReturnTo,\n} from \"../utils/pendingReturnTo\";\n\nconst REDIRECT_DELAY = 5; // seconds\ntype VerificationRequest = ReturnType<\n ReturnType<typeof useAuthOperations>[\"verifyEmail\"]\n>;\n// Share only pending work across remounts; never persist bearer tokens.\nconst pendingVerifications = new Map<string, VerificationRequest>();\n\n/**\n * Navigate to login page with optional email pre-fill.\n * Uses window.location.href for reliable navigation (works in new tabs).\n * Carries the destination the visitor chose before signing up (for example\n * the developer portal from \"Build on Workspaces\") as `returnTo`, which the\n * login page validates and honours (BOFF-10636).\n */\nfunction navigateToLogin(email: string | undefined, returnTo: string | null) {\n window.location.href = authPathWithReturnTo(\"/auth/login\", returnTo, email);\n}\n\n/**\n * Email verification page with professional design\n */\nexport function EmailVerifyPage() {\n const tr = useTr();\n\n const [searchParams] = useSearchParams();\n const token = searchParams.get(\"token\");\n const urlEmail = searchParams.get(\"email\");\n const { verifyEmail, resendVerification } = useAuthOperations();\n const user = useAuthStore((state) => state.user);\n const [status, setStatus] = useState<\"verifying\" | \"success\" | \"error\">(\n \"verifying\",\n );\n const verifiedEmailRef = useRef<string | undefined>(urlEmail || undefined);\n const [isResending, setIsResending] = useState(false);\n const [resendSuccess, setResendSuccess] = useState(false);\n const [countdown, setCountdown] = useState(REDIRECT_DELAY);\n\n const verificationRef = useRef<{\n token: string;\n request: VerificationRequest;\n } | null>(null);\n\n useEffect(() => {\n if (!token) return;\n try {\n // Remove the marker left by older versions, without touching other data.\n window.sessionStorage.removeItem(`auth:verifyEmail:inflight:${token}`);\n } catch {\n // Verification must also work when browser storage is unavailable.\n }\n\n if (verificationRef.current?.token !== token) {\n let request = pendingVerifications.get(token);\n if (!request) {\n request = Promise.resolve()\n .then(() => verifyEmail(token))\n .finally(() => pendingVerifications.delete(token));\n pendingVerifications.set(token, request);\n }\n verificationRef.current = { token, request };\n setStatus(\"verifying\");\n }\n\n let active = true;\n verificationRef.current.request\n .then((result) => {\n if (!active) return;\n if (result.success) {\n setStatus(\"success\");\n if (result.email) verifiedEmailRef.current = result.email;\n } else {\n setStatus(\"error\");\n }\n })\n .catch(() => {\n if (active) setStatus(\"error\");\n });\n return () => {\n active = false;\n };\n }, [token, verifyEmail]);\n\n // The destination remembered at sign-up is read once and kept in a ref, so\n // every way out of this page (auto-redirect, either button) carries the\n // same value, and StrictMode's repeated effects cannot consume it twice.\n const returnToRef = useRef<string | null | undefined>(undefined);\n const pendingReturnTo = useCallback((): string | null => {\n if (returnToRef.current === undefined) {\n returnToRef.current = consumeReturnTo();\n }\n return returnToRef.current;\n }, []);\n const redirectedRef = useRef(false);\n const goToLogin = useCallback(\n (email?: string) => {\n if (redirectedRef.current) return;\n redirectedRef.current = true;\n navigateToLogin(email, pendingReturnTo());\n },\n [pendingReturnTo],\n );\n\n // Auto-redirect countdown after successful verification. The interval only\n // counts down (state updaters stay pure); the redirect happens in the\n // effect below once the count reaches zero.\n useEffect(() => {\n if (status !== \"success\") return;\n pendingReturnTo();\n\n const timer = setInterval(() => {\n setCountdown((prev) => (prev <= 1 ? 0 : prev - 1));\n }, 1000);\n\n return () => clearInterval(timer);\n }, [status, pendingReturnTo]);\n\n useEffect(() => {\n if (status === \"success\" && countdown === 0) {\n goToLogin(verifiedEmailRef.current);\n }\n }, [status, countdown, goToLogin]);\n\n const handleResend = async () => {\n const resendEmail = urlEmail || user?.email;\n if (!resendEmail) {\n console.error(\"No email available for resend\");\n return;\n }\n setIsResending(true);\n try {\n await resendVerification(resendEmail);\n setResendSuccess(true);\n } catch (err) {\n console.error(\"Failed to resend verification:\", err);\n } finally {\n setIsResending(false);\n }\n };\n\n const handleContinueToLogin = useCallback(() => {\n goToLogin(verifiedEmailRef.current);\n }, [goToLogin]);\n\n const handleBackToLogin = useCallback(() => {\n goToLogin();\n }, [goToLogin]);\n\n if (status === \"verifying\") {\n return (\n <AuthLayout\n title={tr(\"auth.emailVerify.verifyingTitle\", \"Verifying your email\")}\n subtitle={tr(\n \"auth.emailVerify.verifyingSubtitle\",\n \"Please wait while we confirm your email address\",\n )}\n >\n {/* Loading Spinner */}\n <div className=\"flex flex-col items-center justify-center py-12\">\n <div className=\"size-16 rounded-full bg-[var(--color-bg-accent)] flex items-center justify-center mb-6\">\n <SpinnerIcon className=\"size-8 text-[var(--color-text-link)] animate-spin\" />\n </div>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\"auth.emailVerify.moment\", \"This will only take a moment...\")}\n </p>\n </div>\n </AuthLayout>\n );\n }\n\n if (status === \"success\") {\n return (\n <AuthLayout\n title={tr(\"auth.emailVerify.verifiedTitle\", \"Email verified!\")}\n subtitle={tr(\n \"auth.emailVerify.verifiedSubtitle\",\n \"Your email address has been confirmed\",\n )}\n >\n {/* Success Icon */}\n <div className=\"flex flex-col items-center justify-center py-6\">\n <div className=\"size-20 rounded-full bg-[var(--color-status-success-bg-subtle)] flex items-center justify-center mb-6\">\n <svg\n className=\"size-10 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=\"M5 13l4 4L19 7\"\n />\n </svg>\n </div>\n\n <p className=\"text-center text-[var(--color-text-secondary)] mb-6\">\n {tr(\n \"auth.emailVerify.successMessage\",\n \"Your email has been successfully verified. You can now sign in to access all features.\",\n )}\n </p>\n\n <p className=\"text-center text-sm text-[var(--color-text-tertiary)] mb-6\">\n {tr(\"auth.emailVerify.redirecting\", \"Redirecting to sign in in\")}{\" \"}\n <span className=\"font-semibold text-[var(--color-text-primary)]\">\n {countdown}\n </span>{\" \"}\n {tr(\"auth.emailVerify.seconds\", \"seconds...\")}\n </p>\n\n <Button\n type=\"button\"\n onClick={handleContinueToLogin}\n variant=\"default\"\n size=\"lg\"\n className=\"w-full font-semibold\"\n >\n {tr(\"auth.emailVerify.continueSignIn\", \"Continue to sign in now\")}\n </Button>\n </div>\n </AuthLayout>\n );\n }\n\n // Error state\n return (\n <AuthLayout\n title={tr(\"auth.emailVerify.failedTitle\", \"Verification failed\")}\n subtitle={tr(\n \"auth.emailVerify.failedSubtitle\",\n \"We couldn't verify your email address\",\n )}\n >\n <div className=\"flex flex-col items-center justify-center py-6\">\n {/* Error Icon */}\n <div className=\"size-20 rounded-full bg-[var(--color-status-error-bg-subtle)] flex items-center justify-center mb-6\">\n <svg\n className=\"size-10 text-[var(--color-status-error-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=\"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\n <p className=\"text-center text-[var(--color-text-secondary)] mb-8\">\n {tr(\n \"auth.emailVerify.invalidLink\",\n \"The verification link is invalid or has expired. Please request a new verification email.\",\n )}\n </p>\n\n {resendSuccess ? (\n <div className=\"w-full p-4 rounded-xl bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)] text-center mb-4\">\n <p className=\"text-sm text-[var(--color-status-success-text)]\">\n {tr(\n \"auth.emailVerify.emailSent\",\n \"Verification email sent! Please check your inbox.\",\n )}\n </p>\n </div>\n ) : (\n <Button\n type=\"button\"\n onClick={handleResend}\n disabled={isResending}\n variant=\"default\"\n size=\"lg\"\n className=\"mb-4 w-full font-semibold\"\n >\n {isResending ? (\n <>\n <SpinnerIcon className=\"size-5 animate-spin\" />\n <span>{tr(\"auth.emailVerify.sending\", \"Sending…\")}</span>\n </>\n ) : (\n tr(\"auth.emailVerify.resend\", \"Resend verification email\")\n )}\n </Button>\n )}\n\n <button\n type=\"button\"\n onClick={handleBackToLogin}\n className=\"w-full py-3 px-4 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] font-medium hover:bg-[var(--color-bg-sunken)] transition-all\"\n >\n {tr(\"auth.emailVerify.backToSignIn\", \"Back to sign in\")}\n </button>\n </div>\n </AuthLayout>\n );\n}\n"],"mappings":"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"}