@mesob/auth-react 0.0.7 → 0.1.0

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 (75) hide show
  1. package/dist/components/auth/auth-page-layout.d.ts +1 -3
  2. package/dist/components/auth/auth-page-layout.js +1 -17
  3. package/dist/components/auth/auth-page-layout.js.map +1 -1
  4. package/dist/components/auth/countdown.js +70 -9
  5. package/dist/components/auth/countdown.js.map +1 -1
  6. package/dist/components/auth/forgot-password.js +101 -35
  7. package/dist/components/auth/forgot-password.js.map +1 -1
  8. package/dist/components/auth/pages/forgot-password-page.d.ts +2 -13
  9. package/dist/components/auth/pages/forgot-password-page.js +198 -126
  10. package/dist/components/auth/pages/forgot-password-page.js.map +1 -1
  11. package/dist/components/auth/pages/reset-password-page.d.ts +1 -12
  12. package/dist/components/auth/pages/reset-password-page.js +288 -200
  13. package/dist/components/auth/pages/reset-password-page.js.map +1 -1
  14. package/dist/components/auth/pages/sign-in-page.d.ts +1 -12
  15. package/dist/components/auth/pages/sign-in-page.js +352 -230
  16. package/dist/components/auth/pages/sign-in-page.js.map +1 -1
  17. package/dist/components/auth/pages/sign-up-page.d.ts +1 -11
  18. package/dist/components/auth/pages/sign-up-page.js +310 -216
  19. package/dist/components/auth/pages/sign-up-page.js.map +1 -1
  20. package/dist/components/auth/pages/verify-email-page.d.ts +2 -12
  21. package/dist/components/auth/pages/verify-email-page.js +203 -135
  22. package/dist/components/auth/pages/verify-email-page.js.map +1 -1
  23. package/dist/components/auth/pages/verify-phone-page.d.ts +1 -11
  24. package/dist/components/auth/pages/verify-phone-page.js +206 -137
  25. package/dist/components/auth/pages/verify-phone-page.js.map +1 -1
  26. package/dist/components/auth/reset-password-form.d.ts +1 -1
  27. package/dist/components/auth/reset-password-form.js +188 -106
  28. package/dist/components/auth/reset-password-form.js.map +1 -1
  29. package/dist/components/auth/sign-in.d.ts +3 -3
  30. package/dist/components/auth/sign-in.js +228 -109
  31. package/dist/components/auth/sign-in.js.map +1 -1
  32. package/dist/components/auth/sign-up.js +210 -122
  33. package/dist/components/auth/sign-up.js.map +1 -1
  34. package/dist/components/auth/verification-form.d.ts +1 -1
  35. package/dist/components/auth/verification-form.js +101 -53
  36. package/dist/components/auth/verification-form.js.map +1 -1
  37. package/dist/components/error-boundary.d.ts +27 -0
  38. package/dist/components/error-boundary.js +49 -0
  39. package/dist/components/error-boundary.js.map +1 -0
  40. package/dist/components/iam/permissions/permissions-page.d.ts +5 -0
  41. package/dist/components/iam/permissions/permissions-page.js +201 -0
  42. package/dist/components/iam/permissions/permissions-page.js.map +1 -0
  43. package/dist/components/iam/roles/roles-page.d.ts +5 -0
  44. package/dist/components/iam/roles/roles-page.js +199 -0
  45. package/dist/components/iam/roles/roles-page.js.map +1 -0
  46. package/dist/components/iam/sessions/sessions-page.d.ts +5 -0
  47. package/dist/components/iam/sessions/sessions-page.js +202 -0
  48. package/dist/components/iam/sessions/sessions-page.js.map +1 -0
  49. package/dist/components/iam/tenants/tenants-page.d.ts +5 -0
  50. package/dist/components/iam/tenants/tenants-page.js +202 -0
  51. package/dist/components/iam/tenants/tenants-page.js.map +1 -0
  52. package/dist/components/iam/users/users-page.d.ts +5 -0
  53. package/dist/components/iam/users/users-page.js +211 -0
  54. package/dist/components/iam/users/users-page.js.map +1 -0
  55. package/dist/components/profile/profile-page.d.ts +8 -0
  56. package/dist/components/profile/profile-page.js +163 -0
  57. package/dist/components/profile/profile-page.js.map +1 -0
  58. package/dist/components/shared/data-table/data-table.d.ts +22 -0
  59. package/dist/components/shared/data-table/data-table.js +85 -0
  60. package/dist/components/shared/data-table/data-table.js.map +1 -0
  61. package/dist/components/skeletons/auth-form-skeleton.d.ts +5 -0
  62. package/dist/components/skeletons/auth-form-skeleton.js +32 -0
  63. package/dist/components/skeletons/auth-form-skeleton.js.map +1 -0
  64. package/dist/components/skeletons/profile-skeleton.d.ts +5 -0
  65. package/dist/components/skeletons/profile-skeleton.js +33 -0
  66. package/dist/components/skeletons/profile-skeleton.js.map +1 -0
  67. package/dist/components/skeletons/table-skeleton.d.ts +9 -0
  68. package/dist/components/skeletons/table-skeleton.js +39 -0
  69. package/dist/components/skeletons/table-skeleton.js.map +1 -0
  70. package/dist/handle-error-BqDMxnQZ.d.ts +8 -0
  71. package/dist/index.d.ts +75 -208
  72. package/dist/index.js +2091 -1057
  73. package/dist/index.js.map +1 -1
  74. package/package.json +9 -3
  75. package/dist/handle-error-H0iqQxJ5.d.ts +0 -6
@@ -1,40 +1,75 @@
1
1
  "use client";
2
2
 
3
3
  // src/components/auth/pages/verify-phone-page.tsx
4
- import { useTranslations as useTranslations3 } from "next-intl";
5
- import { useState as useState3 } from "react";
6
-
7
- // src/context/auth-provider.tsx
8
4
  import {
9
- createContext,
10
- useCallback,
11
- useContext,
12
- useEffect,
13
- useState
14
- } from "react";
5
+ Alert,
6
+ AlertDescription,
7
+ AlertTitle
8
+ } from "@mesob/ui/components/alert";
9
+ import { toast } from "@mesob/ui/components/sonner";
10
+ import { IconAlertCircle } from "@tabler/icons-react";
11
+ import { useEffect as useEffect3, useState as useState3 } from "react";
12
+
13
+ // src/lib/translations.ts
14
+ function createTranslator(messages, namespace) {
15
+ return (key, params) => {
16
+ const fullKey = namespace ? `${namespace}.${key}` : key;
17
+ const keys = fullKey.split(".");
18
+ let value = messages;
19
+ for (const k of keys) {
20
+ if (value && typeof value === "object" && value !== null) {
21
+ value = value[k];
22
+ } else {
23
+ return fullKey;
24
+ }
25
+ }
26
+ if (typeof value !== "string") {
27
+ return fullKey;
28
+ }
29
+ if (params) {
30
+ return value.replace(
31
+ /\{(\w+)\}/g,
32
+ (_, param) => String(params[param] ?? `{${param}}`)
33
+ );
34
+ }
35
+ return value;
36
+ };
37
+ }
38
+
39
+ // src/provider.tsx
40
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
41
+ import { deepmerge } from "deepmerge-ts";
42
+ import createFetchClient from "openapi-fetch";
43
+ import createClient from "openapi-react-query";
44
+ import { createContext, useContext, useEffect, useState } from "react";
15
45
  import { jsx } from "react/jsx-runtime";
16
- var AuthContext = createContext(null);
17
- var useAuth = () => {
18
- const context = useContext(AuthContext);
46
+ var SessionContext = createContext(null);
47
+ var ApiContext = createContext(null);
48
+ var ConfigContext = createContext(null);
49
+ var queryClient = new QueryClient({
50
+ defaultOptions: {
51
+ queries: {
52
+ staleTime: 1e3 * 60 * 5,
53
+ gcTime: 1e3 * 60 * 10,
54
+ retry: 1,
55
+ refetchOnWindowFocus: false
56
+ }
57
+ }
58
+ });
59
+ function useApi() {
60
+ const context = useContext(ApiContext);
19
61
  if (!context) {
20
- throw new Error("useAuth must be used within AuthProvider");
62
+ throw new Error("useApi must be used within MesobAuthProvider");
21
63
  }
22
64
  return context;
23
- };
24
-
25
- // src/client.ts
26
- var AuthError = class extends Error {
27
- code;
28
- status;
29
- details;
30
- constructor(message, code, status, details) {
31
- super(message);
32
- this.name = "AuthError";
33
- this.code = code;
34
- this.status = status;
35
- this.details = details;
65
+ }
66
+ function useConfig() {
67
+ const context = useContext(ConfigContext);
68
+ if (!context) {
69
+ throw new Error("useConfig must be used within MesobAuthProvider");
36
70
  }
37
- };
71
+ return context;
72
+ }
38
73
 
39
74
  // src/constants/auth.error.codes.ts
40
75
  var AUTH_ERROR_MAPPING = {
@@ -86,71 +121,67 @@ var AUTH_ERROR_MAPPING = {
86
121
  var validCodes = Object.keys(AUTH_ERROR_MAPPING);
87
122
 
88
123
  // src/utils/handle-error.ts
89
- var handleError = (err, setError, t) => {
90
- if (err instanceof AuthError) {
91
- let errorCode = "";
92
- if (err.code && validCodes.includes(err.code)) {
93
- errorCode = err.code;
94
- } else if (err.message) {
95
- const messageUpper = err.message.toUpperCase().trim();
96
- if (validCodes.includes(messageUpper)) {
97
- errorCode = messageUpper;
98
- }
99
- }
100
- if (errorCode && AUTH_ERROR_MAPPING[errorCode]) {
101
- const mapping = AUTH_ERROR_MAPPING[errorCode];
102
- setError({
103
- title: mapping.title,
104
- description: mapping.description
105
- });
106
- return;
124
+ function isAuthError(err) {
125
+ return typeof err === "object" && err !== null && "message" in err && typeof err.message === "string";
126
+ }
127
+ function extractErrorCode(err) {
128
+ if (err.code && validCodes.includes(err.code)) {
129
+ return err.code;
130
+ }
131
+ if (err.message) {
132
+ const messageUpper = err.message.toUpperCase().trim();
133
+ if (validCodes.includes(messageUpper)) {
134
+ return messageUpper;
107
135
  }
136
+ }
137
+ return "";
138
+ }
139
+ function handleAuthError(err, setError, t) {
140
+ const errorCode = extractErrorCode(err);
141
+ if (errorCode && AUTH_ERROR_MAPPING[errorCode]) {
142
+ const mapping = AUTH_ERROR_MAPPING[errorCode];
108
143
  setError({
109
- title: t("errors.fallback"),
110
- // or 'Error'
111
- description: err.message || t("errors.fallback")
144
+ title: mapping.title,
145
+ description: mapping.description
112
146
  });
147
+ return;
148
+ }
149
+ setError({
150
+ title: t("errors.fallback"),
151
+ description: err.message || t("errors.fallback")
152
+ });
153
+ }
154
+ function handleGenericError(err, setError, t) {
155
+ const message = err instanceof Error ? err.message : t("errors.fallback");
156
+ setError({
157
+ title: "Error",
158
+ description: message
159
+ });
160
+ }
161
+ var handleError = (err, setError, t) => {
162
+ if (isAuthError(err)) {
163
+ handleAuthError(err, setError, t);
113
164
  } else {
114
- const message = err instanceof Error ? err.message : t("errors.fallback");
115
- setError({
116
- title: "Error",
117
- description: message
118
- });
165
+ handleGenericError(err, setError, t);
119
166
  }
120
167
  };
121
168
 
122
169
  // src/components/auth/auth-page-layout.tsx
123
- import {
124
- Alert,
125
- AlertDescription,
126
- AlertTitle
127
- } from "@mesob/ui/components/alert";
128
- import { IconAlertCircle } from "@tabler/icons-react";
129
170
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
130
171
  var AuthPageLayout = ({
131
172
  title,
132
173
  description,
133
174
  children,
134
- error,
135
175
  footer,
136
176
  logoImage
137
177
  }) => {
138
- const errorContent = error ? (
139
- // biome-ignore lint/style/noNestedTernary: <explanation>
140
- typeof error === "string" ? { title: "Error", description: error } : error
141
- ) : null;
142
178
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
143
- /* @__PURE__ */ jsx2("div", { className: "flex size-8 mb-6 w-full items-center justify-center rounded-md", children: /* @__PURE__ */ jsx2("img", { src: logoImage || "", alt: "Jiret", width: 42, height: 42 }) }),
179
+ /* @__PURE__ */ jsx2("div", { className: "flex size-8 mb-6 w-full items-center justify-center rounded-md", children: /* @__PURE__ */ jsx2("img", { src: logoImage || "", alt: "Mesob", width: 42, height: 42 }) }),
144
180
  /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
145
181
  /* @__PURE__ */ jsx2("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
146
182
  description && /* @__PURE__ */ jsx2("p", { className: "mt-2 text-sm text-muted-foreground", children: description })
147
183
  ] }),
148
184
  children,
149
- errorContent && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
150
- /* @__PURE__ */ jsx2(IconAlertCircle, { className: "h-4 w-4" }),
151
- /* @__PURE__ */ jsx2(AlertTitle, { children: errorContent.title }),
152
- /* @__PURE__ */ jsx2(AlertDescription, { children: errorContent.description })
153
- ] }),
154
185
  /* @__PURE__ */ jsx2("div", { className: "mt-2 w-full", children: footer && /* @__PURE__ */ jsx2("div", { className: "w-full text-center text-sm text-muted-foreground", children: footer }) })
155
186
  ] });
156
187
  };
@@ -158,28 +189,25 @@ var AuthPageLayout = ({
158
189
  // src/components/auth/verification-form.tsx
159
190
  import { zodResolver } from "@hookform/resolvers/zod";
160
191
  import { Button as Button2 } from "@mesob/ui/components/button";
161
- import {
162
- Form,
163
- FormControl,
164
- FormField,
165
- FormItem,
166
- FormMessage
167
- } from "@mesob/ui/components/form";
192
+ import { Field, FieldError, FieldGroup } from "@mesob/ui/components/field";
168
193
  import {
169
194
  InputOTP,
170
195
  InputOTPGroup,
171
196
  InputOTPSlot
172
197
  } from "@mesob/ui/components/input-otp";
173
198
  import { Spinner as Spinner2 } from "@mesob/ui/components/spinner";
174
- import { useTranslations as useTranslations2 } from "next-intl";
175
- import { useMemo } from "react";
176
- import { useForm } from "react-hook-form";
199
+ import { Controller, useForm } from "react-hook-form";
177
200
  import { z } from "zod";
178
201
 
202
+ // src/hooks/use-translator.ts
203
+ function useTranslator(namespace) {
204
+ const { config } = useConfig();
205
+ return createTranslator(config.messages || {}, namespace);
206
+ }
207
+
179
208
  // src/components/auth/countdown.tsx
180
209
  import { Button } from "@mesob/ui/components/button";
181
210
  import { Spinner } from "@mesob/ui/components/spinner";
182
- import { useTranslations } from "next-intl";
183
211
  import { useEffect as useEffect2, useState as useState2 } from "react";
184
212
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
185
213
  var Countdown = ({
@@ -187,7 +215,7 @@ var Countdown = ({
187
215
  onResend,
188
216
  resending = false
189
217
  }) => {
190
- const t = useTranslations("Common");
218
+ const t = useTranslator("Common");
191
219
  const [seconds, setSeconds] = useState2(initialSeconds);
192
220
  const [isResending, setIsResending] = useState2(false);
193
221
  useEffect2(() => {
@@ -234,32 +262,32 @@ var Countdown = ({
234
262
 
235
263
  // src/components/auth/verification-form.tsx
236
264
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
265
+ var verificationSchema = (t) => z.object({
266
+ code: z.string().length(6, t("form.codeLength"))
267
+ });
237
268
  var VerificationForm = ({
238
269
  onSubmit,
239
270
  onResend,
240
271
  isLoading = false
241
272
  }) => {
242
- const t = useTranslations2("Auth.verification");
243
- const verificationSchema = useMemo(
244
- () => z.object({
245
- code: z.string().length(6, t("form.codeLength"))
246
- }),
247
- [t]
248
- );
273
+ const t = useTranslator("Auth.verification");
249
274
  const form = useForm({
250
- resolver: zodResolver(verificationSchema),
275
+ resolver: zodResolver(verificationSchema(t)),
251
276
  defaultValues: {
252
277
  code: ""
253
278
  }
254
279
  });
255
- return /* @__PURE__ */ jsx4(Form, { ...form, children: /* @__PURE__ */ jsxs3("form", { className: "space-y-4", children: [
256
- /* @__PURE__ */ jsx4(
257
- FormField,
280
+ const handleSubmit = form.handleSubmit(async (values) => {
281
+ await onSubmit(values);
282
+ });
283
+ return /* @__PURE__ */ jsxs3("form", { id: "verification-form", onSubmit: handleSubmit, children: [
284
+ /* @__PURE__ */ jsx4(FieldGroup, { children: /* @__PURE__ */ jsx4(
285
+ Controller,
258
286
  {
259
- control: form.control,
260
287
  name: "code",
261
- render: ({ field }) => /* @__PURE__ */ jsxs3(FormItem, { children: [
262
- /* @__PURE__ */ jsx4(FormControl, { children: /* @__PURE__ */ jsx4("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx4(
288
+ control: form.control,
289
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs3(Field, { "data-invalid": fieldState.invalid, children: [
290
+ /* @__PURE__ */ jsx4("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx4(
263
291
  InputOTP,
264
292
  {
265
293
  maxLength: 6,
@@ -269,6 +297,7 @@ var VerificationForm = ({
269
297
  onChange: field.onChange,
270
298
  onBlur: field.onBlur,
271
299
  containerClassName: "gap-4 justify-center mb-2 flex items-center",
300
+ "aria-invalid": fieldState.invalid,
272
301
  children: /* @__PURE__ */ jsxs3(InputOTPGroup, { className: "gap-3 *:data-[slot=input-otp-slot]:h-12 *:data-[slot=input-otp-slot]:w-12 *:data-[slot=input-otp-slot]:rounded-md *:data-[slot=input-otp-slot]:border *:data-[slot=input-otp-slot]:text-xl", children: [
273
302
  /* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 0 }),
274
303
  /* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 1 }),
@@ -278,22 +307,18 @@ var VerificationForm = ({
278
307
  /* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 5 })
279
308
  ] })
280
309
  }
281
- ) }) }),
282
- /* @__PURE__ */ jsx4(FormMessage, {})
310
+ ) }),
311
+ fieldState.invalid && /* @__PURE__ */ jsx4(FieldError, { errors: [fieldState.error] })
283
312
  ] })
284
313
  }
285
- ),
286
- /* @__PURE__ */ jsxs3("div", { className: "flex justify-between items-center", children: [
314
+ ) }),
315
+ /* @__PURE__ */ jsxs3("div", { className: "flex justify-between items-center mt-4", children: [
287
316
  /* @__PURE__ */ jsx4(Countdown, { onResend, resending: isLoading }),
288
317
  /* @__PURE__ */ jsxs3(
289
318
  Button2,
290
319
  {
291
- type: "button",
292
- onClick: () => {
293
- form.handleSubmit(async (values) => {
294
- await onSubmit(values);
295
- })();
296
- },
320
+ type: "submit",
321
+ form: "verification-form",
297
322
  disabled: isLoading || form.watch("code").length !== 6,
298
323
  children: [
299
324
  isLoading && /* @__PURE__ */ jsx4(Spinner2, {}),
@@ -302,28 +327,51 @@ var VerificationForm = ({
302
327
  }
303
328
  )
304
329
  ] })
305
- ] }) });
330
+ ] });
306
331
  };
307
332
 
308
333
  // src/components/auth/pages/verify-phone-page.tsx
309
- import { jsx as jsx5 } from "react/jsx-runtime";
334
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
310
335
  var VerifyPhonePage = ({
311
336
  verificationId,
312
337
  context,
313
338
  phone = "",
314
- onNavigate,
315
- linkComponent: Link,
316
- links,
317
- logoImage,
318
339
  redirectUrl
319
340
  }) => {
320
- const t = useTranslations3("Auth.verification");
321
- const common = useTranslations3("Common");
322
- const footer = useTranslations3("Auth.forgotPassword.footer");
323
- const { client, refresh, setAuth } = useAuth();
341
+ const { hooks, refresh, setAuth } = useApi();
342
+ const { config } = useConfig();
343
+ const t = createTranslator(config.messages || {}, "Auth.verification");
344
+ const common = createTranslator(config.messages || {}, "Common");
345
+ const footer = createTranslator(
346
+ config.messages || {},
347
+ "Auth.forgotPassword.footer"
348
+ );
324
349
  const [isLoading, setIsLoading] = useState3(false);
325
350
  const [error, setError] = useState3(null);
326
- const signInLink = links?.signIn || "/auth/sign-in";
351
+ const verifyPhoneMutation = hooks.useMutation(
352
+ "post",
353
+ "/phone/verification/confirm"
354
+ );
355
+ const requestPhoneMutation = hooks.useMutation(
356
+ "post",
357
+ "/phone/verification/request"
358
+ );
359
+ const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
360
+ const Link = config.navigation?.linkComponent;
361
+ const onNavigate = config.navigation?.onNavigate || ((path) => {
362
+ if (typeof window !== "undefined") {
363
+ window.location.href = path;
364
+ }
365
+ });
366
+ const logoImage = config.ui.logoImage;
367
+ const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
368
+ useEffect3(() => {
369
+ if (error) {
370
+ toast.error(error.title || "Error", {
371
+ description: error.description
372
+ });
373
+ }
374
+ }, [error]);
327
375
  const handleSubmit = async (values) => {
328
376
  if (!verificationId) {
329
377
  setError({
@@ -335,18 +383,20 @@ var VerifyPhonePage = ({
335
383
  setIsLoading(true);
336
384
  setError(null);
337
385
  try {
338
- const res = await client.verifyPhoneOtp({
339
- verificationId,
340
- code: values.code,
341
- context
386
+ const res = await verifyPhoneMutation.mutateAsync({
387
+ body: {
388
+ verificationId,
389
+ code: values.code,
390
+ context
391
+ }
342
392
  });
343
393
  if (res && "user" in res && "session" in res && res.session) {
344
394
  setAuth(res);
345
- onNavigate(redirectUrl || "/");
395
+ onNavigate(defaultRedirect);
346
396
  return;
347
397
  }
348
398
  await refresh();
349
- onNavigate(redirectUrl || "/");
399
+ onNavigate(defaultRedirect);
350
400
  } catch (err) {
351
401
  handleError(err, setError, t);
352
402
  } finally {
@@ -364,7 +414,12 @@ var VerifyPhonePage = ({
364
414
  });
365
415
  return;
366
416
  }
367
- const res = await client.requestPhoneOtp({ phone: targetPhone, context });
417
+ const res = await requestPhoneMutation.mutateAsync({
418
+ body: {
419
+ phone: targetPhone,
420
+ context
421
+ }
422
+ });
368
423
  if (res && "verificationId" in res && res.verificationId) {
369
424
  onNavigate(
370
425
  `/auth/verify-phone?context=${context}&verificationId=${res.verificationId}&phone=${targetPhone}`
@@ -401,14 +456,21 @@ var VerifyPhonePage = ({
401
456
  }
402
457
  );
403
458
  }
404
- return /* @__PURE__ */ jsx5(
459
+ let errorContent = null;
460
+ if (error) {
461
+ if (typeof error === "string") {
462
+ errorContent = { title: "Error", description: error };
463
+ } else {
464
+ errorContent = error;
465
+ }
466
+ }
467
+ return /* @__PURE__ */ jsxs4(
405
468
  AuthPageLayout,
406
469
  {
407
470
  title: t("phone.title"),
408
471
  description: t("phone.description", {
409
472
  target: phone || t("phone.missingPhone")
410
473
  }),
411
- error,
412
474
  logoImage,
413
475
  footer: Link ? /* @__PURE__ */ jsx5(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx5(
414
476
  "a",
@@ -422,16 +484,23 @@ var VerifyPhonePage = ({
422
484
  children: footer("backToSignIn")
423
485
  }
424
486
  ),
425
- children: /* @__PURE__ */ jsx5(
426
- VerificationForm,
427
- {
428
- verificationId,
429
- onSubmit: handleSubmit,
430
- onResend: handleResend,
431
- isLoading,
432
- error
433
- }
434
- )
487
+ children: [
488
+ /* @__PURE__ */ jsx5(
489
+ VerificationForm,
490
+ {
491
+ verificationId,
492
+ onSubmit: handleSubmit,
493
+ onResend: handleResend,
494
+ isLoading: isLoading || verifyPhoneMutation.isPending || requestPhoneMutation.isPending,
495
+ error
496
+ }
497
+ ),
498
+ errorContent && /* @__PURE__ */ jsxs4(Alert, { variant: "destructive", className: "mt-4", children: [
499
+ /* @__PURE__ */ jsx5(IconAlertCircle, { className: "h-4 w-4" }),
500
+ /* @__PURE__ */ jsx5(AlertTitle, { children: errorContent.title }),
501
+ /* @__PURE__ */ jsx5(AlertDescription, { children: errorContent.description })
502
+ ] })
503
+ ]
435
504
  }
436
505
  );
437
506
  };