@mesob/auth-react 0.1.1 → 0.2.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.
Files changed (117) hide show
  1. package/dist/components/auth/auth-card.js +1 -1
  2. package/dist/components/auth/auth-card.js.map +1 -1
  3. package/dist/components/auth/{auth-page-layout.d.ts → auth-layout.d.ts} +3 -3
  4. package/dist/components/auth/{auth-page-layout.js → auth-layout.js} +4 -4
  5. package/dist/components/auth/auth-layout.js.map +1 -0
  6. package/dist/components/auth/countdown.js +15 -6
  7. package/dist/components/auth/countdown.js.map +1 -1
  8. package/dist/components/auth/forgot-password.d.ts +1 -9
  9. package/dist/components/auth/forgot-password.js +267 -43
  10. package/dist/components/auth/forgot-password.js.map +1 -1
  11. package/dist/components/auth/reset-password-form.d.ts +2 -10
  12. package/dist/components/auth/reset-password-form.js +366 -118
  13. package/dist/components/auth/reset-password-form.js.map +1 -1
  14. package/dist/components/auth/sign-in.d.ts +2 -10
  15. package/dist/components/auth/sign-in.js +358 -130
  16. package/dist/components/auth/sign-in.js.map +1 -1
  17. package/dist/components/auth/sign-up.d.ts +2 -10
  18. package/dist/components/auth/sign-up.js +379 -131
  19. package/dist/components/auth/sign-up.js.map +1 -1
  20. package/dist/components/auth/verification-form.d.ts +2 -16
  21. package/dist/components/auth/verification-form.js +15 -6
  22. package/dist/components/auth/verification-form.js.map +1 -1
  23. package/dist/components/auth/verify-email.d.ts +10 -0
  24. package/dist/components/auth/{pages/verify-email-page.js → verify-email.js} +54 -34
  25. package/dist/components/auth/verify-email.js.map +1 -0
  26. package/dist/components/auth/verify-phone.d.ts +11 -0
  27. package/dist/components/auth/{pages/verify-phone-page.js → verify-phone.js} +53 -46
  28. package/dist/components/auth/verify-phone.js.map +1 -0
  29. package/dist/components/iam/permissions.d.ts +5 -0
  30. package/dist/components/iam/{permissions/permissions-page.js → permissions.js} +29 -13
  31. package/dist/components/iam/permissions.js.map +1 -0
  32. package/dist/components/iam/roles.d.ts +5 -0
  33. package/dist/components/iam/{roles/roles-page.js → roles.js} +29 -13
  34. package/dist/components/iam/roles.js.map +1 -0
  35. package/dist/components/iam/sessions.d.ts +5 -0
  36. package/dist/components/iam/{sessions/sessions-page.js → sessions.js} +13 -11
  37. package/dist/components/iam/sessions.js.map +1 -0
  38. package/dist/components/iam/tenants.d.ts +5 -0
  39. package/dist/components/iam/{tenants/tenants-page.js → tenants.js} +13 -11
  40. package/dist/components/iam/tenants.js.map +1 -0
  41. package/dist/components/iam/users.d.ts +5 -0
  42. package/dist/components/iam/{users/users-page.js → users.js} +13 -11
  43. package/dist/components/iam/users.js.map +1 -0
  44. package/dist/components/profile/account.d.ts +5 -0
  45. package/dist/components/profile/account.js +66 -0
  46. package/dist/components/profile/account.js.map +1 -0
  47. package/dist/components/profile/change-email-form.d.ts +5 -0
  48. package/dist/components/profile/change-email-form.js +721 -0
  49. package/dist/components/profile/change-email-form.js.map +1 -0
  50. package/dist/components/profile/change-password-form.d.ts +5 -0
  51. package/dist/components/profile/change-password-form.js +256 -0
  52. package/dist/components/profile/change-password-form.js.map +1 -0
  53. package/dist/components/profile/change-phone-form.d.ts +5 -0
  54. package/dist/components/profile/change-phone-form.js +758 -0
  55. package/dist/components/profile/change-phone-form.js.map +1 -0
  56. package/dist/components/profile/change-profile.d.ts +9 -0
  57. package/dist/components/profile/change-profile.js +37 -0
  58. package/dist/components/profile/change-profile.js.map +1 -0
  59. package/dist/components/profile/otp-verification-modal.d.ts +15 -0
  60. package/dist/components/profile/otp-verification-modal.js +261 -0
  61. package/dist/components/profile/otp-verification-modal.js.map +1 -0
  62. package/dist/components/profile/request-change-email-form.d.ts +10 -0
  63. package/dist/components/profile/request-change-email-form.js +293 -0
  64. package/dist/components/profile/request-change-email-form.js.map +1 -0
  65. package/dist/components/profile/request-change-phone-form.d.ts +10 -0
  66. package/dist/components/profile/request-change-phone-form.js +331 -0
  67. package/dist/components/profile/request-change-phone-form.js.map +1 -0
  68. package/dist/components/profile/security.d.ts +5 -0
  69. package/dist/components/profile/security.js +1439 -0
  70. package/dist/components/profile/security.js.map +1 -0
  71. package/dist/components/profile/verify-change-email-form.d.ts +11 -0
  72. package/dist/components/profile/verify-change-email-form.js +402 -0
  73. package/dist/components/profile/verify-change-email-form.js.map +1 -0
  74. package/dist/components/profile/verify-change-phone-form.d.ts +11 -0
  75. package/dist/components/profile/verify-change-phone-form.js +406 -0
  76. package/dist/components/profile/verify-change-phone-form.js.map +1 -0
  77. package/dist/components/shared/{data-table/data-table.js → data-table.js} +2 -2
  78. package/dist/components/shared/data-table.js.map +1 -0
  79. package/dist/index.d.ts +42 -93
  80. package/dist/index.js +2298 -1300
  81. package/dist/index.js.map +1 -1
  82. package/dist/types-D3s9oE-5.d.ts +75 -0
  83. package/dist/verification-form-ipSRTtQB.d.ts +22 -0
  84. package/package.json +3 -2
  85. package/dist/components/auth/auth-page-layout.js.map +0 -1
  86. package/dist/components/auth/pages/forgot-password-page.d.ts +0 -6
  87. package/dist/components/auth/pages/forgot-password-page.js +0 -362
  88. package/dist/components/auth/pages/forgot-password-page.js.map +0 -1
  89. package/dist/components/auth/pages/reset-password-page.d.ts +0 -9
  90. package/dist/components/auth/pages/reset-password-page.js +0 -514
  91. package/dist/components/auth/pages/reset-password-page.js.map +0 -1
  92. package/dist/components/auth/pages/sign-in-page.d.ts +0 -8
  93. package/dist/components/auth/pages/sign-in-page.js +0 -565
  94. package/dist/components/auth/pages/sign-in-page.js.map +0 -1
  95. package/dist/components/auth/pages/sign-up-page.d.ts +0 -9
  96. package/dist/components/auth/pages/sign-up-page.js +0 -518
  97. package/dist/components/auth/pages/sign-up-page.js.map +0 -1
  98. package/dist/components/auth/pages/verify-email-page.d.ts +0 -10
  99. package/dist/components/auth/pages/verify-email-page.js.map +0 -1
  100. package/dist/components/auth/pages/verify-phone-page.d.ts +0 -11
  101. package/dist/components/auth/pages/verify-phone-page.js.map +0 -1
  102. package/dist/components/iam/permissions/permissions-page.d.ts +0 -5
  103. package/dist/components/iam/permissions/permissions-page.js.map +0 -1
  104. package/dist/components/iam/roles/roles-page.d.ts +0 -5
  105. package/dist/components/iam/roles/roles-page.js.map +0 -1
  106. package/dist/components/iam/sessions/sessions-page.d.ts +0 -5
  107. package/dist/components/iam/sessions/sessions-page.js.map +0 -1
  108. package/dist/components/iam/tenants/tenants-page.d.ts +0 -5
  109. package/dist/components/iam/tenants/tenants-page.js.map +0 -1
  110. package/dist/components/iam/users/users-page.d.ts +0 -5
  111. package/dist/components/iam/users/users-page.js.map +0 -1
  112. package/dist/components/profile/profile-page.d.ts +0 -8
  113. package/dist/components/profile/profile-page.js +0 -163
  114. package/dist/components/profile/profile-page.js.map +0 -1
  115. package/dist/components/shared/data-table/data-table.js.map +0 -1
  116. package/dist/handle-error-BqDMxnQZ.d.ts +0 -8
  117. /package/dist/components/shared/{data-table/data-table.d.ts → data-table.d.ts} +0 -0
package/dist/index.js CHANGED
@@ -3,18 +3,34 @@
3
3
  // src/components/auth/auth-card.tsx
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  var AuthCard = ({ children }) => {
6
- return /* @__PURE__ */ jsx("div", { className: "flex min-h-screen p-4 items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "w-full max-w-md", children: /* @__PURE__ */ jsx("div", { className: "rounded-xl border bg-card p-8 shadow-lg", children }) }) });
6
+ return /* @__PURE__ */ jsx("div", { className: "flex min-h-screen w-full p-4 items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "w-full min-w-[280px] max-w-[28rem] shrink-0", children: /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-border bg-card p-6 shadow-lg sm:p-8", children }) }) });
7
7
  };
8
8
 
9
- // src/components/auth/pages/forgot-password-page.tsx
9
+ // src/components/auth/forgot-password.tsx
10
+ import { zodResolver } from "@hookform/resolvers/zod";
10
11
  import {
11
12
  Alert,
12
13
  AlertDescription,
13
14
  AlertTitle
14
15
  } from "@mesob/ui/components/alert";
15
- import { toast } from "@mesob/ui/components/sonner";
16
+ import { Button } from "@mesob/ui/components/button";
17
+ import {
18
+ Field,
19
+ FieldError,
20
+ FieldGroup,
21
+ FieldLabel
22
+ } from "@mesob/ui/components/field";
23
+ import { Input } from "@mesob/ui/components/input";
24
+ import { useMesob as useMesob2 } from "@mesob/ui/components/mesob-context";
25
+ import { Spinner } from "@mesob/ui/components/spinner";
16
26
  import { IconAlertCircle } from "@tabler/icons-react";
17
- import { useEffect as useEffect2, useState as useState2 } from "react";
27
+ import { useEffect, useState as useState2 } from "react";
28
+ import { Controller, useForm } from "react-hook-form";
29
+ import { toast } from "sonner";
30
+ import { z } from "zod";
31
+
32
+ // src/hooks/use-translator.ts
33
+ import { useMesob } from "@mesob/ui/components/mesob-context";
18
34
 
19
35
  // src/lib/translations.ts
20
36
  function createTranslator(messages, namespace) {
@@ -47,7 +63,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
47
63
  import { deepmerge } from "deepmerge-ts";
48
64
  import createFetchClient from "openapi-fetch";
49
65
  import createClient from "openapi-react-query";
50
- import { createContext, useContext, useEffect, useState } from "react";
66
+ import { createContext, useContext, useMemo, useState } from "react";
51
67
 
52
68
  // src/types.ts
53
69
  var defaultAuthClientConfig = {
@@ -62,57 +78,45 @@ var defaultAuthClientConfig = {
62
78
  navigation: {
63
79
  locale: "en"
64
80
  },
65
- cookiePrefix: "msb"
81
+ cookiePrefix: "msb",
82
+ phoneRegex: /^(\+2519|\+2517|2519|2517|09|07)\d{8}$/
83
+ };
84
+
85
+ // src/utils/cookie.ts
86
+ var isProduction = typeof process !== "undefined" && process.env.NODE_ENV === "production";
87
+ var getSessionCookieName = (config) => {
88
+ const prefix = config.cookiePrefix || "";
89
+ const baseName = "session_token";
90
+ if (prefix) {
91
+ return `${prefix}_${baseName}`;
92
+ }
93
+ return isProduction ? "__Host-session_token" : baseName;
66
94
  };
67
95
 
68
96
  // src/utils/custom-fetch.ts
69
- var createCustomFetch = (config) => {
97
+ var createCustomFetch = (_config) => {
70
98
  return (input, init) => {
71
- const baseUrl = config.baseURL;
72
99
  if (input instanceof Request) {
73
- const originalUrl = input.url;
74
- const fullUrl2 = originalUrl.startsWith("http") ? originalUrl : `${baseUrl}${originalUrl}`;
75
- if (originalUrl === fullUrl2) {
76
- return fetch(input, {
77
- credentials: "include"
78
- });
79
- }
80
- const clonedRequest = input.clone();
81
- const requestInit = {
82
- method: clonedRequest.method,
83
- headers: clonedRequest.headers,
84
- credentials: "include"
85
- };
86
- if (clonedRequest.body !== null) {
87
- requestInit.body = clonedRequest.body;
88
- requestInit.duplex = "half";
89
- }
90
- return fetch(fullUrl2, requestInit);
91
- }
92
- const urlString = typeof input === "string" ? input : input.toString();
93
- const fullUrl = urlString.startsWith("http") ? urlString : `${baseUrl}${urlString}`;
94
- return fetch(fullUrl, {
95
- ...init,
96
- headers: {
97
- "Content-Type": "application/json",
98
- ...init?.headers
99
- },
100
- credentials: "include"
101
- });
100
+ return fetch(input, { ...init, credentials: "include" });
101
+ }
102
+ return fetch(input, { ...init, credentials: "include" });
102
103
  };
103
104
  };
104
105
 
105
106
  // src/provider.tsx
106
107
  import { jsx as jsx2 } from "react/jsx-runtime";
108
+ function isServer() {
109
+ return typeof document === "undefined";
110
+ }
111
+ function hasAuthCookie(_cookieName) {
112
+ return false;
113
+ }
107
114
  var SessionContext = createContext(null);
108
115
  var ApiContext = createContext(null);
109
116
  var ConfigContext = createContext(null);
110
117
  var queryClient = new QueryClient({
111
118
  defaultOptions: {
112
119
  queries: {
113
- staleTime: 1e3 * 60 * 5,
114
- gcTime: 1e3 * 60 * 10,
115
- retry: 1,
116
120
  refetchOnWindowFocus: false
117
121
  }
118
122
  }
@@ -138,35 +142,54 @@ function useConfig() {
138
142
  }
139
143
  return context;
140
144
  }
145
+ function useHasAuthCookie() {
146
+ const { status } = useSession();
147
+ return status === "authenticated" || status === "loading";
148
+ }
141
149
  function MesobAuthProvider({
142
150
  config,
143
151
  children
144
152
  }) {
145
- const mergedConfig = deepmerge(
146
- { ...defaultAuthClientConfig },
147
- config
153
+ const mergedConfig = useMemo(
154
+ () => deepmerge(
155
+ { ...defaultAuthClientConfig },
156
+ config
157
+ ),
158
+ [config]
148
159
  );
149
- const api = createFetchClient({
150
- baseUrl: mergedConfig.baseURL,
151
- fetch: createCustomFetch(mergedConfig)
152
- });
153
- const hooks = createClient(api);
154
- return /* @__PURE__ */ jsx2(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx2(AuthStateProvider, { config: mergedConfig, hooks, children }) });
160
+ const api = useMemo(
161
+ () => createFetchClient({
162
+ baseUrl: mergedConfig.baseURL,
163
+ fetch: createCustomFetch(mergedConfig)
164
+ }),
165
+ [mergedConfig]
166
+ );
167
+ const hooks = useMemo(() => createClient(api), [api]);
168
+ const cookieName = useMemo(
169
+ () => getSessionCookieName(mergedConfig),
170
+ [mergedConfig]
171
+ );
172
+ return /* @__PURE__ */ jsx2(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx2(
173
+ AuthStateProvider,
174
+ {
175
+ config: mergedConfig,
176
+ hooks,
177
+ cookieName,
178
+ children
179
+ }
180
+ ) });
155
181
  }
156
182
  function AuthStateProvider({
157
183
  config,
158
184
  hooks,
185
+ cookieName,
159
186
  children
160
187
  }) {
161
- const [authState, setAuthState] = useState({
162
- user: null,
163
- session: null,
164
- isLoading: false,
165
- error: null
166
- });
188
+ const [override, setOverride] = useState(null);
167
189
  const {
168
190
  data: sessionData,
169
- isLoading: sessionLoading,
191
+ isLoading,
192
+ isFetched,
170
193
  error: sessionError,
171
194
  refetch
172
195
  } = hooks.useQuery(
@@ -174,63 +197,93 @@ function AuthStateProvider({
174
197
  "/session",
175
198
  {},
176
199
  {
177
- enabled: true,
178
- refetchOnMount: true,
200
+ enabled: !(override || isServer()),
201
+ refetchOnMount: false,
179
202
  refetchOnWindowFocus: false,
180
203
  refetchOnReconnect: false,
181
- retry: false
204
+ retry: false,
205
+ gcTime: 0,
206
+ staleTime: 0
182
207
  }
183
208
  );
184
- useEffect(() => {
185
- if (sessionLoading) {
186
- setAuthState((prev) => ({ ...prev, isLoading: true }));
187
- return;
209
+ const user = override?.user ?? sessionData?.user ?? null;
210
+ const session = override?.session ?? sessionData?.session ?? null;
211
+ const error = override?.error ?? sessionError;
212
+ const errorStatus = (() => {
213
+ if (!sessionError) {
214
+ return null;
215
+ }
216
+ const err = sessionError;
217
+ return err.status ?? null;
218
+ })();
219
+ const isNetworkError = (() => {
220
+ if (!sessionError) {
221
+ return false;
222
+ }
223
+ const error2 = sessionError;
224
+ const errorMessage = error2.message || String(error2) || JSON.stringify(error2);
225
+ if (error2 instanceof TypeError || error2 instanceof DOMException || error2.name === "TypeError" || errorMessage.includes("Failed to fetch") || errorMessage.includes("ERR_CONNECTION_REFUSED") || errorMessage.includes("NetworkError") || errorMessage.includes("Network request failed") || errorMessage.includes("fetch failed")) {
226
+ return true;
227
+ }
228
+ if (error2.cause) {
229
+ const causeStr = String(error2.cause);
230
+ if (causeStr.includes("Failed to fetch") || causeStr.includes("ERR_CONNECTION_REFUSED") || causeStr.includes("NetworkError")) {
231
+ return true;
232
+ }
188
233
  }
189
- if (sessionError) {
190
- setAuthState({
191
- user: null,
192
- session: null,
193
- isLoading: false,
194
- error: sessionError
195
- });
196
- return;
234
+ return false;
235
+ })();
236
+ const status = (() => {
237
+ if (override) {
238
+ return override.status;
197
239
  }
198
- if (sessionData) {
199
- setAuthState({
200
- user: sessionData.user,
201
- session: sessionData.session,
202
- isLoading: false,
203
- error: null
204
- });
205
- return;
240
+ if (isServer()) {
241
+ return "loading";
206
242
  }
207
- setAuthState({
208
- user: null,
209
- session: null,
210
- isLoading: false,
211
- error: null
212
- });
213
- }, [sessionData, sessionLoading, sessionError]);
214
- const refresh = async () => {
215
- await refetch();
216
- };
243
+ if (user && session) {
244
+ return "authenticated";
245
+ }
246
+ if (isNetworkError || errorStatus === 401) {
247
+ return "unauthenticated";
248
+ }
249
+ if (sessionError && !isNetworkError && errorStatus !== 401) {
250
+ if (errorStatus && errorStatus >= 500) {
251
+ return "authenticated";
252
+ }
253
+ if (isFetched) {
254
+ return "unauthenticated";
255
+ }
256
+ }
257
+ if (isLoading || !isFetched) {
258
+ return "loading";
259
+ }
260
+ if (isFetched && !user && !session) {
261
+ return "unauthenticated";
262
+ }
263
+ return "unauthenticated";
264
+ })();
265
+ const signOutMutation = hooks.useMutation("post", "/sign-out");
266
+ const t = createTranslator(config.messages || {});
217
267
  const setAuth = (auth) => {
218
- setAuthState({
268
+ setOverride({
219
269
  user: auth.user,
220
270
  session: auth.session,
221
- isLoading: false,
271
+ status: "authenticated",
222
272
  error: null
223
273
  });
224
274
  };
225
275
  const clearAuth = () => {
226
- setAuthState({
276
+ setOverride({
227
277
  user: null,
228
278
  session: null,
229
- isLoading: false,
279
+ status: "unauthenticated",
230
280
  error: null
231
281
  });
232
282
  };
233
- const signOutMutation = hooks.useMutation("post", "/sign-out");
283
+ const refresh = async () => {
284
+ setOverride(null);
285
+ await refetch();
286
+ };
234
287
  const signOut = async () => {
235
288
  try {
236
289
  await signOutMutation.mutateAsync({});
@@ -238,16 +291,16 @@ function AuthStateProvider({
238
291
  clearAuth();
239
292
  }
240
293
  };
241
- const t = createTranslator(config.messages || {});
242
- return /* @__PURE__ */ jsx2(ConfigContext.Provider, { value: { config, t }, children: /* @__PURE__ */ jsx2(ApiContext.Provider, { value: { hooks, setAuth, clearAuth, refresh }, children: /* @__PURE__ */ jsx2(
294
+ return /* @__PURE__ */ jsx2(ConfigContext.Provider, { value: { config, cookieName, t }, children: /* @__PURE__ */ jsx2(ApiContext.Provider, { value: { hooks, setAuth, clearAuth, refresh }, children: /* @__PURE__ */ jsx2(
243
295
  SessionContext.Provider,
244
296
  {
245
297
  value: {
246
- user: authState.user,
247
- session: authState.session,
248
- isLoading: authState.isLoading,
249
- isAuthenticated: !!authState.user && !!authState.session,
250
- error: authState.error,
298
+ user,
299
+ session,
300
+ status,
301
+ error,
302
+ isLoading: status === "loading",
303
+ isAuthenticated: status === "authenticated",
251
304
  refresh,
252
305
  signOut
253
306
  },
@@ -256,6 +309,16 @@ function AuthStateProvider({
256
309
  ) }) });
257
310
  }
258
311
 
312
+ // src/hooks/use-translator.ts
313
+ function useTranslator(namespace) {
314
+ const mesob = useMesob();
315
+ const { config } = useConfig();
316
+ if (mesob?.t) {
317
+ return (key, params) => mesob.t(namespace ? `${namespace}.${key}` : key, params);
318
+ }
319
+ return createTranslator(config.messages || {}, namespace);
320
+ }
321
+
259
322
  // src/constants/auth.error.codes.ts
260
323
  var AUTH_ERROR_MAPPING = {
261
324
  USER_NOT_FOUND: {
@@ -321,6 +384,14 @@ function extractErrorCode(err) {
321
384
  }
322
385
  return "";
323
386
  }
387
+ function sanitizeErrorMessage(message) {
388
+ const lowerMessage = message.toLowerCase();
389
+ const isDatabaseError = lowerMessage.includes("failed query") || lowerMessage.includes("select") || lowerMessage.includes("insert") || lowerMessage.includes("update") || lowerMessage.includes("delete") || lowerMessage.includes("from") || lowerMessage.includes("where") || lowerMessage.includes("limit") || lowerMessage.includes("params:") || lowerMessage.includes("query") || message.includes('"iam".') || message.includes('"tenants"') || message.includes('"users"') || message.includes('"sessions"') || message.includes('"accounts"') || lowerMessage.includes("relation") || lowerMessage.includes("column") || lowerMessage.includes("syntax error") || lowerMessage.includes("database") || lowerMessage.includes("postgres") || lowerMessage.includes("sql");
390
+ if (isDatabaseError) {
391
+ return "An error occurred while processing your request";
392
+ }
393
+ return message;
394
+ }
324
395
  function handleAuthError(err, setError, t) {
325
396
  const errorCode = extractErrorCode(err);
326
397
  if (errorCode && AUTH_ERROR_MAPPING[errorCode]) {
@@ -331,16 +402,20 @@ function handleAuthError(err, setError, t) {
331
402
  });
332
403
  return;
333
404
  }
405
+ const sanitizedMessage = sanitizeErrorMessage(
406
+ err.message || t("errors.fallback")
407
+ );
334
408
  setError({
335
409
  title: t("errors.fallback"),
336
- description: err.message || t("errors.fallback")
410
+ description: sanitizedMessage
337
411
  });
338
412
  }
339
413
  function handleGenericError(err, setError, t) {
340
- const message = err instanceof Error ? err.message : t("errors.fallback");
414
+ const rawMessage = err instanceof Error ? err.message : t("errors.fallback");
415
+ const sanitizedMessage = sanitizeErrorMessage(rawMessage);
341
416
  setError({
342
417
  title: "Error",
343
- description: message
418
+ description: sanitizedMessage
344
419
  });
345
420
  }
346
421
  var handleError = (err, setError, t) => {
@@ -351,9 +426,9 @@ var handleError = (err, setError, t) => {
351
426
  }
352
427
  };
353
428
 
354
- // src/components/auth/auth-page-layout.tsx
429
+ // src/components/auth/auth-layout.tsx
355
430
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
356
- var AuthPageLayout = ({
431
+ var AuthLayout = ({
357
432
  title,
358
433
  description,
359
434
  children,
@@ -371,108 +446,41 @@ var AuthPageLayout = ({
371
446
  ] });
372
447
  };
373
448
 
374
- // src/components/auth/forgot-password.tsx
375
- import { zodResolver } from "@hookform/resolvers/zod";
376
- import { Button } from "@mesob/ui/components/button";
377
- import {
378
- Field,
379
- FieldError,
380
- FieldGroup,
381
- FieldLabel
382
- } from "@mesob/ui/components/field";
383
- import { Input } from "@mesob/ui/components/input";
384
- import { Spinner } from "@mesob/ui/components/spinner";
385
- import { Controller, useForm } from "react-hook-form";
386
- import { z } from "zod";
387
-
388
- // src/hooks/use-translator.ts
389
- function useTranslator(namespace) {
390
- const { config } = useConfig();
391
- return createTranslator(config.messages || {}, namespace);
392
- }
393
-
394
449
  // src/components/auth/forgot-password.tsx
395
450
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
396
451
  var forgotPasswordSchema = (t) => z.object({
397
452
  account: z.string().min(1, t("errors.accountRequired"))
398
453
  });
399
- var ForgotPassword = ({
400
- onSubmit,
401
- isLoading = false
402
- }) => {
403
- const t = useTranslator("Auth.forgotPassword");
404
- const form = useForm({
405
- resolver: zodResolver(forgotPasswordSchema(t)),
406
- defaultValues: {
407
- account: ""
408
- }
409
- });
410
- const handleSubmit = form.handleSubmit(async (values) => {
411
- await onSubmit(values);
412
- });
413
- return /* @__PURE__ */ jsxs2("form", { id: "forgot-password-form", onSubmit: handleSubmit, children: [
414
- /* @__PURE__ */ jsx4(FieldGroup, { children: /* @__PURE__ */ jsx4(
415
- Controller,
416
- {
417
- name: "account",
418
- control: form.control,
419
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs2(Field, { "data-invalid": fieldState.invalid, children: [
420
- /* @__PURE__ */ jsx4(FieldLabel, { htmlFor: "forgot-password-account", children: t("form.accountLabel") }),
421
- /* @__PURE__ */ jsx4(
422
- Input,
423
- {
424
- ...field,
425
- id: "forgot-password-account",
426
- type: "text",
427
- placeholder: t("form.accountPlaceholder"),
428
- "aria-invalid": fieldState.invalid
429
- }
430
- ),
431
- fieldState.invalid && /* @__PURE__ */ jsx4(FieldError, { errors: [fieldState.error] })
432
- ] })
433
- }
434
- ) }),
435
- /* @__PURE__ */ jsx4("div", { className: "mt-4", children: /* @__PURE__ */ jsxs2(
436
- Button,
437
- {
438
- type: "submit",
439
- form: "forgot-password-form",
440
- className: "w-full",
441
- disabled: isLoading,
442
- children: [
443
- isLoading && /* @__PURE__ */ jsx4(Spinner, {}),
444
- isLoading ? t("form.submitting") : t("form.submit")
445
- ]
446
- }
447
- ) })
448
- ] });
449
- };
450
-
451
- // src/components/auth/pages/forgot-password-page.tsx
452
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
453
- var ForgotPasswordPage = (_props = {}) => {
454
+ var ForgotPassword = () => {
454
455
  const { hooks } = useApi();
455
456
  const { config } = useConfig();
456
- const t = createTranslator(config.messages || {}, "Auth.forgotPassword");
457
+ const mesob = useMesob2();
458
+ const t = useTranslator("Auth.forgotPassword");
459
+ const Link3 = mesob?.linkComponent ?? config.navigation?.linkComponent;
457
460
  const [isLoading, setIsLoading] = useState2(false);
458
461
  const [error, setError] = useState2(null);
459
462
  const forgotPasswordMutation = hooks.useMutation("post", "/password/forgot");
460
463
  const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
461
- const Link = config.navigation?.linkComponent;
462
464
  const onNavigate = config.navigation?.onNavigate || ((path) => {
463
465
  if (typeof window !== "undefined") {
464
466
  window.location.href = path;
465
467
  }
466
468
  });
467
469
  const logoImage = config.ui.logoImage;
468
- useEffect2(() => {
470
+ const form = useForm({
471
+ resolver: zodResolver(forgotPasswordSchema(t)),
472
+ defaultValues: {
473
+ account: ""
474
+ }
475
+ });
476
+ useEffect(() => {
469
477
  if (error) {
470
478
  toast.error(error.title || "Error", {
471
479
  description: error.description
472
480
  });
473
481
  }
474
482
  }, [error]);
475
- const handleSubmit = async (values) => {
483
+ const handleSubmit = form.handleSubmit(async (values) => {
476
484
  setIsLoading(true);
477
485
  setError(null);
478
486
  try {
@@ -493,10 +501,7 @@ var ForgotPasswordPage = (_props = {}) => {
493
501
  } finally {
494
502
  setIsLoading(false);
495
503
  }
496
- };
497
- const handleBack = () => {
498
- onNavigate(signInLink);
499
- };
504
+ });
500
505
  let errorContent = null;
501
506
  if (error) {
502
507
  if (typeof error === "string") {
@@ -505,13 +510,13 @@ var ForgotPasswordPage = (_props = {}) => {
505
510
  errorContent = error;
506
511
  }
507
512
  }
508
- return /* @__PURE__ */ jsxs3(
509
- AuthPageLayout,
513
+ return /* @__PURE__ */ jsxs2(
514
+ AuthLayout,
510
515
  {
511
516
  title: t("title"),
512
517
  description: t("description"),
513
518
  logoImage,
514
- footer: Link ? /* @__PURE__ */ jsx5(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.backToSignIn") }) : /* @__PURE__ */ jsx5(
519
+ footer: Link3 ? /* @__PURE__ */ jsx4(Link3, { href: signInLink, className: "text-primary hover:underline", children: t("footer.backToSignIn") }) : /* @__PURE__ */ jsx4(
515
520
  "a",
516
521
  {
517
522
  href: signInLink,
@@ -524,36 +529,59 @@ var ForgotPasswordPage = (_props = {}) => {
524
529
  }
525
530
  ),
526
531
  children: [
527
- /* @__PURE__ */ jsx5(
528
- ForgotPassword,
529
- {
530
- onSubmit: handleSubmit,
531
- isLoading: isLoading || forgotPasswordMutation.isPending,
532
- onBack: handleBack
533
- }
534
- ),
535
- errorContent && /* @__PURE__ */ jsxs3(Alert, { variant: "destructive", className: "mt-4", children: [
536
- /* @__PURE__ */ jsx5(IconAlertCircle, { className: "h-4 w-4" }),
537
- /* @__PURE__ */ jsx5(AlertTitle, { children: errorContent.title }),
538
- /* @__PURE__ */ jsx5(AlertDescription, { children: errorContent.description })
532
+ /* @__PURE__ */ jsxs2("form", { id: "forgot-password-form", onSubmit: handleSubmit, children: [
533
+ /* @__PURE__ */ jsx4(FieldGroup, { children: /* @__PURE__ */ jsx4(
534
+ Controller,
535
+ {
536
+ name: "account",
537
+ control: form.control,
538
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs2(Field, { "data-invalid": fieldState.invalid, children: [
539
+ /* @__PURE__ */ jsx4(FieldLabel, { htmlFor: "forgot-password-account", children: t("form.accountLabel") }),
540
+ /* @__PURE__ */ jsx4(
541
+ Input,
542
+ {
543
+ ...field,
544
+ id: "forgot-password-account",
545
+ type: "text",
546
+ placeholder: t("form.accountPlaceholder"),
547
+ "aria-invalid": fieldState.invalid
548
+ }
549
+ ),
550
+ fieldState.invalid && /* @__PURE__ */ jsx4(FieldError, { errors: [fieldState.error] })
551
+ ] })
552
+ }
553
+ ) }),
554
+ /* @__PURE__ */ jsx4("div", { className: "mt-4", children: /* @__PURE__ */ jsxs2(
555
+ Button,
556
+ {
557
+ type: "submit",
558
+ form: "forgot-password-form",
559
+ className: "w-full",
560
+ disabled: isLoading || forgotPasswordMutation.isPending,
561
+ children: [
562
+ isLoading || forgotPasswordMutation.isPending && /* @__PURE__ */ jsx4(Spinner, {}),
563
+ isLoading || forgotPasswordMutation.isPending ? t("form.submitting") : t("form.submit")
564
+ ]
565
+ }
566
+ ) })
567
+ ] }),
568
+ errorContent && /* @__PURE__ */ jsxs2(Alert, { variant: "destructive", className: "mt-4", children: [
569
+ /* @__PURE__ */ jsx4(IconAlertCircle, { className: "h-4 w-4" }),
570
+ /* @__PURE__ */ jsx4(AlertTitle, { children: errorContent.title }),
571
+ /* @__PURE__ */ jsx4(AlertDescription, { children: errorContent.description })
539
572
  ] })
540
573
  ]
541
574
  }
542
575
  );
543
576
  };
544
577
 
545
- // src/components/auth/pages/reset-password-page.tsx
578
+ // src/components/auth/reset-password-form.tsx
579
+ import { zodResolver as zodResolver2 } from "@hookform/resolvers/zod";
546
580
  import {
547
581
  Alert as Alert2,
548
582
  AlertDescription as AlertDescription2,
549
583
  AlertTitle as AlertTitle2
550
584
  } from "@mesob/ui/components/alert";
551
- import { toast as toast2 } from "@mesob/ui/components/sonner";
552
- import { IconAlertCircle as IconAlertCircle2 } from "@tabler/icons-react";
553
- import { useEffect as useEffect3, useState as useState4 } from "react";
554
-
555
- // src/components/auth/reset-password-form.tsx
556
- import { zodResolver as zodResolver2 } from "@hookform/resolvers/zod";
557
585
  import { Button as Button2 } from "@mesob/ui/components/button";
558
586
  import {
559
587
  Field as Field2,
@@ -567,12 +595,14 @@ import {
567
595
  InputOTPGroup,
568
596
  InputOTPSlot
569
597
  } from "@mesob/ui/components/input-otp";
598
+ import { Link } from "@mesob/ui/components/link";
570
599
  import { Spinner as Spinner2 } from "@mesob/ui/components/spinner";
571
- import { IconEye, IconEyeOff } from "@tabler/icons-react";
572
- import { useState as useState3 } from "react";
600
+ import { IconAlertCircle as IconAlertCircle2, IconEye, IconEyeOff } from "@tabler/icons-react";
601
+ import { useEffect as useEffect2, useState as useState3 } from "react";
573
602
  import { Controller as Controller2, useForm as useForm2 } from "react-hook-form";
603
+ import { toast as toast2 } from "sonner";
574
604
  import { z as z2 } from "zod";
575
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
605
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
576
606
  var resetPasswordSchema = (t) => z2.object({
577
607
  code: z2.string().length(6, t("errors.codeLength")),
578
608
  password: z2.string().min(8, t("errors.passwordLength")),
@@ -582,151 +612,19 @@ var resetPasswordSchema = (t) => z2.object({
582
612
  path: ["confirmPassword"]
583
613
  });
584
614
  var ResetPasswordForm = ({
585
- onSubmit,
586
- isLoading = false
587
- }) => {
588
- const t = useTranslator("Auth.resetPassword");
589
- const [showPassword, setShowPassword] = useState3(false);
590
- const form = useForm2({
591
- resolver: zodResolver2(resetPasswordSchema(t)),
592
- defaultValues: {
593
- code: "",
594
- password: "",
595
- confirmPassword: ""
596
- }
597
- });
598
- const handleSubmit = form.handleSubmit(async (values) => {
599
- await onSubmit(values);
600
- });
601
- return /* @__PURE__ */ jsxs4("form", { id: "reset-password-form", onSubmit: handleSubmit, children: [
602
- /* @__PURE__ */ jsxs4(FieldGroup2, { children: [
603
- /* @__PURE__ */ jsx6(
604
- Controller2,
605
- {
606
- name: "code",
607
- control: form.control,
608
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs4(Field2, { "data-invalid": fieldState.invalid, children: [
609
- /* @__PURE__ */ jsx6("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx6(FieldLabel2, { children: t("form.codeLabel") }) }),
610
- /* @__PURE__ */ jsx6("div", { className: "flex mt-2 justify-center", children: /* @__PURE__ */ jsx6(
611
- InputOTP,
612
- {
613
- maxLength: 6,
614
- value: field.value,
615
- onChange: field.onChange,
616
- onBlur: field.onBlur,
617
- containerClassName: "gap-4",
618
- "aria-invalid": fieldState.invalid,
619
- children: /* @__PURE__ */ jsxs4(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: [
620
- /* @__PURE__ */ jsx6(InputOTPSlot, { className: "h-12", index: 0 }),
621
- /* @__PURE__ */ jsx6(InputOTPSlot, { className: "h-12", index: 1 }),
622
- /* @__PURE__ */ jsx6(InputOTPSlot, { className: "h-12", index: 2 }),
623
- /* @__PURE__ */ jsx6(InputOTPSlot, { className: "h-12", index: 3 }),
624
- /* @__PURE__ */ jsx6(InputOTPSlot, { className: "h-12", index: 4 }),
625
- /* @__PURE__ */ jsx6(InputOTPSlot, { className: "h-12", index: 5 })
626
- ] })
627
- }
628
- ) }),
629
- fieldState.invalid && /* @__PURE__ */ jsx6(FieldError2, { errors: [fieldState.error] })
630
- ] })
631
- }
632
- ),
633
- /* @__PURE__ */ jsx6(
634
- Controller2,
635
- {
636
- name: "password",
637
- control: form.control,
638
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs4(Field2, { "data-invalid": fieldState.invalid, children: [
639
- /* @__PURE__ */ jsx6(FieldLabel2, { htmlFor: "reset-password-password", children: t("form.passwordLabel") }),
640
- /* @__PURE__ */ jsxs4("div", { className: "relative", children: [
641
- /* @__PURE__ */ jsx6(
642
- Input2,
643
- {
644
- ...field,
645
- id: "reset-password-password",
646
- type: showPassword ? "text" : "password",
647
- placeholder: t("form.passwordPlaceholder"),
648
- "aria-invalid": fieldState.invalid
649
- }
650
- ),
651
- /* @__PURE__ */ jsx6(
652
- "button",
653
- {
654
- type: "button",
655
- onClick: () => setShowPassword(!showPassword),
656
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
657
- children: showPassword ? /* @__PURE__ */ jsx6(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx6(IconEye, { className: "h-4 w-4" })
658
- }
659
- )
660
- ] }),
661
- fieldState.invalid && /* @__PURE__ */ jsx6(FieldError2, { errors: [fieldState.error] })
662
- ] })
663
- }
664
- ),
665
- /* @__PURE__ */ jsx6(
666
- Controller2,
667
- {
668
- name: "confirmPassword",
669
- control: form.control,
670
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs4(Field2, { "data-invalid": fieldState.invalid, children: [
671
- /* @__PURE__ */ jsx6(FieldLabel2, { htmlFor: "reset-password-confirmPassword", children: t("form.confirmPasswordLabel") }),
672
- /* @__PURE__ */ jsxs4("div", { className: "relative", children: [
673
- /* @__PURE__ */ jsx6(
674
- Input2,
675
- {
676
- ...field,
677
- id: "reset-password-confirmPassword",
678
- type: showPassword ? "text" : "password",
679
- placeholder: t("form.passwordPlaceholder"),
680
- "aria-invalid": fieldState.invalid
681
- }
682
- ),
683
- /* @__PURE__ */ jsx6(
684
- "button",
685
- {
686
- type: "button",
687
- onClick: () => setShowPassword(!showPassword),
688
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
689
- children: showPassword ? /* @__PURE__ */ jsx6(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx6(IconEye, { className: "h-4 w-4" })
690
- }
691
- )
692
- ] }),
693
- fieldState.invalid && /* @__PURE__ */ jsx6(FieldError2, { errors: [fieldState.error] })
694
- ] })
695
- }
696
- )
697
- ] }),
698
- /* @__PURE__ */ jsx6("div", { className: "mt-4", children: /* @__PURE__ */ jsxs4(
699
- Button2,
700
- {
701
- type: "submit",
702
- form: "reset-password-form",
703
- className: "w-full",
704
- disabled: isLoading,
705
- children: [
706
- isLoading && /* @__PURE__ */ jsx6(Spinner2, {}),
707
- isLoading ? t("form.submitting") : t("form.submit")
708
- ]
709
- }
710
- ) })
711
- ] });
712
- };
713
-
714
- // src/components/auth/pages/reset-password-page.tsx
715
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
716
- var ResetPasswordPage = ({
717
615
  verificationId,
718
616
  redirectUrl
719
617
  }) => {
720
618
  const { hooks, refresh } = useApi();
721
619
  const { config } = useConfig();
722
- const t = createTranslator(config.messages || {}, "Auth.resetPassword");
723
- const common = createTranslator(config.messages || {}, "Common");
724
- const [isLoading, setIsLoading] = useState4(false);
725
- const [error, setError] = useState4(null);
620
+ const t = useTranslator("Auth.resetPassword");
621
+ const common = useTranslator("Common");
622
+ const [isLoading, setIsLoading] = useState3(false);
623
+ const [error, setError] = useState3(null);
624
+ const [showPassword, setShowPassword] = useState3(false);
726
625
  const resetPasswordMutation = hooks.useMutation("post", "/password/reset");
727
626
  const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
728
627
  const forgotPasswordLink = config.navigation?.links?.forgotPassword || "/auth/forgot-password";
729
- const Link = config.navigation?.linkComponent;
730
628
  const onNavigate = config.navigation?.onNavigate || ((path) => {
731
629
  if (typeof window !== "undefined") {
732
630
  window.location.href = path;
@@ -734,14 +632,22 @@ var ResetPasswordPage = ({
734
632
  });
735
633
  const logoImage = config.ui.logoImage;
736
634
  const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
737
- useEffect3(() => {
635
+ const form = useForm2({
636
+ resolver: zodResolver2(resetPasswordSchema(t)),
637
+ defaultValues: {
638
+ code: "",
639
+ password: "",
640
+ confirmPassword: ""
641
+ }
642
+ });
643
+ useEffect2(() => {
738
644
  if (error) {
739
645
  toast2.error(error.title || "Error", {
740
646
  description: error.description
741
647
  });
742
648
  }
743
649
  }, [error]);
744
- const handleSubmit = async (values) => {
650
+ const handleSubmit = form.handleSubmit(async (values) => {
745
651
  if (!verificationId) {
746
652
  setError({
747
653
  title: t("errors.fallback"),
@@ -766,34 +672,23 @@ var ResetPasswordPage = ({
766
672
  } finally {
767
673
  setIsLoading(false);
768
674
  }
769
- };
675
+ });
770
676
  if (!verificationId) {
771
- return /* @__PURE__ */ jsx7(
772
- AuthPageLayout,
677
+ return /* @__PURE__ */ jsx5(
678
+ AuthLayout,
773
679
  {
774
680
  title: common("invalidLinkTitle"),
775
681
  description: common("invalidLinkDescription"),
776
682
  logoImage,
777
- footer: Link ? /* @__PURE__ */ jsx7(
683
+ footer: /* @__PURE__ */ jsx5(
778
684
  Link,
779
685
  {
780
686
  href: forgotPasswordLink,
781
687
  className: "text-primary hover:underline",
782
688
  children: t("footer.requestNew")
783
689
  }
784
- ) : /* @__PURE__ */ jsx7(
785
- "a",
786
- {
787
- href: forgotPasswordLink,
788
- onClick: (e) => {
789
- e.preventDefault();
790
- onNavigate(forgotPasswordLink);
791
- },
792
- className: "text-primary hover:underline",
793
- children: t("footer.requestNew")
794
- }
795
690
  ),
796
- children: /* @__PURE__ */ jsx7("div", {})
691
+ children: /* @__PURE__ */ jsx5("div", {})
797
692
  }
798
693
  );
799
694
  }
@@ -805,15 +700,15 @@ var ResetPasswordPage = ({
805
700
  errorContent = error;
806
701
  }
807
702
  }
808
- return /* @__PURE__ */ jsxs5(
809
- AuthPageLayout,
703
+ return /* @__PURE__ */ jsxs3(
704
+ AuthLayout,
810
705
  {
811
706
  title: t("title"),
812
707
  description: t("description"),
813
708
  logoImage,
814
- footer: Link ? /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between w-full gap-2", children: [
815
- /* @__PURE__ */ jsx7(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.backToSignIn") }),
816
- /* @__PURE__ */ jsx7(
709
+ footer: /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between w-full gap-2", children: [
710
+ /* @__PURE__ */ jsx5(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.backToSignIn") }),
711
+ /* @__PURE__ */ jsx5(
817
712
  Link,
818
713
  {
819
714
  href: forgotPasswordLink,
@@ -821,64 +716,136 @@ var ResetPasswordPage = ({
821
716
  children: t("footer.changeAccount")
822
717
  }
823
718
  )
824
- ] }) : /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between w-full gap-2", children: [
825
- /* @__PURE__ */ jsx7(
826
- "a",
827
- {
828
- href: forgotPasswordLink,
829
- onClick: (e) => {
830
- e.preventDefault();
831
- onNavigate(forgotPasswordLink);
832
- },
833
- className: "text-primary hover:underline",
834
- children: t("footer.backToSignIn")
835
- }
836
- ),
837
- /* @__PURE__ */ jsx7(
838
- "a",
839
- {
840
- href: forgotPasswordLink,
841
- onClick: (e) => {
842
- e.preventDefault();
843
- onNavigate(forgotPasswordLink);
844
- },
845
- className: "text-primary hover:underline",
846
- children: t("footer.changeAccount")
847
- }
848
- )
849
719
  ] }),
850
720
  children: [
851
- /* @__PURE__ */ jsx7(
852
- ResetPasswordForm,
853
- {
854
- verificationId,
855
- onSubmit: handleSubmit,
856
- isLoading: isLoading || resetPasswordMutation.isPending,
857
- error
858
- }
859
- ),
860
- errorContent && /* @__PURE__ */ jsxs5(Alert2, { variant: "destructive", className: "mt-4", children: [
861
- /* @__PURE__ */ jsx7(IconAlertCircle2, { className: "h-4 w-4" }),
862
- /* @__PURE__ */ jsx7(AlertTitle2, { children: errorContent.title }),
863
- /* @__PURE__ */ jsx7(AlertDescription2, { children: errorContent.description })
721
+ /* @__PURE__ */ jsxs3("form", { id: "reset-password-form", onSubmit: handleSubmit, children: [
722
+ /* @__PURE__ */ jsxs3(FieldGroup2, { children: [
723
+ /* @__PURE__ */ jsx5(
724
+ Controller2,
725
+ {
726
+ name: "code",
727
+ control: form.control,
728
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs3(Field2, { "data-invalid": fieldState.invalid, children: [
729
+ /* @__PURE__ */ jsx5("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx5(FieldLabel2, { children: t("form.codeLabel") }) }),
730
+ /* @__PURE__ */ jsx5("div", { className: "flex mt-2 justify-center", children: /* @__PURE__ */ jsx5(
731
+ InputOTP,
732
+ {
733
+ maxLength: 6,
734
+ value: field.value,
735
+ onChange: field.onChange,
736
+ onBlur: field.onBlur,
737
+ containerClassName: "gap-4",
738
+ "aria-invalid": fieldState.invalid,
739
+ 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: [
740
+ /* @__PURE__ */ jsx5(InputOTPSlot, { className: "h-12", index: 0 }),
741
+ /* @__PURE__ */ jsx5(InputOTPSlot, { className: "h-12", index: 1 }),
742
+ /* @__PURE__ */ jsx5(InputOTPSlot, { className: "h-12", index: 2 }),
743
+ /* @__PURE__ */ jsx5(InputOTPSlot, { className: "h-12", index: 3 }),
744
+ /* @__PURE__ */ jsx5(InputOTPSlot, { className: "h-12", index: 4 }),
745
+ /* @__PURE__ */ jsx5(InputOTPSlot, { className: "h-12", index: 5 })
746
+ ] })
747
+ }
748
+ ) }),
749
+ fieldState.invalid && /* @__PURE__ */ jsx5(FieldError2, { errors: [fieldState.error] })
750
+ ] })
751
+ }
752
+ ),
753
+ /* @__PURE__ */ jsx5(
754
+ Controller2,
755
+ {
756
+ name: "password",
757
+ control: form.control,
758
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs3(Field2, { "data-invalid": fieldState.invalid, children: [
759
+ /* @__PURE__ */ jsx5(FieldLabel2, { htmlFor: "reset-password-password", children: t("form.passwordLabel") }),
760
+ /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
761
+ /* @__PURE__ */ jsx5(
762
+ Input2,
763
+ {
764
+ ...field,
765
+ id: "reset-password-password",
766
+ type: showPassword ? "text" : "password",
767
+ placeholder: t("form.passwordPlaceholder"),
768
+ "aria-invalid": fieldState.invalid
769
+ }
770
+ ),
771
+ /* @__PURE__ */ jsx5(
772
+ "button",
773
+ {
774
+ type: "button",
775
+ onClick: () => setShowPassword(!showPassword),
776
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
777
+ children: showPassword ? /* @__PURE__ */ jsx5(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx5(IconEye, { className: "h-4 w-4" })
778
+ }
779
+ )
780
+ ] }),
781
+ fieldState.invalid && /* @__PURE__ */ jsx5(FieldError2, { errors: [fieldState.error] })
782
+ ] })
783
+ }
784
+ ),
785
+ /* @__PURE__ */ jsx5(
786
+ Controller2,
787
+ {
788
+ name: "confirmPassword",
789
+ control: form.control,
790
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs3(Field2, { "data-invalid": fieldState.invalid, children: [
791
+ /* @__PURE__ */ jsx5(FieldLabel2, { htmlFor: "reset-password-confirmPassword", children: t("form.confirmPasswordLabel") }),
792
+ /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
793
+ /* @__PURE__ */ jsx5(
794
+ Input2,
795
+ {
796
+ ...field,
797
+ id: "reset-password-confirmPassword",
798
+ type: showPassword ? "text" : "password",
799
+ placeholder: t("form.passwordPlaceholder"),
800
+ "aria-invalid": fieldState.invalid
801
+ }
802
+ ),
803
+ /* @__PURE__ */ jsx5(
804
+ "button",
805
+ {
806
+ type: "button",
807
+ onClick: () => setShowPassword(!showPassword),
808
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
809
+ children: showPassword ? /* @__PURE__ */ jsx5(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx5(IconEye, { className: "h-4 w-4" })
810
+ }
811
+ )
812
+ ] }),
813
+ fieldState.invalid && /* @__PURE__ */ jsx5(FieldError2, { errors: [fieldState.error] })
814
+ ] })
815
+ }
816
+ )
817
+ ] }),
818
+ /* @__PURE__ */ jsx5("div", { className: "mt-4", children: /* @__PURE__ */ jsxs3(
819
+ Button2,
820
+ {
821
+ type: "submit",
822
+ form: "reset-password-form",
823
+ className: "w-full",
824
+ disabled: isLoading || resetPasswordMutation.isPending,
825
+ children: [
826
+ isLoading || resetPasswordMutation.isPending && /* @__PURE__ */ jsx5(Spinner2, {}),
827
+ isLoading || resetPasswordMutation.isPending ? t("form.submitting") : t("form.submit")
828
+ ]
829
+ }
830
+ ) })
831
+ ] }),
832
+ errorContent && /* @__PURE__ */ jsxs3(Alert2, { variant: "destructive", className: "mt-4", children: [
833
+ /* @__PURE__ */ jsx5(IconAlertCircle2, { className: "h-4 w-4" }),
834
+ /* @__PURE__ */ jsx5(AlertTitle2, { children: errorContent.title }),
835
+ /* @__PURE__ */ jsx5(AlertDescription2, { children: errorContent.description })
864
836
  ] })
865
837
  ]
866
838
  }
867
839
  );
868
840
  };
869
841
 
870
- // src/components/auth/pages/sign-in-page.tsx
842
+ // src/components/auth/sign-in.tsx
843
+ import { zodResolver as zodResolver3 } from "@hookform/resolvers/zod";
871
844
  import {
872
845
  Alert as Alert3,
873
846
  AlertDescription as AlertDescription3,
874
847
  AlertTitle as AlertTitle3
875
848
  } from "@mesob/ui/components/alert";
876
- import { toast as toast3 } from "@mesob/ui/components/sonner";
877
- import { IconAlertCircle as IconAlertCircle3 } from "@tabler/icons-react";
878
- import { useEffect as useEffect5, useState as useState6 } from "react";
879
-
880
- // src/components/auth/sign-in.tsx
881
- import { zodResolver as zodResolver3 } from "@hookform/resolvers/zod";
882
849
  import { Button as Button3 } from "@mesob/ui/components/button";
883
850
  import {
884
851
  Field as Field3,
@@ -887,39 +854,41 @@ import {
887
854
  FieldLabel as FieldLabel3
888
855
  } from "@mesob/ui/components/field";
889
856
  import { Input as Input3 } from "@mesob/ui/components/input";
857
+ import { useMesob as useMesob3 } from "@mesob/ui/components/mesob-context";
890
858
  import { Spinner as Spinner3 } from "@mesob/ui/components/spinner";
891
- import { IconEye as IconEye2, IconEyeOff as IconEyeOff2 } from "@tabler/icons-react";
892
- import { useEffect as useEffect4, useState as useState5 } from "react";
859
+ import { IconAlertCircle as IconAlertCircle3, IconEye as IconEye2, IconEyeOff as IconEyeOff2 } from "@tabler/icons-react";
860
+ import { useEffect as useEffect3, useState as useState4 } from "react";
893
861
  import { Controller as Controller3, useForm as useForm3 } from "react-hook-form";
862
+ import { toast as toast3 } from "sonner";
894
863
  import { z as z3 } from "zod";
895
864
 
896
865
  // src/utils/normalize-phone.ts
897
866
  function normalizePhone(phone) {
898
867
  const cleaned = phone.trim().replace(/\s/g, "");
899
- if (cleaned.startsWith("+2519")) {
868
+ if (cleaned.startsWith("+2519") || cleaned.startsWith("+2517")) {
900
869
  return cleaned;
901
870
  }
902
- if (cleaned.startsWith("2519")) {
871
+ if (cleaned.startsWith("2519") || cleaned.startsWith("2517")) {
903
872
  return `+${cleaned}`;
904
873
  }
905
- if (cleaned.startsWith("09")) {
874
+ if (cleaned.startsWith("09") || cleaned.startsWith("07")) {
906
875
  return `+251${cleaned.slice(1)}`;
907
876
  }
908
- if (cleaned.startsWith("9") && cleaned.length === 9) {
877
+ if ((cleaned.startsWith("9") || cleaned.startsWith("7")) && cleaned.length === 9) {
909
878
  return `+251${cleaned}`;
910
879
  }
911
880
  return cleaned;
912
881
  }
913
882
 
914
883
  // src/components/auth/sign-in.tsx
915
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
916
- var identifierSchema = (t) => z3.object({
917
- identifier: z3.string().trim().min(1, { message: t("errors.requiredField") }).refine(
884
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
885
+ var isPhone = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
886
+ var usernameSchema = (t, phoneRegex) => z3.object({
887
+ username: z3.string().trim().min(1, { message: t("errors.requiredField") }).refine(
918
888
  (val) => {
919
889
  const isEmail = z3.email().safeParse(val).success;
920
- const phoneRegex = /^(\+2519|2519|09)\d{8}$/;
921
- const isPhone4 = phoneRegex.test(val);
922
- return isEmail || isPhone4;
890
+ const isPhone3 = phoneRegex.test(val);
891
+ return isEmail || isPhone3;
923
892
  },
924
893
  {
925
894
  message: t("errors.invalidEmailOrPhone")
@@ -929,253 +898,111 @@ var identifierSchema = (t) => z3.object({
929
898
  var passwordSchema = (t) => z3.object({
930
899
  password: z3.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError"))
931
900
  });
932
- var SignIn = ({
933
- onSubmit,
934
- isLoading = false,
935
- identifier: initialIdentifier = "",
936
- step = "identifier",
937
- onBack: _onBack
938
- }) => {
939
- const { hooks } = useApi();
940
- const t = useTranslator("Auth.signIn");
941
- const [showPassword, setShowPassword] = useState5(false);
942
- const [currentIdentifier, setCurrentIdentifier] = useState5(initialIdentifier);
943
- const identifierForm = useForm3({
944
- resolver: zodResolver3(identifierSchema(t)),
945
- defaultValues: {
946
- identifier: initialIdentifier
947
- },
948
- mode: "onChange"
949
- });
950
- const passwordForm = useForm3({
951
- resolver: zodResolver3(passwordSchema(t)),
952
- defaultValues: {
953
- password: ""
954
- },
955
- mode: "onChange"
956
- });
957
- const signInMutation = hooks.useMutation("post", "/sign-in");
958
- useEffect4(() => {
959
- if (initialIdentifier) {
960
- identifierForm.setValue("identifier", initialIdentifier);
961
- setCurrentIdentifier(initialIdentifier);
962
- }
963
- }, [initialIdentifier, identifierForm]);
964
- const handleIdentifierSubmit = async (values) => {
965
- const phoneRegex = /^(\+2519|2519|09)\d{8}$/;
966
- const normalizedIdentifier = phoneRegex.test(values.identifier) ? normalizePhone(values.identifier) : values.identifier;
967
- setCurrentIdentifier(normalizedIdentifier);
968
- identifierForm.setValue("identifier", normalizedIdentifier);
969
- await onSubmit(
970
- { identifier: normalizedIdentifier, password: "" },
971
- "identifier"
972
- );
973
- };
974
- const handlePasswordSubmit = async (values) => {
975
- try {
976
- await signInMutation.mutateAsync({
977
- body: {
978
- identifier: currentIdentifier || identifierForm.getValues("identifier"),
979
- password: values.password
980
- }
981
- });
982
- await onSubmit(
983
- {
984
- identifier: currentIdentifier || identifierForm.getValues("identifier"),
985
- password: values.password
986
- },
987
- "password"
988
- );
989
- } catch {
990
- await onSubmit(
991
- {
992
- identifier: currentIdentifier || identifierForm.getValues("identifier"),
993
- password: values.password
994
- },
995
- "password"
996
- );
997
- }
998
- };
999
- const isPasswordStep = step === "password";
1000
- const isSubmitting = isLoading || signInMutation.isPending;
1001
- if (isPasswordStep) {
1002
- return /* @__PURE__ */ jsxs6(
1003
- "form",
1004
- {
1005
- id: "sign-in-password-form",
1006
- onSubmit: passwordForm.handleSubmit(handlePasswordSubmit),
1007
- children: [
1008
- /* @__PURE__ */ jsxs6(FieldGroup3, { children: [
1009
- /* @__PURE__ */ jsxs6("div", { className: "text-center", children: [
1010
- /* @__PURE__ */ jsx8("p", { className: "text-sm text-muted-foreground mb-2", children: t("form.enterPasswordFor") }),
1011
- /* @__PURE__ */ jsx8("p", { className: "font-bold", children: currentIdentifier || identifierForm.getValues("identifier") })
1012
- ] }),
1013
- /* @__PURE__ */ jsx8(
1014
- Controller3,
1015
- {
1016
- name: "password",
1017
- control: passwordForm.control,
1018
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs6(Field3, { "data-invalid": fieldState.invalid, children: [
1019
- /* @__PURE__ */ jsx8(FieldLabel3, { htmlFor: "sign-in-password", children: t("form.passwordLabel") }),
1020
- /* @__PURE__ */ jsxs6("div", { className: "relative", children: [
1021
- /* @__PURE__ */ jsx8(
1022
- Input3,
1023
- {
1024
- ...field,
1025
- id: "sign-in-password",
1026
- type: showPassword ? "text" : "password",
1027
- placeholder: t("form.passwordPlaceholder"),
1028
- autoComplete: "current-password",
1029
- "aria-invalid": fieldState.invalid
1030
- }
1031
- ),
1032
- /* @__PURE__ */ jsx8(
1033
- "button",
1034
- {
1035
- type: "button",
1036
- onClick: () => setShowPassword(!showPassword),
1037
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1038
- children: showPassword ? /* @__PURE__ */ jsx8(IconEyeOff2, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx8(IconEye2, { className: "h-4 w-4" })
1039
- }
1040
- )
1041
- ] }),
1042
- fieldState.invalid && /* @__PURE__ */ jsx8(FieldError3, { errors: [fieldState.error] })
1043
- ] })
1044
- }
1045
- )
1046
- ] }),
1047
- /* @__PURE__ */ jsx8("div", { className: "mt-4", children: /* @__PURE__ */ jsxs6(Button3, { type: "submit", className: "w-full", disabled: isSubmitting, children: [
1048
- isSubmitting && /* @__PURE__ */ jsx8(Spinner3, {}),
1049
- isSubmitting ? t("form.submitting") : t("form.submit")
1050
- ] }) })
1051
- ]
1052
- }
1053
- );
1054
- }
1055
- return /* @__PURE__ */ jsxs6(
1056
- "form",
1057
- {
1058
- id: "sign-in-identifier-form",
1059
- onSubmit: identifierForm.handleSubmit(handleIdentifierSubmit),
1060
- children: [
1061
- /* @__PURE__ */ jsx8(FieldGroup3, { children: /* @__PURE__ */ jsx8(
1062
- Controller3,
1063
- {
1064
- name: "identifier",
1065
- control: identifierForm.control,
1066
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs6(Field3, { "data-invalid": fieldState.invalid, children: [
1067
- /* @__PURE__ */ jsx8(FieldLabel3, { htmlFor: "sign-in-identifier", children: t("form.accountLabel") }),
1068
- /* @__PURE__ */ jsx8(
1069
- Input3,
1070
- {
1071
- ...field,
1072
- id: "sign-in-identifier",
1073
- type: "text",
1074
- placeholder: t("form.accountPlaceholder"),
1075
- autoComplete: "username",
1076
- "aria-invalid": fieldState.invalid
1077
- }
1078
- ),
1079
- fieldState.invalid && /* @__PURE__ */ jsx8(FieldError3, { errors: [fieldState.error] })
1080
- ] })
1081
- }
1082
- ) }),
1083
- /* @__PURE__ */ jsx8("div", { className: "mt-4", children: /* @__PURE__ */ jsxs6(Button3, { type: "submit", className: "w-full", disabled: isSubmitting, children: [
1084
- isSubmitting && /* @__PURE__ */ jsx8(Spinner3, {}),
1085
- isSubmitting ? t("form.submitting") : t("form.continue")
1086
- ] }) })
1087
- ]
1088
- }
1089
- );
1090
- };
1091
-
1092
- // src/components/auth/pages/sign-in-page.tsx
1093
- import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1094
- var isPhone = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
1095
- var SignInPage = ({ redirectUrl } = {}) => {
901
+ var SignIn = ({ redirectUrl } = {}) => {
1096
902
  const { hooks, setAuth } = useApi();
1097
903
  const { config } = useConfig();
1098
- const t = createTranslator(config.messages || {}, "Auth.signIn");
1099
- const [isLoading, setIsLoading] = useState6(false);
1100
- const [error, setError] = useState6(null);
1101
- const [step, setStep] = useState6("identifier");
1102
- const [identifier, setIdentifier] = useState6("");
1103
- const checkUserMutation = hooks.useMutation("post", "/check-user");
904
+ const mesob = useMesob3();
905
+ const t = useTranslator("Auth.signIn");
906
+ const Link3 = mesob?.linkComponent ?? config.navigation?.linkComponent;
907
+ const [isLoading, setIsLoading] = useState4(false);
908
+ const [error, setError] = useState4(null);
909
+ const [showPasswordField, setShowPasswordField] = useState4(false);
910
+ const [showPassword, setShowPassword] = useState4(false);
911
+ const [username, setUsername] = useState4("");
912
+ const [isChecking, setIsChecking] = useState4(false);
913
+ const checkUserMutation = hooks.useMutation("post", "/check-account");
1104
914
  const signInMutation = hooks.useMutation("post", "/sign-in");
915
+ const phoneRegex = typeof config.phoneRegex === "string" ? new RegExp(config.phoneRegex) : config.phoneRegex || /^(\+2519|\+2517|2519|2517|09|07)\d{8}$/;
1105
916
  const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/dashboard";
1106
917
  const forgotPasswordLink = config.navigation?.links?.forgotPassword || "/auth/forgot-password";
1107
918
  const signUpLink = config.navigation?.links?.signUp || "/auth/sign-up";
1108
- const Link = config.navigation?.linkComponent;
1109
919
  const onNavigate = config.navigation?.onNavigate || ((path) => {
1110
920
  if (typeof window !== "undefined") {
1111
921
  window.location.href = path;
1112
922
  }
1113
923
  });
1114
924
  const logoImage = config.ui.logoImage;
1115
- useEffect5(() => {
925
+ const usernameForm = useForm3({
926
+ resolver: zodResolver3(usernameSchema(t, phoneRegex)),
927
+ defaultValues: { username: "" },
928
+ mode: "onChange"
929
+ });
930
+ const passwordForm = useForm3({
931
+ resolver: zodResolver3(passwordSchema(t)),
932
+ defaultValues: { password: "" },
933
+ mode: "onChange"
934
+ });
935
+ useEffect3(() => {
1116
936
  if (error) {
1117
937
  toast3.error(error.title || "Error", {
1118
938
  description: error.description
1119
939
  });
1120
940
  }
1121
941
  }, [error]);
1122
- const handleIdentifierStep = async (identifierValue) => {
1123
- const checkResult = await checkUserMutation.mutateAsync({
1124
- body: {
1125
- identifier: identifierValue
942
+ const handleCheckAccount = async (usernameValue) => {
943
+ setIsChecking(true);
944
+ try {
945
+ const normalizedUsername = phoneRegex.test(usernameValue) ? normalizePhone(usernameValue) : usernameValue;
946
+ const result = await checkUserMutation.mutateAsync({
947
+ body: {
948
+ username: normalizedUsername
949
+ }
950
+ });
951
+ if (result.exists) {
952
+ setUsername(normalizedUsername);
953
+ setShowPasswordField(true);
954
+ } else {
955
+ const email = isPhone(normalizedUsername) ? "" : normalizedUsername;
956
+ if (email) {
957
+ onNavigate(`${signUpLink}?email=${encodeURIComponent(email)}`);
958
+ } else {
959
+ onNavigate(
960
+ `${signUpLink}?phone=${encodeURIComponent(normalizedUsername)}`
961
+ );
962
+ }
1126
963
  }
1127
- });
1128
- if (checkResult.exists) {
1129
- setIdentifier(identifierValue);
1130
- setStep("password");
1131
- return;
1132
- }
1133
- const email = isPhone(identifierValue) ? "" : identifierValue;
1134
- if (email) {
1135
- onNavigate(`${signUpLink}?email=${encodeURIComponent(email)}`);
1136
- } else {
1137
- onNavigate(`${signUpLink}?phone=${encodeURIComponent(identifierValue)}`);
964
+ } catch {
965
+ usernameForm.setError("username", {
966
+ message: t("errors.checkAccountFailed")
967
+ });
968
+ } finally {
969
+ setIsChecking(false);
1138
970
  }
1139
971
  };
1140
- const handlePasswordStep = async (passwordValue) => {
1141
- const res = await signInMutation.mutateAsync({
1142
- body: {
1143
- identifier,
1144
- password: passwordValue
1145
- }
1146
- });
1147
- if ("verificationId" in res && res.verificationId) {
1148
- const verifyPath = isPhone(identifier) ? `/auth/verify-phone?context=sign-in&verificationId=${res.verificationId}&identifier=${encodeURIComponent(identifier)}` : `/auth/verify-email?verificationId=${res.verificationId}`;
1149
- onNavigate(verifyPath);
1150
- return;
1151
- }
1152
- if ("user" in res && "session" in res) {
1153
- setAuth(res);
1154
- }
1155
- onNavigate(defaultRedirect);
972
+ const handleUsernameSubmit = async (values) => {
973
+ await handleCheckAccount(values.username);
1156
974
  };
1157
- const handleSubmit = async (values, currentStep) => {
975
+ const handlePasswordSubmit = async (values) => {
1158
976
  setIsLoading(true);
1159
977
  setError(null);
1160
978
  try {
1161
- if (currentStep === "identifier") {
1162
- await handleIdentifierStep(values.identifier);
1163
- } else {
1164
- await handlePasswordStep(values.password || "");
979
+ const res = await signInMutation.mutateAsync({
980
+ body: {
981
+ identifier: username,
982
+ password: values.password
983
+ }
984
+ });
985
+ if ("verificationId" in res && res.verificationId) {
986
+ const verifyPath = isPhone(username) ? `/auth/verify-phone?context=sign-in&verificationId=${res.verificationId}&identifier=${encodeURIComponent(username)}` : `/auth/verify-email?verificationId=${res.verificationId}`;
987
+ onNavigate(verifyPath);
988
+ return;
1165
989
  }
990
+ if ("user" in res && "session" in res) {
991
+ setAuth(res);
992
+ }
993
+ onNavigate(defaultRedirect);
1166
994
  } catch (err) {
1167
995
  handleError(err, setError, t);
1168
996
  } finally {
1169
997
  setIsLoading(false);
1170
998
  }
1171
999
  };
1172
- const isSubmitting = isLoading || checkUserMutation.isPending || signInMutation.isPending;
1173
1000
  const handleBack = () => {
1174
- setStep("identifier");
1175
- setIdentifier("");
1176
- setError(null);
1001
+ setShowPasswordField(false);
1002
+ setUsername("");
1003
+ passwordForm.reset();
1177
1004
  };
1178
- const isStepPassword = step === "password";
1005
+ const isSubmitting = isLoading || checkUserMutation.isPending || signInMutation.isPending || isChecking;
1179
1006
  let errorContent = null;
1180
1007
  if (error) {
1181
1008
  if (typeof error === "string") {
@@ -1184,79 +1011,145 @@ var SignInPage = ({ redirectUrl } = {}) => {
1184
1011
  errorContent = error;
1185
1012
  }
1186
1013
  }
1187
- return /* @__PURE__ */ jsx9("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs7(
1188
- AuthPageLayout,
1014
+ const formContent = showPasswordField ? /* @__PURE__ */ jsxs4(
1015
+ "form",
1189
1016
  {
1190
- title: t("title"),
1191
- description: isStepPassword ? void 0 : t("description"),
1192
- logoImage,
1193
- footer: /* @__PURE__ */ jsxs7(
1194
- "div",
1195
- {
1196
- className: "flex items-center justify-center w-full gap-2",
1197
- style: {
1198
- justifyContent: isStepPassword ? "space-between" : "center"
1199
- },
1200
- children: [
1201
- isStepPassword && // biome-ignore lint/a11y/useKeyWithClickEvents: change account
1202
- /* @__PURE__ */ jsx9(
1203
- "p",
1017
+ id: "sign-in-form",
1018
+ onSubmit: passwordForm.handleSubmit(handlePasswordSubmit),
1019
+ children: [
1020
+ /* @__PURE__ */ jsxs4(FieldGroup3, { children: [
1021
+ /* @__PURE__ */ jsxs4("div", { className: "text-center mb-4", children: [
1022
+ /* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground mb-1", children: t("form.enterPasswordFor") }),
1023
+ /* @__PURE__ */ jsx6("p", { className: "font-medium text-foreground", children: username }),
1024
+ /* @__PURE__ */ jsx6(
1025
+ "button",
1204
1026
  {
1205
- className: "text-primary inline-block cursor-pointer hover:underline",
1027
+ type: "button",
1206
1028
  onClick: handleBack,
1029
+ className: "text-sm text-primary hover:underline mt-2",
1207
1030
  children: t("changeAccount")
1208
1031
  }
1209
- ),
1210
- Link ? /* @__PURE__ */ jsx9(
1211
- Link,
1212
- {
1213
- href: forgotPasswordLink,
1214
- className: "text-primary inline-block hover:underline",
1215
- children: t("footer.forgotPassword")
1216
- }
1217
- ) : /* @__PURE__ */ jsx9(
1218
- "a",
1219
- {
1220
- href: forgotPasswordLink,
1221
- className: "text-primary inline-block hover:underline",
1222
- children: t("footer.forgotPassword")
1223
- }
1224
1032
  )
1225
- ]
1226
- }
1227
- ),
1228
- children: [
1229
- /* @__PURE__ */ jsx9(
1230
- SignIn,
1231
- {
1232
- onSubmit: handleSubmit,
1233
- isLoading: isSubmitting,
1234
- identifier,
1235
- step
1236
- }
1237
- ),
1238
- errorContent && /* @__PURE__ */ jsxs7(Alert3, { variant: "destructive", className: "mt-4", children: [
1239
- /* @__PURE__ */ jsx9(IconAlertCircle3, { className: "h-4 w-4" }),
1240
- /* @__PURE__ */ jsx9(AlertTitle3, { children: errorContent.title }),
1241
- /* @__PURE__ */ jsx9(AlertDescription3, { children: errorContent.description })
1033
+ ] }),
1034
+ /* @__PURE__ */ jsx6(
1035
+ Controller3,
1036
+ {
1037
+ name: "password",
1038
+ control: passwordForm.control,
1039
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs4(Field3, { "data-invalid": fieldState.invalid, children: [
1040
+ /* @__PURE__ */ jsx6(FieldLabel3, { htmlFor: "sign-in-password", children: t("form.passwordLabel") }),
1041
+ /* @__PURE__ */ jsxs4("div", { className: "relative", children: [
1042
+ /* @__PURE__ */ jsx6(
1043
+ Input3,
1044
+ {
1045
+ ...field,
1046
+ id: "sign-in-password",
1047
+ type: showPassword ? "text" : "password",
1048
+ placeholder: t("form.passwordPlaceholder"),
1049
+ autoComplete: "current-password",
1050
+ "aria-invalid": fieldState.invalid
1051
+ }
1052
+ ),
1053
+ /* @__PURE__ */ jsx6(
1054
+ "button",
1055
+ {
1056
+ type: "button",
1057
+ onClick: () => setShowPassword(!showPassword),
1058
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1059
+ children: showPassword ? /* @__PURE__ */ jsx6(IconEyeOff2, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx6(IconEye2, { className: "h-4 w-4" })
1060
+ }
1061
+ )
1062
+ ] }),
1063
+ fieldState.invalid && /* @__PURE__ */ jsx6(FieldError3, { errors: [fieldState.error] })
1064
+ ] })
1065
+ }
1066
+ )
1067
+ ] }),
1068
+ /* @__PURE__ */ jsx6("div", { className: "mt-4", children: /* @__PURE__ */ jsxs4(Button3, { type: "submit", className: "w-full", disabled: isSubmitting, children: [
1069
+ isSubmitting && /* @__PURE__ */ jsx6(Spinner3, {}),
1070
+ isSubmitting ? t("form.submitting") : t("form.submit")
1071
+ ] }) })
1072
+ ]
1073
+ }
1074
+ ) : /* @__PURE__ */ jsxs4(
1075
+ "form",
1076
+ {
1077
+ id: "sign-in-form",
1078
+ onSubmit: usernameForm.handleSubmit(handleUsernameSubmit),
1079
+ children: [
1080
+ /* @__PURE__ */ jsx6(FieldGroup3, { children: /* @__PURE__ */ jsx6(
1081
+ Controller3,
1082
+ {
1083
+ name: "username",
1084
+ control: usernameForm.control,
1085
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs4(Field3, { "data-invalid": fieldState.invalid, children: [
1086
+ /* @__PURE__ */ jsx6(FieldLabel3, { htmlFor: "sign-in-username", children: t("form.accountLabel") }),
1087
+ /* @__PURE__ */ jsx6(
1088
+ Input3,
1089
+ {
1090
+ ...field,
1091
+ id: "sign-in-username",
1092
+ type: "text",
1093
+ placeholder: t("form.accountPlaceholder"),
1094
+ autoComplete: "username",
1095
+ "aria-invalid": fieldState.invalid
1096
+ }
1097
+ ),
1098
+ fieldState.invalid && /* @__PURE__ */ jsx6(FieldError3, { errors: [fieldState.error] })
1099
+ ] })
1100
+ }
1101
+ ) }),
1102
+ /* @__PURE__ */ jsx6("div", { className: "mt-4", children: /* @__PURE__ */ jsxs4(Button3, { type: "submit", className: "w-full", disabled: isSubmitting, children: [
1103
+ isSubmitting && /* @__PURE__ */ jsx6(Spinner3, {}),
1104
+ isSubmitting ? t("form.submitting") : t("form.continue")
1105
+ ] }) })
1106
+ ]
1107
+ }
1108
+ );
1109
+ return /* @__PURE__ */ jsx6("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs4(
1110
+ AuthLayout,
1111
+ {
1112
+ title: t("title"),
1113
+ description: t("description"),
1114
+ logoImage,
1115
+ footer: showPasswordField ? /* @__PURE__ */ jsx6("div", { className: "flex items-center justify-center w-full", children: Link3 ? /* @__PURE__ */ jsx6(
1116
+ Link3,
1117
+ {
1118
+ href: forgotPasswordLink,
1119
+ className: "text-primary inline-block hover:underline",
1120
+ children: t("footer.forgotPassword")
1121
+ }
1122
+ ) : /* @__PURE__ */ jsx6(
1123
+ "a",
1124
+ {
1125
+ href: forgotPasswordLink,
1126
+ onClick: (e) => {
1127
+ e.preventDefault();
1128
+ onNavigate(forgotPasswordLink);
1129
+ },
1130
+ className: "text-primary inline-block hover:underline",
1131
+ children: t("footer.forgotPassword")
1132
+ }
1133
+ ) }) : void 0,
1134
+ children: [
1135
+ formContent,
1136
+ errorContent && /* @__PURE__ */ jsxs4(Alert3, { variant: "destructive", className: "mt-4", children: [
1137
+ /* @__PURE__ */ jsx6(IconAlertCircle3, { className: "h-4 w-4" }),
1138
+ /* @__PURE__ */ jsx6(AlertTitle3, { children: errorContent.title }),
1139
+ /* @__PURE__ */ jsx6(AlertDescription3, { children: errorContent.description })
1242
1140
  ] })
1243
1141
  ]
1244
1142
  }
1245
1143
  ) });
1246
1144
  };
1247
1145
 
1248
- // src/components/auth/pages/sign-up-page.tsx
1146
+ // src/components/auth/sign-up.tsx
1147
+ import { zodResolver as zodResolver4 } from "@hookform/resolvers/zod";
1249
1148
  import {
1250
1149
  Alert as Alert4,
1251
1150
  AlertDescription as AlertDescription4,
1252
1151
  AlertTitle as AlertTitle4
1253
1152
  } from "@mesob/ui/components/alert";
1254
- import { toast as toast4 } from "@mesob/ui/components/sonner";
1255
- import { IconAlertCircle as IconAlertCircle4 } from "@tabler/icons-react";
1256
- import { useEffect as useEffect7, useState as useState8 } from "react";
1257
-
1258
- // src/components/auth/sign-up.tsx
1259
- import { zodResolver as zodResolver4 } from "@hookform/resolvers/zod";
1260
1153
  import { Button as Button4 } from "@mesob/ui/components/button";
1261
1154
  import {
1262
1155
  Field as Field4,
@@ -1265,11 +1158,13 @@ import {
1265
1158
  FieldLabel as FieldLabel4
1266
1159
  } from "@mesob/ui/components/field";
1267
1160
  import { Input as Input4 } from "@mesob/ui/components/input";
1268
- import { IconEye as IconEye3, IconEyeOff as IconEyeOff3 } from "@tabler/icons-react";
1269
- import { useEffect as useEffect6, useState as useState7 } from "react";
1161
+ import { useMesob as useMesob4 } from "@mesob/ui/components/mesob-context";
1162
+ import { IconAlertCircle as IconAlertCircle4, IconEye as IconEye3, IconEyeOff as IconEyeOff3 } from "@tabler/icons-react";
1163
+ import { useEffect as useEffect4, useState as useState5 } from "react";
1270
1164
  import { Controller as Controller4, useForm as useForm4 } from "react-hook-form";
1165
+ import { toast as toast4 } from "sonner";
1271
1166
  import { z as z4 } from "zod";
1272
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1167
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1273
1168
  var isPhone2 = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
1274
1169
  var signUpSchema = (t) => z4.object({
1275
1170
  fullName: z4.string().min(1, t("errors.fullNameRequired")),
@@ -1291,14 +1186,28 @@ var signUpSchema = (t) => z4.object({
1291
1186
  path: ["confirmPassword"]
1292
1187
  });
1293
1188
  var SignUp = ({
1294
- onSubmit,
1295
- isLoading = false,
1189
+ redirectUrl,
1296
1190
  initialIdentifier
1297
- }) => {
1191
+ } = {}) => {
1192
+ const { hooks, setAuth } = useApi();
1193
+ const { config } = useConfig();
1194
+ const mesob = useMesob4();
1298
1195
  const t = useTranslator("Auth.signUp");
1196
+ const Link3 = mesob?.linkComponent ?? config.navigation?.linkComponent;
1197
+ const [isLoading, setIsLoading] = useState5(false);
1198
+ const [error, setError] = useState5(null);
1199
+ const [showPassword, setShowPassword] = useState5(false);
1200
+ const [showConfirmPassword, setShowConfirmPassword] = useState5(false);
1201
+ const signUpMutation = hooks.useMutation("post", "/sign-up");
1202
+ const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
1203
+ const onNavigate = config.navigation?.onNavigate || ((path) => {
1204
+ if (typeof window !== "undefined") {
1205
+ window.location.href = path;
1206
+ }
1207
+ });
1208
+ const logoImage = config.ui.logoImage;
1209
+ const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
1299
1210
  const hasInitialIdentifier = !!initialIdentifier;
1300
- const [showPassword, setShowPassword] = useState7(false);
1301
- const [showConfirmPassword, setShowConfirmPassword] = useState7(false);
1302
1211
  const form = useForm4({
1303
1212
  resolver: zodResolver4(signUpSchema(t)),
1304
1213
  defaultValues: {
@@ -1308,188 +1217,24 @@ var SignUp = ({
1308
1217
  confirmPassword: ""
1309
1218
  }
1310
1219
  });
1311
- useEffect6(() => {
1220
+ useEffect4(() => {
1312
1221
  if (initialIdentifier) {
1313
1222
  form.setValue("identifier", initialIdentifier);
1314
1223
  }
1315
1224
  }, [initialIdentifier, form]);
1316
- const handleSubmit = form.handleSubmit(async (values) => {
1317
- await onSubmit(values);
1318
- });
1319
- const getIdentifierLabel = () => {
1320
- if (!hasInitialIdentifier) {
1321
- return t("form.accountLabel") || "Email/Phone";
1322
- }
1323
- if (initialIdentifier?.includes("@")) {
1324
- return t("form.emailLabel");
1325
- }
1326
- return t("form.phoneLabel");
1327
- };
1328
- const identifierLabel = getIdentifierLabel();
1329
- return /* @__PURE__ */ jsxs8("form", { id: "sign-up-form", onSubmit: handleSubmit, children: [
1330
- /* @__PURE__ */ jsxs8(FieldGroup4, { children: [
1331
- /* @__PURE__ */ jsx10(
1332
- Controller4,
1333
- {
1334
- name: "fullName",
1335
- control: form.control,
1336
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs8(Field4, { "data-invalid": fieldState.invalid, children: [
1337
- /* @__PURE__ */ jsx10(FieldLabel4, { htmlFor: "sign-up-fullName", children: t("form.fullNameLabel") }),
1338
- /* @__PURE__ */ jsx10(
1339
- Input4,
1340
- {
1341
- ...field,
1342
- id: "sign-up-fullName",
1343
- placeholder: t("form.fullNamePlaceholder"),
1344
- "aria-invalid": fieldState.invalid
1345
- }
1346
- ),
1347
- fieldState.invalid && /* @__PURE__ */ jsx10(FieldError4, { errors: [fieldState.error] })
1348
- ] })
1349
- }
1350
- ),
1351
- /* @__PURE__ */ jsx10(
1352
- Controller4,
1353
- {
1354
- name: "identifier",
1355
- control: form.control,
1356
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs8(Field4, { "data-invalid": fieldState.invalid, children: [
1357
- /* @__PURE__ */ jsx10(
1358
- FieldLabel4,
1359
- {
1360
- htmlFor: "sign-up-identifier",
1361
- className: hasInitialIdentifier ? "block" : void 0,
1362
- children: identifierLabel
1363
- }
1364
- ),
1365
- /* @__PURE__ */ jsx10(
1366
- Input4,
1367
- {
1368
- ...field,
1369
- id: "sign-up-identifier",
1370
- type: field.value.includes("@") ? "email" : "tel",
1371
- placeholder: hasInitialIdentifier ? void 0 : t("form.accountPlaceholder") || "Email or phone number",
1372
- disabled: hasInitialIdentifier,
1373
- "aria-invalid": fieldState.invalid
1374
- }
1375
- ),
1376
- fieldState.invalid && /* @__PURE__ */ jsx10(FieldError4, { errors: [fieldState.error] })
1377
- ] })
1378
- }
1379
- ),
1380
- /* @__PURE__ */ jsx10(
1381
- Controller4,
1382
- {
1383
- name: "password",
1384
- control: form.control,
1385
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs8(Field4, { "data-invalid": fieldState.invalid, children: [
1386
- /* @__PURE__ */ jsx10(FieldLabel4, { htmlFor: "sign-up-password", children: t("form.passwordLabel") }),
1387
- /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
1388
- /* @__PURE__ */ jsx10(
1389
- Input4,
1390
- {
1391
- ...field,
1392
- id: "sign-up-password",
1393
- type: showPassword ? "text" : "password",
1394
- placeholder: t("form.passwordPlaceholder"),
1395
- "aria-invalid": fieldState.invalid
1396
- }
1397
- ),
1398
- /* @__PURE__ */ jsx10(
1399
- "button",
1400
- {
1401
- type: "button",
1402
- onClick: () => setShowPassword(!showPassword),
1403
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1404
- children: showPassword ? /* @__PURE__ */ jsx10(IconEyeOff3, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx10(IconEye3, { className: "h-4 w-4" })
1405
- }
1406
- )
1407
- ] }),
1408
- fieldState.invalid && /* @__PURE__ */ jsx10(FieldError4, { errors: [fieldState.error] })
1409
- ] })
1410
- }
1411
- ),
1412
- /* @__PURE__ */ jsx10(
1413
- Controller4,
1414
- {
1415
- name: "confirmPassword",
1416
- control: form.control,
1417
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs8(Field4, { "data-invalid": fieldState.invalid, children: [
1418
- /* @__PURE__ */ jsx10(FieldLabel4, { htmlFor: "sign-up-confirmPassword", children: t("form.confirmPasswordLabel") }),
1419
- /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
1420
- /* @__PURE__ */ jsx10(
1421
- Input4,
1422
- {
1423
- ...field,
1424
- id: "sign-up-confirmPassword",
1425
- type: showConfirmPassword ? "text" : "password",
1426
- placeholder: t("form.passwordPlaceholder"),
1427
- "aria-invalid": fieldState.invalid
1428
- }
1429
- ),
1430
- /* @__PURE__ */ jsx10(
1431
- "button",
1432
- {
1433
- type: "button",
1434
- onClick: () => setShowConfirmPassword(!showConfirmPassword),
1435
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1436
- children: showConfirmPassword ? /* @__PURE__ */ jsx10(IconEyeOff3, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx10(IconEye3, { className: "h-4 w-4" })
1437
- }
1438
- )
1439
- ] }),
1440
- fieldState.invalid && /* @__PURE__ */ jsx10(FieldError4, { errors: [fieldState.error] })
1441
- ] })
1442
- }
1443
- )
1444
- ] }),
1445
- /* @__PURE__ */ jsx10("div", { className: "mt-4", children: /* @__PURE__ */ jsx10(
1446
- Button4,
1447
- {
1448
- type: "submit",
1449
- form: "sign-up-form",
1450
- className: "w-full",
1451
- disabled: isLoading,
1452
- children: isLoading ? t("form.submitting") : t("form.submit")
1453
- }
1454
- ) })
1455
- ] });
1456
- };
1457
-
1458
- // src/components/auth/pages/sign-up-page.tsx
1459
- import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1460
- var isPhone3 = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
1461
- var SignUpPage = ({
1462
- redirectUrl,
1463
- initialIdentifier
1464
- } = {}) => {
1465
- const { hooks, setAuth } = useApi();
1466
- const { config } = useConfig();
1467
- const t = createTranslator(config.messages || {}, "Auth.signUp");
1468
- const [isLoading, setIsLoading] = useState8(false);
1469
- const [error, setError] = useState8(null);
1470
- const signUpMutation = hooks.useMutation("post", "/sign-up");
1471
- const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
1472
- const Link = config.navigation?.linkComponent;
1473
- const onNavigate = config.navigation?.onNavigate || ((path) => {
1474
- if (typeof window !== "undefined") {
1475
- window.location.href = path;
1476
- }
1477
- });
1478
- const logoImage = config.ui.logoImage;
1479
- const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
1480
- useEffect7(() => {
1225
+ useEffect4(() => {
1481
1226
  if (error) {
1482
1227
  toast4.error(error.title || "Error", {
1483
1228
  description: error.description
1484
1229
  });
1485
1230
  }
1486
1231
  }, [error]);
1487
- const handleSubmit = async (values) => {
1232
+ const handleSubmit = form.handleSubmit(async (values) => {
1488
1233
  setIsLoading(true);
1489
1234
  setError(null);
1490
1235
  try {
1491
1236
  const identifier = values.identifier;
1492
- const usingPhone = isPhone3(identifier);
1237
+ const usingPhone = isPhone2(identifier);
1493
1238
  const res = await signUpMutation.mutateAsync({
1494
1239
  body: usingPhone ? {
1495
1240
  phone: identifier,
@@ -1524,7 +1269,17 @@ var SignUpPage = ({
1524
1269
  } finally {
1525
1270
  setIsLoading(false);
1526
1271
  }
1272
+ });
1273
+ const getIdentifierLabel = () => {
1274
+ if (!hasInitialIdentifier) {
1275
+ return t("form.accountLabel") || "Email/Phone";
1276
+ }
1277
+ if (initialIdentifier?.includes("@")) {
1278
+ return t("form.emailLabel");
1279
+ }
1280
+ return t("form.phoneLabel");
1527
1281
  };
1282
+ const identifierLabel = getIdentifierLabel();
1528
1283
  let errorContent = null;
1529
1284
  if (error) {
1530
1285
  if (typeof error === "string") {
@@ -1533,16 +1288,16 @@ var SignUpPage = ({
1533
1288
  errorContent = error;
1534
1289
  }
1535
1290
  }
1536
- return /* @__PURE__ */ jsxs9(
1537
- AuthPageLayout,
1291
+ return /* @__PURE__ */ jsxs5(
1292
+ AuthLayout,
1538
1293
  {
1539
1294
  title: t("title"),
1540
1295
  description: t("description"),
1541
1296
  logoImage,
1542
- footer: /* @__PURE__ */ jsxs9("p", { children: [
1297
+ footer: /* @__PURE__ */ jsxs5("p", { children: [
1543
1298
  t("footer.hasAccount"),
1544
1299
  " ",
1545
- Link ? /* @__PURE__ */ jsx11(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.signInCta") }) : /* @__PURE__ */ jsx11(
1300
+ Link3 ? /* @__PURE__ */ jsx7(Link3, { href: signInLink, className: "text-primary hover:underline", children: t("footer.signInCta") }) : /* @__PURE__ */ jsx7(
1546
1301
  "a",
1547
1302
  {
1548
1303
  href: signInLink,
@@ -1556,34 +1311,143 @@ var SignUpPage = ({
1556
1311
  )
1557
1312
  ] }),
1558
1313
  children: [
1559
- /* @__PURE__ */ jsx11(
1560
- SignUp,
1561
- {
1562
- onSubmit: handleSubmit,
1563
- isLoading: isLoading || signUpMutation.isPending,
1564
- initialIdentifier
1565
- }
1566
- ),
1567
- errorContent && /* @__PURE__ */ jsxs9(Alert4, { variant: "destructive", className: "mt-4", children: [
1568
- /* @__PURE__ */ jsx11(IconAlertCircle4, { className: "h-4 w-4" }),
1569
- /* @__PURE__ */ jsx11(AlertTitle4, { children: errorContent.title }),
1570
- /* @__PURE__ */ jsx11(AlertDescription4, { children: errorContent.description })
1314
+ /* @__PURE__ */ jsxs5("form", { id: "sign-up-form", onSubmit: handleSubmit, children: [
1315
+ /* @__PURE__ */ jsxs5(FieldGroup4, { children: [
1316
+ /* @__PURE__ */ jsx7(
1317
+ Controller4,
1318
+ {
1319
+ name: "fullName",
1320
+ control: form.control,
1321
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs5(Field4, { "data-invalid": fieldState.invalid, children: [
1322
+ /* @__PURE__ */ jsx7(FieldLabel4, { htmlFor: "sign-up-fullName", children: t("form.fullNameLabel") }),
1323
+ /* @__PURE__ */ jsx7(
1324
+ Input4,
1325
+ {
1326
+ ...field,
1327
+ id: "sign-up-fullName",
1328
+ placeholder: t("form.fullNamePlaceholder"),
1329
+ "aria-invalid": fieldState.invalid
1330
+ }
1331
+ ),
1332
+ fieldState.invalid && /* @__PURE__ */ jsx7(FieldError4, { errors: [fieldState.error] })
1333
+ ] })
1334
+ }
1335
+ ),
1336
+ /* @__PURE__ */ jsx7(
1337
+ Controller4,
1338
+ {
1339
+ name: "identifier",
1340
+ control: form.control,
1341
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs5(Field4, { "data-invalid": fieldState.invalid, children: [
1342
+ /* @__PURE__ */ jsx7(
1343
+ FieldLabel4,
1344
+ {
1345
+ htmlFor: "sign-up-identifier",
1346
+ className: hasInitialIdentifier ? "block" : void 0,
1347
+ children: identifierLabel
1348
+ }
1349
+ ),
1350
+ /* @__PURE__ */ jsx7(
1351
+ Input4,
1352
+ {
1353
+ ...field,
1354
+ id: "sign-up-identifier",
1355
+ type: field.value.includes("@") ? "email" : "tel",
1356
+ placeholder: hasInitialIdentifier ? void 0 : t("form.accountPlaceholder") || "Email or phone number",
1357
+ disabled: hasInitialIdentifier,
1358
+ "aria-invalid": fieldState.invalid
1359
+ }
1360
+ ),
1361
+ fieldState.invalid && /* @__PURE__ */ jsx7(FieldError4, { errors: [fieldState.error] })
1362
+ ] })
1363
+ }
1364
+ ),
1365
+ /* @__PURE__ */ jsx7(
1366
+ Controller4,
1367
+ {
1368
+ name: "password",
1369
+ control: form.control,
1370
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs5(Field4, { "data-invalid": fieldState.invalid, children: [
1371
+ /* @__PURE__ */ jsx7(FieldLabel4, { htmlFor: "sign-up-password", children: t("form.passwordLabel") }),
1372
+ /* @__PURE__ */ jsxs5("div", { className: "relative", children: [
1373
+ /* @__PURE__ */ jsx7(
1374
+ Input4,
1375
+ {
1376
+ ...field,
1377
+ id: "sign-up-password",
1378
+ type: showPassword ? "text" : "password",
1379
+ placeholder: t("form.passwordPlaceholder"),
1380
+ "aria-invalid": fieldState.invalid
1381
+ }
1382
+ ),
1383
+ /* @__PURE__ */ jsx7(
1384
+ "button",
1385
+ {
1386
+ type: "button",
1387
+ onClick: () => setShowPassword(!showPassword),
1388
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1389
+ children: showPassword ? /* @__PURE__ */ jsx7(IconEyeOff3, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx7(IconEye3, { className: "h-4 w-4" })
1390
+ }
1391
+ )
1392
+ ] }),
1393
+ fieldState.invalid && /* @__PURE__ */ jsx7(FieldError4, { errors: [fieldState.error] })
1394
+ ] })
1395
+ }
1396
+ ),
1397
+ /* @__PURE__ */ jsx7(
1398
+ Controller4,
1399
+ {
1400
+ name: "confirmPassword",
1401
+ control: form.control,
1402
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs5(Field4, { "data-invalid": fieldState.invalid, children: [
1403
+ /* @__PURE__ */ jsx7(FieldLabel4, { htmlFor: "sign-up-confirmPassword", children: t("form.confirmPasswordLabel") }),
1404
+ /* @__PURE__ */ jsxs5("div", { className: "relative", children: [
1405
+ /* @__PURE__ */ jsx7(
1406
+ Input4,
1407
+ {
1408
+ ...field,
1409
+ id: "sign-up-confirmPassword",
1410
+ type: showConfirmPassword ? "text" : "password",
1411
+ placeholder: t("form.passwordPlaceholder"),
1412
+ "aria-invalid": fieldState.invalid
1413
+ }
1414
+ ),
1415
+ /* @__PURE__ */ jsx7(
1416
+ "button",
1417
+ {
1418
+ type: "button",
1419
+ onClick: () => setShowConfirmPassword(!showConfirmPassword),
1420
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1421
+ children: showConfirmPassword ? /* @__PURE__ */ jsx7(IconEyeOff3, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx7(IconEye3, { className: "h-4 w-4" })
1422
+ }
1423
+ )
1424
+ ] }),
1425
+ fieldState.invalid && /* @__PURE__ */ jsx7(FieldError4, { errors: [fieldState.error] })
1426
+ ] })
1427
+ }
1428
+ )
1429
+ ] }),
1430
+ /* @__PURE__ */ jsx7("div", { className: "mt-4", children: /* @__PURE__ */ jsx7(
1431
+ Button4,
1432
+ {
1433
+ type: "submit",
1434
+ form: "sign-up-form",
1435
+ className: "w-full",
1436
+ disabled: isLoading || signUpMutation.isPending,
1437
+ children: isLoading || signUpMutation.isPending ? t("form.submitting") : t("form.submit")
1438
+ }
1439
+ ) })
1440
+ ] }),
1441
+ errorContent && /* @__PURE__ */ jsxs5(Alert4, { variant: "destructive", className: "mt-4", children: [
1442
+ /* @__PURE__ */ jsx7(IconAlertCircle4, { className: "h-4 w-4" }),
1443
+ /* @__PURE__ */ jsx7(AlertTitle4, { children: errorContent.title }),
1444
+ /* @__PURE__ */ jsx7(AlertDescription4, { children: errorContent.description })
1571
1445
  ] })
1572
1446
  ]
1573
1447
  }
1574
1448
  );
1575
1449
  };
1576
1450
 
1577
- // src/components/auth/pages/verify-email-page.tsx
1578
- import {
1579
- Alert as Alert5,
1580
- AlertDescription as AlertDescription5,
1581
- AlertTitle as AlertTitle5
1582
- } from "@mesob/ui/components/alert";
1583
- import { toast as toast5 } from "@mesob/ui/components/sonner";
1584
- import { IconAlertCircle as IconAlertCircle5 } from "@tabler/icons-react";
1585
- import { useEffect as useEffect9, useState as useState10 } from "react";
1586
-
1587
1451
  // src/components/auth/verification-form.tsx
1588
1452
  import { zodResolver as zodResolver5 } from "@hookform/resolvers/zod";
1589
1453
  import { Button as Button6 } from "@mesob/ui/components/button";
@@ -1600,17 +1464,17 @@ import { z as z5 } from "zod";
1600
1464
  // src/components/auth/countdown.tsx
1601
1465
  import { Button as Button5 } from "@mesob/ui/components/button";
1602
1466
  import { Spinner as Spinner4 } from "@mesob/ui/components/spinner";
1603
- import { useEffect as useEffect8, useState as useState9 } from "react";
1604
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1467
+ import { useEffect as useEffect5, useState as useState6 } from "react";
1468
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1605
1469
  var Countdown = ({
1606
1470
  initialSeconds = 60,
1607
1471
  onResend,
1608
1472
  resending = false
1609
1473
  }) => {
1610
1474
  const t = useTranslator("Common");
1611
- const [seconds, setSeconds] = useState9(initialSeconds);
1612
- const [isResending, setIsResending] = useState9(false);
1613
- useEffect8(() => {
1475
+ const [seconds, setSeconds] = useState6(initialSeconds);
1476
+ const [isResending, setIsResending] = useState6(false);
1477
+ useEffect5(() => {
1614
1478
  if (seconds <= 0) {
1615
1479
  return;
1616
1480
  }
@@ -1636,16 +1500,16 @@ var Countdown = ({
1636
1500
  }
1637
1501
  };
1638
1502
  if (seconds > 0) {
1639
- return /* @__PURE__ */ jsx12(Button5, { variant: "ghost", disabled: true, children: t("resendIn", { seconds }) });
1503
+ return /* @__PURE__ */ jsx8(Button5, { variant: "ghost", disabled: true, children: t("resendIn", { seconds }) });
1640
1504
  }
1641
- return /* @__PURE__ */ jsxs10(
1505
+ return /* @__PURE__ */ jsxs6(
1642
1506
  Button5,
1643
1507
  {
1644
1508
  variant: "ghost",
1645
1509
  onClick: handleResend,
1646
1510
  disabled: isResending || resending,
1647
1511
  children: [
1648
- isResending || resending && /* @__PURE__ */ jsx12(Spinner4, {}),
1512
+ isResending || resending && /* @__PURE__ */ jsx8(Spinner4, {}),
1649
1513
  t("resend")
1650
1514
  ]
1651
1515
  }
@@ -1653,7 +1517,7 @@ var Countdown = ({
1653
1517
  };
1654
1518
 
1655
1519
  // src/components/auth/verification-form.tsx
1656
- import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1520
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1657
1521
  var verificationSchema = (t) => z5.object({
1658
1522
  code: z5.string().length(6, t("form.codeLength"))
1659
1523
  });
@@ -1672,14 +1536,14 @@ var VerificationForm = ({
1672
1536
  const handleSubmit = form.handleSubmit(async (values) => {
1673
1537
  await onSubmit(values);
1674
1538
  });
1675
- return /* @__PURE__ */ jsxs11("form", { id: "verification-form", onSubmit: handleSubmit, children: [
1676
- /* @__PURE__ */ jsx13(FieldGroup5, { children: /* @__PURE__ */ jsx13(
1539
+ return /* @__PURE__ */ jsxs7("form", { id: "verification-form", onSubmit: handleSubmit, children: [
1540
+ /* @__PURE__ */ jsx9(FieldGroup5, { children: /* @__PURE__ */ jsx9(
1677
1541
  Controller5,
1678
1542
  {
1679
1543
  name: "code",
1680
1544
  control: form.control,
1681
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs11(Field5, { "data-invalid": fieldState.invalid, children: [
1682
- /* @__PURE__ */ jsx13("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx13(
1545
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs7(Field5, { "data-invalid": fieldState.invalid, children: [
1546
+ /* @__PURE__ */ jsx9("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx9(
1683
1547
  InputOTP2,
1684
1548
  {
1685
1549
  maxLength: 6,
@@ -1690,30 +1554,30 @@ var VerificationForm = ({
1690
1554
  onBlur: field.onBlur,
1691
1555
  containerClassName: "gap-4 justify-center mb-2 flex items-center",
1692
1556
  "aria-invalid": fieldState.invalid,
1693
- children: /* @__PURE__ */ jsxs11(InputOTPGroup2, { 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: [
1694
- /* @__PURE__ */ jsx13(InputOTPSlot2, { className: "h-12", index: 0 }),
1695
- /* @__PURE__ */ jsx13(InputOTPSlot2, { className: "h-12", index: 1 }),
1696
- /* @__PURE__ */ jsx13(InputOTPSlot2, { className: "h-12", index: 2 }),
1697
- /* @__PURE__ */ jsx13(InputOTPSlot2, { className: "h-12", index: 3 }),
1698
- /* @__PURE__ */ jsx13(InputOTPSlot2, { className: "h-12", index: 4 }),
1699
- /* @__PURE__ */ jsx13(InputOTPSlot2, { className: "h-12", index: 5 })
1557
+ children: /* @__PURE__ */ jsxs7(InputOTPGroup2, { 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: [
1558
+ /* @__PURE__ */ jsx9(InputOTPSlot2, { className: "h-12", index: 0 }),
1559
+ /* @__PURE__ */ jsx9(InputOTPSlot2, { className: "h-12", index: 1 }),
1560
+ /* @__PURE__ */ jsx9(InputOTPSlot2, { className: "h-12", index: 2 }),
1561
+ /* @__PURE__ */ jsx9(InputOTPSlot2, { className: "h-12", index: 3 }),
1562
+ /* @__PURE__ */ jsx9(InputOTPSlot2, { className: "h-12", index: 4 }),
1563
+ /* @__PURE__ */ jsx9(InputOTPSlot2, { className: "h-12", index: 5 })
1700
1564
  ] })
1701
1565
  }
1702
1566
  ) }),
1703
- fieldState.invalid && /* @__PURE__ */ jsx13(FieldError5, { errors: [fieldState.error] })
1567
+ fieldState.invalid && /* @__PURE__ */ jsx9(FieldError5, { errors: [fieldState.error] })
1704
1568
  ] })
1705
1569
  }
1706
1570
  ) }),
1707
- /* @__PURE__ */ jsxs11("div", { className: "flex justify-between items-center mt-4", children: [
1708
- /* @__PURE__ */ jsx13(Countdown, { onResend, resending: isLoading }),
1709
- /* @__PURE__ */ jsxs11(
1571
+ /* @__PURE__ */ jsxs7("div", { className: "flex justify-between items-center mt-4", children: [
1572
+ /* @__PURE__ */ jsx9(Countdown, { onResend, resending: isLoading }),
1573
+ /* @__PURE__ */ jsxs7(
1710
1574
  Button6,
1711
1575
  {
1712
1576
  type: "submit",
1713
1577
  form: "verification-form",
1714
1578
  disabled: isLoading || form.watch("code").length !== 6,
1715
1579
  children: [
1716
- isLoading && /* @__PURE__ */ jsx13(Spinner5, {}),
1580
+ isLoading && /* @__PURE__ */ jsx9(Spinner5, {}),
1717
1581
  t("form.confirm")
1718
1582
  ]
1719
1583
  }
@@ -1722,23 +1586,31 @@ var VerificationForm = ({
1722
1586
  ] });
1723
1587
  };
1724
1588
 
1725
- // src/components/auth/pages/verify-email-page.tsx
1726
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1727
- var VerifyEmailPage = ({
1728
- verificationId,
1729
- email,
1730
- redirectUrl
1731
- }) => {
1732
- const { hooks, setAuth } = useApi();
1733
- const { config } = useConfig();
1734
- const t = createTranslator(config.messages || {}, "Auth.verification");
1735
- const common = createTranslator(config.messages || {}, "Common");
1736
- const footer = createTranslator(
1737
- config.messages || {},
1738
- "Auth.forgotPassword.footer"
1739
- );
1740
- const [isLoading, setIsLoading] = useState10(false);
1741
- const [error, setError] = useState10(null);
1589
+ // src/components/auth/verify-email.tsx
1590
+ import {
1591
+ Alert as Alert5,
1592
+ AlertDescription as AlertDescription5,
1593
+ AlertTitle as AlertTitle5
1594
+ } from "@mesob/ui/components/alert";
1595
+ import { useMesob as useMesob5 } from "@mesob/ui/components/mesob-context";
1596
+ import { IconAlertCircle as IconAlertCircle5 } from "@tabler/icons-react";
1597
+ import { useEffect as useEffect6, useState as useState7 } from "react";
1598
+ import { toast as toast5 } from "sonner";
1599
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1600
+ var VerifyEmail = ({
1601
+ verificationId,
1602
+ email,
1603
+ redirectUrl
1604
+ }) => {
1605
+ const { hooks, setAuth } = useApi();
1606
+ const { config } = useConfig();
1607
+ const mesob = useMesob5();
1608
+ const t = useTranslator("Auth.verification");
1609
+ const common = useTranslator("Common");
1610
+ const footer = useTranslator("Auth.forgotPassword.footer");
1611
+ const Link3 = mesob?.linkComponent ?? config.navigation?.linkComponent;
1612
+ const [isLoading, setIsLoading] = useState7(false);
1613
+ const [error, setError] = useState7(null);
1742
1614
  const verifyEmailMutation = hooks.useMutation(
1743
1615
  "post",
1744
1616
  "/email/verification/confirm"
@@ -1748,7 +1620,6 @@ var VerifyEmailPage = ({
1748
1620
  "/email/verification/request"
1749
1621
  );
1750
1622
  const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
1751
- const Link = config.navigation?.linkComponent;
1752
1623
  const onNavigate = config.navigation?.onNavigate || ((path) => {
1753
1624
  if (typeof window !== "undefined") {
1754
1625
  window.location.href = path;
@@ -1756,7 +1627,7 @@ var VerifyEmailPage = ({
1756
1627
  });
1757
1628
  const logoImage = config.ui.logoImage;
1758
1629
  const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
1759
- useEffect9(() => {
1630
+ useEffect6(() => {
1760
1631
  if (error) {
1761
1632
  toast5.error(error.title || "Error", {
1762
1633
  description: error.description
@@ -1813,12 +1684,12 @@ var VerifyEmailPage = ({
1813
1684
  }
1814
1685
  };
1815
1686
  if (!verificationId) {
1816
- return /* @__PURE__ */ jsx14(
1817
- AuthPageLayout,
1687
+ return /* @__PURE__ */ jsx10(
1688
+ AuthLayout,
1818
1689
  {
1819
1690
  title: common("invalidLinkTitle"),
1820
1691
  description: common("invalidLinkDescription"),
1821
- footer: Link ? /* @__PURE__ */ jsx14(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx14(
1692
+ footer: Link3 ? /* @__PURE__ */ jsx10(Link3, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx10(
1822
1693
  "a",
1823
1694
  {
1824
1695
  href: signInLink,
@@ -1830,7 +1701,7 @@ var VerifyEmailPage = ({
1830
1701
  children: footer("backToSignIn")
1831
1702
  }
1832
1703
  ),
1833
- children: /* @__PURE__ */ jsx14("div", {})
1704
+ children: /* @__PURE__ */ jsx10("div", {})
1834
1705
  }
1835
1706
  );
1836
1707
  }
@@ -1842,13 +1713,13 @@ var VerifyEmailPage = ({
1842
1713
  errorContent = error;
1843
1714
  }
1844
1715
  }
1845
- return /* @__PURE__ */ jsxs12(
1846
- AuthPageLayout,
1716
+ return /* @__PURE__ */ jsxs8(
1717
+ AuthLayout,
1847
1718
  {
1848
1719
  title: t("email.title"),
1849
1720
  description: t("email.description"),
1850
1721
  logoImage,
1851
- footer: Link ? /* @__PURE__ */ jsx14(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx14(
1722
+ footer: Link3 ? /* @__PURE__ */ jsx10(Link3, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx10(
1852
1723
  "a",
1853
1724
  {
1854
1725
  href: signInLink,
@@ -1861,7 +1732,7 @@ var VerifyEmailPage = ({
1861
1732
  }
1862
1733
  ),
1863
1734
  children: [
1864
- /* @__PURE__ */ jsx14(
1735
+ /* @__PURE__ */ jsx10(
1865
1736
  VerificationForm,
1866
1737
  {
1867
1738
  verificationId,
@@ -1871,27 +1742,28 @@ var VerifyEmailPage = ({
1871
1742
  error
1872
1743
  }
1873
1744
  ),
1874
- errorContent && /* @__PURE__ */ jsxs12(Alert5, { variant: "destructive", className: "mt-4", children: [
1875
- /* @__PURE__ */ jsx14(IconAlertCircle5, { className: "h-4 w-4" }),
1876
- /* @__PURE__ */ jsx14(AlertTitle5, { children: errorContent.title }),
1877
- /* @__PURE__ */ jsx14(AlertDescription5, { children: errorContent.description })
1745
+ errorContent && /* @__PURE__ */ jsxs8(Alert5, { variant: "destructive", className: "mt-4", children: [
1746
+ /* @__PURE__ */ jsx10(IconAlertCircle5, { className: "h-4 w-4" }),
1747
+ /* @__PURE__ */ jsx10(AlertTitle5, { children: errorContent.title }),
1748
+ /* @__PURE__ */ jsx10(AlertDescription5, { children: errorContent.description })
1878
1749
  ] })
1879
1750
  ]
1880
1751
  }
1881
1752
  );
1882
1753
  };
1883
1754
 
1884
- // src/components/auth/pages/verify-phone-page.tsx
1755
+ // src/components/auth/verify-phone.tsx
1885
1756
  import {
1886
1757
  Alert as Alert6,
1887
1758
  AlertDescription as AlertDescription6,
1888
1759
  AlertTitle as AlertTitle6
1889
1760
  } from "@mesob/ui/components/alert";
1890
- import { toast as toast6 } from "@mesob/ui/components/sonner";
1761
+ import { Link as Link2 } from "@mesob/ui/components/link";
1891
1762
  import { IconAlertCircle as IconAlertCircle6 } from "@tabler/icons-react";
1892
- import { useEffect as useEffect10, useState as useState11 } from "react";
1893
- import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
1894
- var VerifyPhonePage = ({
1763
+ import { useEffect as useEffect7, useState as useState8 } from "react";
1764
+ import { toast as toast6 } from "sonner";
1765
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1766
+ var VerifyPhone = ({
1895
1767
  verificationId,
1896
1768
  context,
1897
1769
  phone = "",
@@ -1899,14 +1771,11 @@ var VerifyPhonePage = ({
1899
1771
  }) => {
1900
1772
  const { hooks, refresh, setAuth } = useApi();
1901
1773
  const { config } = useConfig();
1902
- const t = createTranslator(config.messages || {}, "Auth.verification");
1903
- const common = createTranslator(config.messages || {}, "Common");
1904
- const footer = createTranslator(
1905
- config.messages || {},
1906
- "Auth.forgotPassword.footer"
1907
- );
1908
- const [isLoading, setIsLoading] = useState11(false);
1909
- const [error, setError] = useState11(null);
1774
+ const t = useTranslator("Auth.verification");
1775
+ const common = useTranslator("Common");
1776
+ const footer = useTranslator("Auth.forgotPassword.footer");
1777
+ const [isLoading, setIsLoading] = useState8(false);
1778
+ const [error, setError] = useState8(null);
1910
1779
  const verifyPhoneMutation = hooks.useMutation(
1911
1780
  "post",
1912
1781
  "/phone/verification/confirm"
@@ -1916,7 +1785,6 @@ var VerifyPhonePage = ({
1916
1785
  "/phone/verification/request"
1917
1786
  );
1918
1787
  const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
1919
- const Link = config.navigation?.linkComponent;
1920
1788
  const onNavigate = config.navigation?.onNavigate || ((path) => {
1921
1789
  if (typeof window !== "undefined") {
1922
1790
  window.location.href = path;
@@ -1924,7 +1792,7 @@ var VerifyPhonePage = ({
1924
1792
  });
1925
1793
  const logoImage = config.ui.logoImage;
1926
1794
  const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
1927
- useEffect10(() => {
1795
+ useEffect7(() => {
1928
1796
  if (error) {
1929
1797
  toast6.error(error.title || "Error", {
1930
1798
  description: error.description
@@ -1994,24 +1862,13 @@ var VerifyPhonePage = ({
1994
1862
  }
1995
1863
  };
1996
1864
  if (!verificationId) {
1997
- return /* @__PURE__ */ jsx15(
1998
- AuthPageLayout,
1865
+ return /* @__PURE__ */ jsx11(
1866
+ AuthLayout,
1999
1867
  {
2000
1868
  title: common("invalidLinkTitle"),
2001
1869
  description: common("invalidLinkDescription"),
2002
- footer: Link ? /* @__PURE__ */ jsx15(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx15(
2003
- "a",
2004
- {
2005
- href: signInLink,
2006
- onClick: (e) => {
2007
- e.preventDefault();
2008
- onNavigate(signInLink);
2009
- },
2010
- className: "text-primary hover:underline",
2011
- children: footer("backToSignIn")
2012
- }
2013
- ),
2014
- children: /* @__PURE__ */ jsx15("div", {})
1870
+ footer: /* @__PURE__ */ jsx11(Link2, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }),
1871
+ children: /* @__PURE__ */ jsx11("div", {})
2015
1872
  }
2016
1873
  );
2017
1874
  }
@@ -2023,15 +1880,15 @@ var VerifyPhonePage = ({
2023
1880
  errorContent = error;
2024
1881
  }
2025
1882
  }
2026
- return /* @__PURE__ */ jsxs13(
2027
- AuthPageLayout,
1883
+ return /* @__PURE__ */ jsxs9(
1884
+ AuthLayout,
2028
1885
  {
2029
1886
  title: t("phone.title"),
2030
1887
  description: t("phone.description", {
2031
1888
  target: phone || t("phone.missingPhone")
2032
1889
  }),
2033
1890
  logoImage,
2034
- footer: Link ? /* @__PURE__ */ jsx15(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx15(
1891
+ footer: Link2 ? /* @__PURE__ */ jsx11(Link2, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx11(
2035
1892
  "a",
2036
1893
  {
2037
1894
  href: signInLink,
@@ -2044,7 +1901,7 @@ var VerifyPhonePage = ({
2044
1901
  }
2045
1902
  ),
2046
1903
  children: [
2047
- /* @__PURE__ */ jsx15(
1904
+ /* @__PURE__ */ jsx11(
2048
1905
  VerificationForm,
2049
1906
  {
2050
1907
  verificationId,
@@ -2054,10 +1911,10 @@ var VerifyPhonePage = ({
2054
1911
  error
2055
1912
  }
2056
1913
  ),
2057
- errorContent && /* @__PURE__ */ jsxs13(Alert6, { variant: "destructive", className: "mt-4", children: [
2058
- /* @__PURE__ */ jsx15(IconAlertCircle6, { className: "h-4 w-4" }),
2059
- /* @__PURE__ */ jsx15(AlertTitle6, { children: errorContent.title }),
2060
- /* @__PURE__ */ jsx15(AlertDescription6, { children: errorContent.description })
1914
+ errorContent && /* @__PURE__ */ jsxs9(Alert6, { variant: "destructive", className: "mt-4", children: [
1915
+ /* @__PURE__ */ jsx11(IconAlertCircle6, { className: "h-4 w-4" }),
1916
+ /* @__PURE__ */ jsx11(AlertTitle6, { children: errorContent.title }),
1917
+ /* @__PURE__ */ jsx11(AlertDescription6, { children: errorContent.description })
2061
1918
  ] })
2062
1919
  ]
2063
1920
  }
@@ -2067,7 +1924,7 @@ var VerifyPhonePage = ({
2067
1924
  // src/components/error-boundary.tsx
2068
1925
  import { Button as Button7 } from "@mesob/ui/components/button";
2069
1926
  import { Component } from "react";
2070
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1927
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2071
1928
  var ErrorBoundary = class extends Component {
2072
1929
  constructor(props) {
2073
1930
  super(props);
@@ -2089,30 +1946,31 @@ var ErrorBoundary = class extends Component {
2089
1946
  reset: this.reset
2090
1947
  });
2091
1948
  }
2092
- return /* @__PURE__ */ jsx16(ErrorFallback, { error: this.state.error, reset: this.reset });
1949
+ return /* @__PURE__ */ jsx12(ErrorFallback, { error: this.state.error, reset: this.reset });
2093
1950
  }
2094
1951
  return this.props.children;
2095
1952
  }
2096
1953
  };
2097
1954
  function ErrorFallback({ error, reset }) {
2098
- return /* @__PURE__ */ jsx16("div", { className: "flex flex-col items-center justify-center min-h-[400px] p-6", children: /* @__PURE__ */ jsxs14("div", { className: "max-w-md w-full space-y-4 text-center", children: [
2099
- /* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
2100
- /* @__PURE__ */ jsx16("h2", { className: "text-2xl font-bold text-destructive", children: "Something went wrong" }),
2101
- /* @__PURE__ */ jsx16("p", { className: "text-muted-foreground", children: error.message || "An unexpected error occurred" })
1955
+ return /* @__PURE__ */ jsx12("div", { className: "flex flex-col items-center justify-center min-h-[400px] p-6", children: /* @__PURE__ */ jsxs10("div", { className: "max-w-md w-full space-y-4 text-center", children: [
1956
+ /* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
1957
+ /* @__PURE__ */ jsx12("h2", { className: "text-2xl font-bold text-destructive", children: "Something went wrong" }),
1958
+ /* @__PURE__ */ jsx12("p", { className: "text-muted-foreground", children: error.message || "An unexpected error occurred" })
2102
1959
  ] }),
2103
- /* @__PURE__ */ jsx16(Button7, { onClick: reset, variant: "outline", children: "Try again" })
1960
+ /* @__PURE__ */ jsx12(Button7, { onClick: reset, variant: "outline", children: "Try again" })
2104
1961
  ] }) });
2105
1962
  }
2106
1963
  function AuthErrorBoundary({ children }) {
2107
- return /* @__PURE__ */ jsx16(ErrorBoundary, { children });
1964
+ return /* @__PURE__ */ jsx12(ErrorBoundary, { children });
2108
1965
  }
2109
1966
 
2110
- // src/components/iam/permissions/permissions-page.tsx
1967
+ // src/components/iam/permissions.tsx
2111
1968
  import { Badge } from "@mesob/ui/components/badge";
2112
1969
  import { Button as Button8 } from "@mesob/ui/components/button";
2113
- import { useState as useState12 } from "react";
1970
+ import { useLocale } from "next-intl";
1971
+ import { useState as useState9 } from "react";
2114
1972
 
2115
- // src/components/shared/data-table/data-table.tsx
1973
+ // src/components/shared/data-table.tsx
2116
1974
  import {
2117
1975
  Table,
2118
1976
  TableBody,
@@ -2124,7 +1982,7 @@ import {
2124
1982
 
2125
1983
  // src/components/skeletons/table-skeleton.tsx
2126
1984
  import { Skeleton } from "@mesob/ui/components/skeleton";
2127
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
1985
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
2128
1986
  function TableSkeleton({ columns = 5, rows = 10 }) {
2129
1987
  const headerKeys = Array.from({ length: columns }, (_, i) => `header-${i}`);
2130
1988
  const rowKeys = Array.from({ length: rows }, (_, i) => `row-${i}`);
@@ -2132,32 +1990,32 @@ function TableSkeleton({ columns = 5, rows = 10 }) {
2132
1990
  { length: rows },
2133
1991
  (_, rowIdx) => Array.from({ length: columns }, (_2, colIdx) => `cell-${rowIdx}-${colIdx}`)
2134
1992
  );
2135
- return /* @__PURE__ */ jsxs15("div", { className: "w-full space-y-4", children: [
2136
- /* @__PURE__ */ jsxs15("div", { className: "flex justify-between items-center", children: [
2137
- /* @__PURE__ */ jsx17(Skeleton, { className: "h-8 w-48" }),
2138
- /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-32" })
1993
+ return /* @__PURE__ */ jsxs11("div", { className: "w-full space-y-4", children: [
1994
+ /* @__PURE__ */ jsxs11("div", { className: "flex justify-between items-center", children: [
1995
+ /* @__PURE__ */ jsx13(Skeleton, { className: "h-8 w-48" }),
1996
+ /* @__PURE__ */ jsx13(Skeleton, { className: "h-10 w-32" })
2139
1997
  ] }),
2140
- /* @__PURE__ */ jsxs15("div", { className: "flex gap-4", children: [
2141
- /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 flex-1 max-w-sm" }),
2142
- /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-24" }),
2143
- /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-24" })
1998
+ /* @__PURE__ */ jsxs11("div", { className: "flex gap-4", children: [
1999
+ /* @__PURE__ */ jsx13(Skeleton, { className: "h-10 flex-1 max-w-sm" }),
2000
+ /* @__PURE__ */ jsx13(Skeleton, { className: "h-10 w-24" }),
2001
+ /* @__PURE__ */ jsx13(Skeleton, { className: "h-10 w-24" })
2144
2002
  ] }),
2145
- /* @__PURE__ */ jsxs15("div", { className: "border rounded-lg overflow-hidden", children: [
2146
- /* @__PURE__ */ jsx17("div", { className: "flex gap-4 p-4 bg-muted", children: headerKeys.map((key) => /* @__PURE__ */ jsx17(Skeleton, { className: "h-4 flex-1" }, key)) }),
2147
- rowKeys.map((rowKey, rowIdx) => /* @__PURE__ */ jsx17("div", { className: "flex gap-4 p-4 border-t", children: cellKeys[rowIdx]?.map((cellKey) => /* @__PURE__ */ jsx17(Skeleton, { className: "h-4 flex-1" }, cellKey)) }, rowKey))
2003
+ /* @__PURE__ */ jsxs11("div", { className: "border rounded-lg overflow-hidden", children: [
2004
+ /* @__PURE__ */ jsx13("div", { className: "flex gap-4 p-4 bg-muted", children: headerKeys.map((key) => /* @__PURE__ */ jsx13(Skeleton, { className: "h-4 flex-1" }, key)) }),
2005
+ rowKeys.map((rowKey, rowIdx) => /* @__PURE__ */ jsx13("div", { className: "flex gap-4 p-4 border-t", children: cellKeys[rowIdx]?.map((cellKey) => /* @__PURE__ */ jsx13(Skeleton, { className: "h-4 flex-1" }, cellKey)) }, rowKey))
2148
2006
  ] }),
2149
- /* @__PURE__ */ jsxs15("div", { className: "flex justify-between items-center", children: [
2150
- /* @__PURE__ */ jsx17(Skeleton, { className: "h-4 w-32" }),
2151
- /* @__PURE__ */ jsxs15("div", { className: "flex gap-2", children: [
2152
- /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-20" }),
2153
- /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-20" })
2007
+ /* @__PURE__ */ jsxs11("div", { className: "flex justify-between items-center", children: [
2008
+ /* @__PURE__ */ jsx13(Skeleton, { className: "h-4 w-32" }),
2009
+ /* @__PURE__ */ jsxs11("div", { className: "flex gap-2", children: [
2010
+ /* @__PURE__ */ jsx13(Skeleton, { className: "h-10 w-20" }),
2011
+ /* @__PURE__ */ jsx13(Skeleton, { className: "h-10 w-20" })
2154
2012
  ] })
2155
2013
  ] })
2156
2014
  ] });
2157
2015
  }
2158
2016
 
2159
- // src/components/shared/data-table/data-table.tsx
2160
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
2017
+ // src/components/shared/data-table.tsx
2018
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
2161
2019
  function DataTable({
2162
2020
  data,
2163
2021
  columns,
@@ -2167,24 +2025,24 @@ function DataTable({
2167
2025
  actions
2168
2026
  }) {
2169
2027
  if (isLoading) {
2170
- return /* @__PURE__ */ jsx18(TableSkeleton, { columns: columns.length, rows: 5 });
2028
+ return /* @__PURE__ */ jsx14(TableSkeleton, { columns: columns.length, rows: 5 });
2171
2029
  }
2172
2030
  if (data.length === 0) {
2173
- return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col items-center justify-center min-h-[400px] p-6", children: [
2174
- /* @__PURE__ */ jsx18("p", { className: "text-muted-foreground", children: emptyMessage }),
2175
- actions && /* @__PURE__ */ jsx18("div", { className: "mt-4", children: actions })
2031
+ return /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center min-h-[400px] p-6", children: [
2032
+ /* @__PURE__ */ jsx14("p", { className: "text-muted-foreground", children: emptyMessage }),
2033
+ actions && /* @__PURE__ */ jsx14("div", { className: "mt-4", children: actions })
2176
2034
  ] });
2177
2035
  }
2178
- return /* @__PURE__ */ jsxs16("div", { className: "w-full space-y-4", children: [
2179
- actions && /* @__PURE__ */ jsx18("div", { className: "flex justify-end", children: actions }),
2180
- /* @__PURE__ */ jsx18("div", { className: "border rounded-lg overflow-hidden", children: /* @__PURE__ */ jsxs16(Table, { children: [
2181
- /* @__PURE__ */ jsx18(TableHeader, { children: /* @__PURE__ */ jsx18(TableRow, { children: columns.map((column) => /* @__PURE__ */ jsx18(TableHead, { children: column.header }, column.key)) }) }),
2182
- /* @__PURE__ */ jsx18(TableBody, { children: data.map((row) => /* @__PURE__ */ jsx18(
2036
+ return /* @__PURE__ */ jsxs12("div", { className: "w-full space-y-4", children: [
2037
+ actions && /* @__PURE__ */ jsx14("div", { className: "flex justify-end", children: actions }),
2038
+ /* @__PURE__ */ jsx14("div", { className: "border rounded-lg overflow-hidden", children: /* @__PURE__ */ jsxs12(Table, { children: [
2039
+ /* @__PURE__ */ jsx14(TableHeader, { children: /* @__PURE__ */ jsx14(TableRow, { children: columns.map((column) => /* @__PURE__ */ jsx14(TableHead, { children: column.header }, column.key)) }) }),
2040
+ /* @__PURE__ */ jsx14(TableBody, { children: data.map((row) => /* @__PURE__ */ jsx14(
2183
2041
  TableRow,
2184
2042
  {
2185
2043
  onClick: () => onRowClick?.(row),
2186
2044
  className: onRowClick ? "cursor-pointer hover:bg-muted/50" : "",
2187
- children: columns.map((column) => /* @__PURE__ */ jsx18(TableCell, { children: column.cell(row) }, `${row.id}-${column.key}`))
2045
+ children: columns.map((column) => /* @__PURE__ */ jsx14(TableCell, { children: column.cell(row) }, `${row.id}-${column.key}`))
2188
2046
  },
2189
2047
  row.id
2190
2048
  )) })
@@ -2192,11 +2050,24 @@ function DataTable({
2192
2050
  ] });
2193
2051
  }
2194
2052
 
2195
- // src/components/iam/permissions/permissions-page.tsx
2196
- import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
2197
- function PermissionsPage() {
2053
+ // src/components/iam/permissions.tsx
2054
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
2055
+ function getTranslation(value, locale) {
2056
+ if (!value) {
2057
+ return "";
2058
+ }
2059
+ if (typeof value === "string") {
2060
+ return value;
2061
+ }
2062
+ if (typeof value === "object") {
2063
+ return value[locale] ?? value.en ?? value.am ?? "";
2064
+ }
2065
+ return "";
2066
+ }
2067
+ function Permissions() {
2198
2068
  const { hooks } = useApi();
2199
- const [page, setPage] = useState12(1);
2069
+ const locale = useLocale();
2070
+ const [page, setPage] = useState9(1);
2200
2071
  const limit = 20;
2201
2072
  const { data, isLoading, error } = hooks.useQuery("get", "/permissions", {
2202
2073
  params: {
@@ -2210,44 +2081,44 @@ function PermissionsPage() {
2210
2081
  {
2211
2082
  key: "name",
2212
2083
  header: "Permission",
2213
- cell: (permission) => /* @__PURE__ */ jsxs17("div", { children: [
2214
- /* @__PURE__ */ jsx19("p", { className: "font-medium", children: permission.name }),
2215
- /* @__PURE__ */ jsx19(Badge, { variant: "outline", className: "mt-1 font-mono text-xs", children: permission.code })
2084
+ cell: (permission) => /* @__PURE__ */ jsxs13("div", { children: [
2085
+ /* @__PURE__ */ jsx15("p", { className: "font-medium", children: getTranslation(permission.name, locale) }),
2086
+ /* @__PURE__ */ jsx15(Badge, { variant: "outline", className: "mt-1 font-mono text-xs", children: permission.code })
2216
2087
  ] })
2217
2088
  },
2218
2089
  {
2219
2090
  key: "resource",
2220
2091
  header: "Resource",
2221
- cell: (permission) => /* @__PURE__ */ jsx19(Badge, { variant: "secondary", children: permission.resource })
2092
+ cell: (permission) => /* @__PURE__ */ jsx15(Badge, { variant: "secondary", children: permission.resource })
2222
2093
  },
2223
2094
  {
2224
2095
  key: "action",
2225
2096
  header: "Action",
2226
- cell: (permission) => /* @__PURE__ */ jsx19(Badge, { variant: "outline", children: permission.action })
2097
+ cell: (permission) => /* @__PURE__ */ jsx15(Badge, { variant: "outline", children: permission.action })
2227
2098
  },
2228
2099
  {
2229
2100
  key: "description",
2230
2101
  header: "Description",
2231
- cell: (permission) => /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground max-w-xs truncate", children: permission.description })
2102
+ cell: (permission) => /* @__PURE__ */ jsx15("p", { className: "text-sm text-muted-foreground max-w-xs truncate", children: getTranslation(permission.description, locale) })
2232
2103
  },
2233
2104
  {
2234
2105
  key: "actions",
2235
2106
  header: "Actions",
2236
- cell: (_permission) => /* @__PURE__ */ jsx19(Button8, { variant: "outline", size: "sm", children: "Edit" })
2107
+ cell: (_permission) => /* @__PURE__ */ jsx15(Button8, { variant: "outline", size: "sm", children: "Edit" })
2237
2108
  }
2238
2109
  ];
2239
2110
  if (error) {
2240
- return /* @__PURE__ */ jsx19("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx19("p", { className: "text-destructive", children: "Error loading permissions" }) });
2111
+ return /* @__PURE__ */ jsx15("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx15("p", { className: "text-destructive", children: "Error loading permissions" }) });
2241
2112
  }
2242
- return /* @__PURE__ */ jsxs17("div", { className: "w-full p-6 space-y-4", children: [
2243
- /* @__PURE__ */ jsxs17("div", { className: "flex justify-between items-center", children: [
2244
- /* @__PURE__ */ jsxs17("div", { children: [
2245
- /* @__PURE__ */ jsx19("h1", { className: "text-3xl font-bold", children: "Permissions" }),
2246
- /* @__PURE__ */ jsx19("p", { className: "text-muted-foreground", children: "Manage system permissions" })
2113
+ return /* @__PURE__ */ jsxs13("div", { className: "w-full p-6 space-y-4", children: [
2114
+ /* @__PURE__ */ jsxs13("div", { className: "flex justify-between items-center", children: [
2115
+ /* @__PURE__ */ jsxs13("div", { children: [
2116
+ /* @__PURE__ */ jsx15("h1", { className: "text-3xl font-bold", children: "Permissions" }),
2117
+ /* @__PURE__ */ jsx15("p", { className: "text-muted-foreground", children: "Manage system permissions" })
2247
2118
  ] }),
2248
- /* @__PURE__ */ jsx19(Button8, { children: "Create Permission" })
2119
+ /* @__PURE__ */ jsx15(Button8, { children: "Create Permission" })
2249
2120
  ] }),
2250
- /* @__PURE__ */ jsx19(
2121
+ /* @__PURE__ */ jsx15(
2251
2122
  DataTable,
2252
2123
  {
2253
2124
  data: data?.permissions || [],
@@ -2256,8 +2127,8 @@ function PermissionsPage() {
2256
2127
  emptyMessage: "No permissions found"
2257
2128
  }
2258
2129
  ),
2259
- data && "permissions" in data && data.permissions && data.permissions.length >= limit && /* @__PURE__ */ jsxs17("div", { className: "flex justify-between items-center", children: [
2260
- /* @__PURE__ */ jsx19(
2130
+ data && "permissions" in data && data.permissions && data.permissions.length >= limit && /* @__PURE__ */ jsxs13("div", { className: "flex justify-between items-center", children: [
2131
+ /* @__PURE__ */ jsx15(
2261
2132
  Button8,
2262
2133
  {
2263
2134
  variant: "outline",
@@ -2266,23 +2137,37 @@ function PermissionsPage() {
2266
2137
  children: "Previous"
2267
2138
  }
2268
2139
  ),
2269
- /* @__PURE__ */ jsxs17("span", { className: "text-sm text-muted-foreground", children: [
2140
+ /* @__PURE__ */ jsxs13("span", { className: "text-sm text-muted-foreground", children: [
2270
2141
  "Page ",
2271
2142
  page
2272
2143
  ] }),
2273
- /* @__PURE__ */ jsx19(Button8, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
2144
+ /* @__PURE__ */ jsx15(Button8, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
2274
2145
  ] })
2275
2146
  ] });
2276
2147
  }
2277
2148
 
2278
- // src/components/iam/roles/roles-page.tsx
2149
+ // src/components/iam/roles.tsx
2279
2150
  import { Badge as Badge2 } from "@mesob/ui/components/badge";
2280
2151
  import { Button as Button9 } from "@mesob/ui/components/button";
2281
- import { useState as useState13 } from "react";
2282
- import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
2283
- function RolesPage() {
2152
+ import { useLocale as useLocale2 } from "next-intl";
2153
+ import { useState as useState10 } from "react";
2154
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
2155
+ function getTranslation2(value, locale) {
2156
+ if (!value) {
2157
+ return "";
2158
+ }
2159
+ if (typeof value === "string") {
2160
+ return value;
2161
+ }
2162
+ if (typeof value === "object") {
2163
+ return value[locale] ?? value.en ?? value.am ?? "";
2164
+ }
2165
+ return "";
2166
+ }
2167
+ function Roles() {
2284
2168
  const { hooks } = useApi();
2285
- const [page, setPage] = useState13(1);
2169
+ const locale = useLocale2();
2170
+ const [page, setPage] = useState10(1);
2286
2171
  const limit = 20;
2287
2172
  const { data, isLoading, error } = hooks.useQuery("get", "/roles", {
2288
2173
  params: {
@@ -2296,42 +2181,42 @@ function RolesPage() {
2296
2181
  {
2297
2182
  key: "name",
2298
2183
  header: "Role",
2299
- cell: (role) => /* @__PURE__ */ jsxs18("div", { children: [
2300
- /* @__PURE__ */ jsx20("p", { className: "font-medium", children: role.name }),
2301
- /* @__PURE__ */ jsx20(Badge2, { variant: "outline", className: "mt-1", children: role.code })
2184
+ cell: (role) => /* @__PURE__ */ jsxs14("div", { children: [
2185
+ /* @__PURE__ */ jsx16("p", { className: "font-medium", children: getTranslation2(role.name, locale) }),
2186
+ /* @__PURE__ */ jsx16(Badge2, { variant: "outline", className: "mt-1", children: role.code })
2302
2187
  ] })
2303
2188
  },
2304
2189
  {
2305
2190
  key: "description",
2306
2191
  header: "Description",
2307
- cell: (role) => /* @__PURE__ */ jsx20("p", { className: "text-sm text-muted-foreground", children: role.description })
2192
+ cell: (role) => /* @__PURE__ */ jsx16("p", { className: "text-sm text-muted-foreground", children: getTranslation2(role.description, locale) })
2308
2193
  },
2309
2194
  {
2310
2195
  key: "createdAt",
2311
2196
  header: "Created",
2312
- cell: (role) => /* @__PURE__ */ jsx20("p", { className: "text-sm", children: new Date(role.createdAt).toLocaleDateString() })
2197
+ cell: (role) => /* @__PURE__ */ jsx16("p", { className: "text-sm", children: new Date(role.createdAt).toLocaleDateString() })
2313
2198
  },
2314
2199
  {
2315
2200
  key: "actions",
2316
2201
  header: "Actions",
2317
- cell: (_role) => /* @__PURE__ */ jsxs18("div", { className: "flex gap-2", children: [
2318
- /* @__PURE__ */ jsx20(Button9, { variant: "outline", size: "sm", children: "Permissions" }),
2319
- /* @__PURE__ */ jsx20(Button9, { variant: "outline", size: "sm", children: "Edit" })
2202
+ cell: (_role) => /* @__PURE__ */ jsxs14("div", { className: "flex gap-2", children: [
2203
+ /* @__PURE__ */ jsx16(Button9, { variant: "outline", size: "sm", children: "Permissions" }),
2204
+ /* @__PURE__ */ jsx16(Button9, { variant: "outline", size: "sm", children: "Edit" })
2320
2205
  ] })
2321
2206
  }
2322
2207
  ];
2323
2208
  if (error) {
2324
- return /* @__PURE__ */ jsx20("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx20("p", { className: "text-destructive", children: "Error loading roles" }) });
2209
+ return /* @__PURE__ */ jsx16("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx16("p", { className: "text-destructive", children: "Error loading roles" }) });
2325
2210
  }
2326
- return /* @__PURE__ */ jsxs18("div", { className: "w-full p-6 space-y-4", children: [
2327
- /* @__PURE__ */ jsxs18("div", { className: "flex justify-between items-center", children: [
2328
- /* @__PURE__ */ jsxs18("div", { children: [
2329
- /* @__PURE__ */ jsx20("h1", { className: "text-3xl font-bold", children: "Roles" }),
2330
- /* @__PURE__ */ jsx20("p", { className: "text-muted-foreground", children: "Manage user roles" })
2211
+ return /* @__PURE__ */ jsxs14("div", { className: "w-full p-6 space-y-4", children: [
2212
+ /* @__PURE__ */ jsxs14("div", { className: "flex justify-between items-center", children: [
2213
+ /* @__PURE__ */ jsxs14("div", { children: [
2214
+ /* @__PURE__ */ jsx16("h1", { className: "text-3xl font-bold", children: "Roles" }),
2215
+ /* @__PURE__ */ jsx16("p", { className: "text-muted-foreground", children: "Manage user roles" })
2331
2216
  ] }),
2332
- /* @__PURE__ */ jsx20(Button9, { children: "Create Role" })
2217
+ /* @__PURE__ */ jsx16(Button9, { children: "Create Role" })
2333
2218
  ] }),
2334
- /* @__PURE__ */ jsx20(
2219
+ /* @__PURE__ */ jsx16(
2335
2220
  DataTable,
2336
2221
  {
2337
2222
  data: data?.roles || [],
@@ -2340,8 +2225,8 @@ function RolesPage() {
2340
2225
  emptyMessage: "No roles found"
2341
2226
  }
2342
2227
  ),
2343
- data && "roles" in data && data.roles && data.roles.length >= limit && /* @__PURE__ */ jsxs18("div", { className: "flex justify-between items-center", children: [
2344
- /* @__PURE__ */ jsx20(
2228
+ data && "roles" in data && data.roles && data.roles.length >= limit && /* @__PURE__ */ jsxs14("div", { className: "flex justify-between items-center", children: [
2229
+ /* @__PURE__ */ jsx16(
2345
2230
  Button9,
2346
2231
  {
2347
2232
  variant: "outline",
@@ -2350,22 +2235,22 @@ function RolesPage() {
2350
2235
  children: "Previous"
2351
2236
  }
2352
2237
  ),
2353
- /* @__PURE__ */ jsxs18("span", { className: "text-sm text-muted-foreground", children: [
2238
+ /* @__PURE__ */ jsxs14("span", { className: "text-sm text-muted-foreground", children: [
2354
2239
  "Page ",
2355
2240
  page
2356
2241
  ] }),
2357
- /* @__PURE__ */ jsx20(Button9, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
2242
+ /* @__PURE__ */ jsx16(Button9, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
2358
2243
  ] })
2359
2244
  ] });
2360
2245
  }
2361
2246
 
2362
- // src/components/iam/sessions/sessions-page.tsx
2247
+ // src/components/iam/sessions.tsx
2363
2248
  import { Button as Button10 } from "@mesob/ui/components/button";
2364
- import { useState as useState14 } from "react";
2365
- import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
2366
- function SessionsPage() {
2249
+ import { useState as useState11 } from "react";
2250
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
2251
+ function Sessions() {
2367
2252
  const { hooks } = useApi();
2368
- const [selectedSessionId] = useState14(null);
2253
+ const [selectedSessionId] = useState11(null);
2369
2254
  const { data, isLoading, error, refetch } = hooks.useQuery(
2370
2255
  "get",
2371
2256
  "/sessions"
@@ -2391,30 +2276,30 @@ function SessionsPage() {
2391
2276
  {
2392
2277
  key: "createdAt",
2393
2278
  header: "Created",
2394
- cell: (session) => /* @__PURE__ */ jsxs19("div", { children: [
2395
- /* @__PURE__ */ jsx21("p", { className: "text-sm font-medium", children: new Date(session.createdAt).toLocaleDateString() }),
2396
- /* @__PURE__ */ jsx21("p", { className: "text-xs text-muted-foreground", children: new Date(session.createdAt).toLocaleTimeString() })
2279
+ cell: (session) => /* @__PURE__ */ jsxs15("div", { children: [
2280
+ /* @__PURE__ */ jsx17("p", { className: "text-sm font-medium", children: new Date(session.createdAt).toLocaleDateString() }),
2281
+ /* @__PURE__ */ jsx17("p", { className: "text-xs text-muted-foreground", children: new Date(session.createdAt).toLocaleTimeString() })
2397
2282
  ] })
2398
2283
  },
2399
2284
  {
2400
2285
  key: "expiresAt",
2401
2286
  header: "Expires",
2402
- cell: (session) => /* @__PURE__ */ jsx21("p", { className: "text-sm", children: new Date(session.expiresAt).toLocaleDateString() })
2287
+ cell: (session) => /* @__PURE__ */ jsx17("p", { className: "text-sm", children: new Date(session.expiresAt).toLocaleDateString() })
2403
2288
  },
2404
2289
  {
2405
2290
  key: "userAgent",
2406
2291
  header: "Device",
2407
- cell: (session) => /* @__PURE__ */ jsx21("p", { className: "text-sm truncate max-w-xs", children: session.userAgent || "Unknown" })
2292
+ cell: (session) => /* @__PURE__ */ jsx17("p", { className: "text-sm truncate max-w-xs", children: session.userAgent || "Unknown" })
2408
2293
  },
2409
2294
  {
2410
2295
  key: "ip",
2411
2296
  header: "IP Address",
2412
- cell: (session) => /* @__PURE__ */ jsx21("p", { className: "text-sm font-mono", children: session.ip || "Unknown" })
2297
+ cell: (session) => /* @__PURE__ */ jsx17("p", { className: "text-sm font-mono", children: session.ip || "Unknown" })
2413
2298
  },
2414
2299
  {
2415
2300
  key: "actions",
2416
2301
  header: "Actions",
2417
- cell: (session) => /* @__PURE__ */ jsx21(
2302
+ cell: (session) => /* @__PURE__ */ jsx17(
2418
2303
  Button10,
2419
2304
  {
2420
2305
  variant: "destructive",
@@ -2427,14 +2312,14 @@ function SessionsPage() {
2427
2312
  }
2428
2313
  ];
2429
2314
  if (error) {
2430
- return /* @__PURE__ */ jsx21("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx21("p", { className: "text-destructive", children: "Error loading sessions" }) });
2315
+ return /* @__PURE__ */ jsx17("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx17("p", { className: "text-destructive", children: "Error loading sessions" }) });
2431
2316
  }
2432
- return /* @__PURE__ */ jsxs19("div", { className: "w-full p-6 space-y-4", children: [
2433
- /* @__PURE__ */ jsxs19("div", { children: [
2434
- /* @__PURE__ */ jsx21("h1", { className: "text-3xl font-bold", children: "Sessions" }),
2435
- /* @__PURE__ */ jsx21("p", { className: "text-muted-foreground", children: "View and manage active sessions" })
2317
+ return /* @__PURE__ */ jsxs15("div", { className: "w-full p-6 space-y-4", children: [
2318
+ /* @__PURE__ */ jsxs15("div", { children: [
2319
+ /* @__PURE__ */ jsx17("h1", { className: "text-3xl font-bold", children: "Sessions" }),
2320
+ /* @__PURE__ */ jsx17("p", { className: "text-muted-foreground", children: "View and manage active sessions" })
2436
2321
  ] }),
2437
- /* @__PURE__ */ jsx21(
2322
+ /* @__PURE__ */ jsx17(
2438
2323
  DataTable,
2439
2324
  {
2440
2325
  data: data?.sessions || [],
@@ -2446,14 +2331,14 @@ function SessionsPage() {
2446
2331
  ] });
2447
2332
  }
2448
2333
 
2449
- // src/components/iam/tenants/tenants-page.tsx
2334
+ // src/components/iam/tenants.tsx
2450
2335
  import { Badge as Badge3 } from "@mesob/ui/components/badge";
2451
2336
  import { Button as Button11 } from "@mesob/ui/components/button";
2452
- import { useState as useState15 } from "react";
2453
- import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
2454
- function TenantsPage() {
2337
+ import { useState as useState12 } from "react";
2338
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
2339
+ function Tenants() {
2455
2340
  const { hooks } = useApi();
2456
- const [page, setPage] = useState15(1);
2341
+ const [page, setPage] = useState12(1);
2457
2342
  const limit = 20;
2458
2343
  const { data, isLoading, error } = hooks.useQuery("get", "/tenants", {
2459
2344
  params: {
@@ -2467,9 +2352,9 @@ function TenantsPage() {
2467
2352
  {
2468
2353
  key: "name",
2469
2354
  header: "Tenant",
2470
- cell: (tenant) => /* @__PURE__ */ jsxs20("div", { children: [
2471
- /* @__PURE__ */ jsx22("p", { className: "font-medium", children: tenant.name }),
2472
- /* @__PURE__ */ jsxs20("p", { className: "text-sm text-muted-foreground", children: [
2355
+ cell: (tenant) => /* @__PURE__ */ jsxs16("div", { children: [
2356
+ /* @__PURE__ */ jsx18("p", { className: "font-medium", children: tenant.name }),
2357
+ /* @__PURE__ */ jsxs16("p", { className: "text-sm text-muted-foreground", children: [
2473
2358
  "/",
2474
2359
  tenant.slug
2475
2360
  ] })
@@ -2478,34 +2363,34 @@ function TenantsPage() {
2478
2363
  {
2479
2364
  key: "status",
2480
2365
  header: "Status",
2481
- cell: (tenant) => /* @__PURE__ */ jsx22(Badge3, { variant: tenant.status === "active" ? "default" : "secondary", children: tenant.status })
2366
+ cell: (tenant) => /* @__PURE__ */ jsx18(Badge3, { variant: tenant.status === "active" ? "default" : "secondary", children: tenant.status })
2482
2367
  },
2483
2368
  {
2484
2369
  key: "createdAt",
2485
2370
  header: "Created",
2486
- cell: (tenant) => /* @__PURE__ */ jsx22("p", { className: "text-sm", children: new Date(tenant.createdAt).toLocaleDateString() })
2371
+ cell: (tenant) => /* @__PURE__ */ jsx18("p", { className: "text-sm", children: new Date(tenant.createdAt).toLocaleDateString() })
2487
2372
  },
2488
2373
  {
2489
2374
  key: "actions",
2490
2375
  header: "Actions",
2491
- cell: (_tenant) => /* @__PURE__ */ jsxs20("div", { className: "flex gap-2", children: [
2492
- /* @__PURE__ */ jsx22(Button11, { variant: "outline", size: "sm", children: "Domains" }),
2493
- /* @__PURE__ */ jsx22(Button11, { variant: "outline", size: "sm", children: "Edit" })
2376
+ cell: (_tenant) => /* @__PURE__ */ jsxs16("div", { className: "flex gap-2", children: [
2377
+ /* @__PURE__ */ jsx18(Button11, { variant: "outline", size: "sm", children: "Domains" }),
2378
+ /* @__PURE__ */ jsx18(Button11, { variant: "outline", size: "sm", children: "Edit" })
2494
2379
  ] })
2495
2380
  }
2496
2381
  ];
2497
2382
  if (error) {
2498
- return /* @__PURE__ */ jsx22("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx22("p", { className: "text-destructive", children: "Error loading tenants" }) });
2383
+ return /* @__PURE__ */ jsx18("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx18("p", { className: "text-destructive", children: "Error loading tenants" }) });
2499
2384
  }
2500
- return /* @__PURE__ */ jsxs20("div", { className: "w-full p-6 space-y-4", children: [
2501
- /* @__PURE__ */ jsxs20("div", { className: "flex justify-between items-center", children: [
2502
- /* @__PURE__ */ jsxs20("div", { children: [
2503
- /* @__PURE__ */ jsx22("h1", { className: "text-3xl font-bold", children: "Tenants" }),
2504
- /* @__PURE__ */ jsx22("p", { className: "text-muted-foreground", children: "Manage tenant organizations" })
2385
+ return /* @__PURE__ */ jsxs16("div", { className: "w-full p-6 space-y-4", children: [
2386
+ /* @__PURE__ */ jsxs16("div", { className: "flex justify-between items-center", children: [
2387
+ /* @__PURE__ */ jsxs16("div", { children: [
2388
+ /* @__PURE__ */ jsx18("h1", { className: "text-3xl font-bold", children: "Tenants" }),
2389
+ /* @__PURE__ */ jsx18("p", { className: "text-muted-foreground", children: "Manage tenant organizations" })
2505
2390
  ] }),
2506
- /* @__PURE__ */ jsx22(Button11, { children: "Create Tenant" })
2391
+ /* @__PURE__ */ jsx18(Button11, { children: "Create Tenant" })
2507
2392
  ] }),
2508
- /* @__PURE__ */ jsx22(
2393
+ /* @__PURE__ */ jsx18(
2509
2394
  DataTable,
2510
2395
  {
2511
2396
  data: data?.tenants || [],
@@ -2514,8 +2399,8 @@ function TenantsPage() {
2514
2399
  emptyMessage: "No tenants found"
2515
2400
  }
2516
2401
  ),
2517
- data && "tenants" in data && data.tenants && data.tenants.length >= limit && /* @__PURE__ */ jsxs20("div", { className: "flex justify-between items-center", children: [
2518
- /* @__PURE__ */ jsx22(
2402
+ data && "tenants" in data && data.tenants && data.tenants.length >= limit && /* @__PURE__ */ jsxs16("div", { className: "flex justify-between items-center", children: [
2403
+ /* @__PURE__ */ jsx18(
2519
2404
  Button11,
2520
2405
  {
2521
2406
  variant: "outline",
@@ -2524,23 +2409,23 @@ function TenantsPage() {
2524
2409
  children: "Previous"
2525
2410
  }
2526
2411
  ),
2527
- /* @__PURE__ */ jsxs20("span", { className: "text-sm text-muted-foreground", children: [
2412
+ /* @__PURE__ */ jsxs16("span", { className: "text-sm text-muted-foreground", children: [
2528
2413
  "Page ",
2529
2414
  page
2530
2415
  ] }),
2531
- /* @__PURE__ */ jsx22(Button11, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
2416
+ /* @__PURE__ */ jsx18(Button11, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
2532
2417
  ] })
2533
2418
  ] });
2534
2419
  }
2535
2420
 
2536
- // src/components/iam/users/users-page.tsx
2421
+ // src/components/iam/users.tsx
2537
2422
  import { Badge as Badge4 } from "@mesob/ui/components/badge";
2538
2423
  import { Button as Button12 } from "@mesob/ui/components/button";
2539
- import { useState as useState16 } from "react";
2540
- import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
2541
- function UsersPage() {
2424
+ import { useState as useState13 } from "react";
2425
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
2426
+ function Users() {
2542
2427
  const { hooks } = useApi();
2543
- const [page, setPage] = useState16(1);
2428
+ const [page, setPage] = useState13(1);
2544
2429
  const limit = 20;
2545
2430
  const { data, isLoading, error } = hooks.useQuery("get", "/users", {
2546
2431
  params: {
@@ -2554,9 +2439,9 @@ function UsersPage() {
2554
2439
  {
2555
2440
  key: "fullName",
2556
2441
  header: "Name",
2557
- cell: (user) => /* @__PURE__ */ jsxs21("div", { children: [
2558
- /* @__PURE__ */ jsx23("p", { className: "font-medium", children: user.fullName }),
2559
- /* @__PURE__ */ jsxs21("p", { className: "text-sm text-muted-foreground", children: [
2442
+ cell: (user) => /* @__PURE__ */ jsxs17("div", { children: [
2443
+ /* @__PURE__ */ jsx19("p", { className: "font-medium", children: user.fullName }),
2444
+ /* @__PURE__ */ jsxs17("p", { className: "text-sm text-muted-foreground", children: [
2560
2445
  "@",
2561
2446
  user.handle
2562
2447
  ] })
@@ -2565,43 +2450,43 @@ function UsersPage() {
2565
2450
  {
2566
2451
  key: "contact",
2567
2452
  header: "Contact",
2568
- cell: (user) => /* @__PURE__ */ jsxs21("div", { className: "space-y-1", children: [
2569
- user.email && /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-2", children: [
2570
- /* @__PURE__ */ jsx23("p", { className: "text-sm", children: user.email }),
2571
- user.emailVerified && /* @__PURE__ */ jsx23(Badge4, { variant: "outline", className: "text-xs", children: "Verified" })
2453
+ cell: (user) => /* @__PURE__ */ jsxs17("div", { className: "space-y-1", children: [
2454
+ user.email && /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
2455
+ /* @__PURE__ */ jsx19("p", { className: "text-sm", children: user.email }),
2456
+ user.emailVerified && /* @__PURE__ */ jsx19(Badge4, { variant: "outline", className: "text-xs", children: "Verified" })
2572
2457
  ] }),
2573
- user.phone && /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-2", children: [
2574
- /* @__PURE__ */ jsx23("p", { className: "text-sm", children: user.phone }),
2575
- user.phoneVerified && /* @__PURE__ */ jsx23(Badge4, { variant: "outline", className: "text-xs", children: "Verified" })
2458
+ user.phone && /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
2459
+ /* @__PURE__ */ jsx19("p", { className: "text-sm", children: user.phone }),
2460
+ user.phoneVerified && /* @__PURE__ */ jsx19(Badge4, { variant: "outline", className: "text-xs", children: "Verified" })
2576
2461
  ] })
2577
2462
  ] })
2578
2463
  },
2579
2464
  {
2580
2465
  key: "lastSignIn",
2581
2466
  header: "Last Sign In",
2582
- cell: (user) => /* @__PURE__ */ jsx23("p", { className: "text-sm", children: user.lastSignInAt ? new Date(user.lastSignInAt).toLocaleDateString() : "Never" })
2467
+ cell: (user) => /* @__PURE__ */ jsx19("p", { className: "text-sm", children: user.lastSignInAt ? new Date(user.lastSignInAt).toLocaleDateString() : "Never" })
2583
2468
  },
2584
2469
  {
2585
2470
  key: "actions",
2586
2471
  header: "Actions",
2587
- cell: (_user) => /* @__PURE__ */ jsxs21("div", { className: "flex gap-2", children: [
2588
- /* @__PURE__ */ jsx23(Button12, { variant: "outline", size: "sm", children: "View" }),
2589
- /* @__PURE__ */ jsx23(Button12, { variant: "outline", size: "sm", children: "Edit" })
2472
+ cell: (_user) => /* @__PURE__ */ jsxs17("div", { className: "flex gap-2", children: [
2473
+ /* @__PURE__ */ jsx19(Button12, { variant: "outline", size: "sm", children: "View" }),
2474
+ /* @__PURE__ */ jsx19(Button12, { variant: "outline", size: "sm", children: "Edit" })
2590
2475
  ] })
2591
2476
  }
2592
2477
  ];
2593
2478
  if (error) {
2594
- return /* @__PURE__ */ jsx23("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx23("p", { className: "text-destructive", children: "Error loading users" }) });
2479
+ return /* @__PURE__ */ jsx19("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx19("p", { className: "text-destructive", children: "Error loading users" }) });
2595
2480
  }
2596
- return /* @__PURE__ */ jsxs21("div", { className: "w-full p-6 space-y-4", children: [
2597
- /* @__PURE__ */ jsxs21("div", { className: "flex justify-between items-center", children: [
2598
- /* @__PURE__ */ jsxs21("div", { children: [
2599
- /* @__PURE__ */ jsx23("h1", { className: "text-3xl font-bold", children: "Users" }),
2600
- /* @__PURE__ */ jsx23("p", { className: "text-muted-foreground", children: "Manage user accounts" })
2481
+ return /* @__PURE__ */ jsxs17("div", { className: "w-full p-6 space-y-4", children: [
2482
+ /* @__PURE__ */ jsxs17("div", { className: "flex justify-between items-center", children: [
2483
+ /* @__PURE__ */ jsxs17("div", { children: [
2484
+ /* @__PURE__ */ jsx19("h1", { className: "text-3xl font-bold", children: "Users" }),
2485
+ /* @__PURE__ */ jsx19("p", { className: "text-muted-foreground", children: "Manage user accounts" })
2601
2486
  ] }),
2602
- /* @__PURE__ */ jsx23(Button12, { children: "Create User" })
2487
+ /* @__PURE__ */ jsx19(Button12, { children: "Create User" })
2603
2488
  ] }),
2604
- /* @__PURE__ */ jsx23(
2489
+ /* @__PURE__ */ jsx19(
2605
2490
  DataTable,
2606
2491
  {
2607
2492
  data: data?.users || [],
@@ -2610,8 +2495,8 @@ function UsersPage() {
2610
2495
  emptyMessage: "No users found"
2611
2496
  }
2612
2497
  ),
2613
- data && "users" in data && data.users && data.users.length >= limit && /* @__PURE__ */ jsxs21("div", { className: "flex justify-between items-center", children: [
2614
- /* @__PURE__ */ jsx23(
2498
+ data && "users" in data && data.users && data.users.length >= limit && /* @__PURE__ */ jsxs17("div", { className: "flex justify-between items-center", children: [
2499
+ /* @__PURE__ */ jsx19(
2615
2500
  Button12,
2616
2501
  {
2617
2502
  variant: "outline",
@@ -2620,182 +2505,1291 @@ function UsersPage() {
2620
2505
  children: "Previous"
2621
2506
  }
2622
2507
  ),
2623
- /* @__PURE__ */ jsxs21("span", { className: "text-sm text-muted-foreground", children: [
2508
+ /* @__PURE__ */ jsxs17("span", { className: "text-sm text-muted-foreground", children: [
2624
2509
  "Page ",
2625
2510
  page
2626
2511
  ] }),
2627
- /* @__PURE__ */ jsx23(Button12, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
2512
+ /* @__PURE__ */ jsx19(Button12, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
2628
2513
  ] })
2629
2514
  ] });
2630
2515
  }
2631
2516
 
2632
- // src/components/profile/profile-page.tsx
2633
- import { Button as Button13 } from "@mesob/ui/components/button";
2634
- import {
2635
- Card,
2636
- CardContent,
2637
- CardDescription,
2638
- CardHeader,
2639
- CardTitle
2640
- } from "@mesob/ui/components/card";
2517
+ // src/components/profile/account.tsx
2641
2518
  import { Separator } from "@mesob/ui/components/separator";
2642
-
2643
- // src/components/skeletons/profile-skeleton.tsx
2644
- import { Skeleton as Skeleton2 } from "@mesob/ui/components/skeleton";
2645
- import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
2646
- function ProfileSkeleton() {
2647
- return /* @__PURE__ */ jsxs22("div", { className: "w-full max-w-4xl space-y-8 p-6", children: [
2648
- /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-6", children: [
2649
- /* @__PURE__ */ jsx24(Skeleton2, { className: "h-24 w-24 rounded-full" }),
2650
- /* @__PURE__ */ jsxs22("div", { className: "space-y-2 flex-1", children: [
2651
- /* @__PURE__ */ jsx24(Skeleton2, { className: "h-8 w-48" }),
2652
- /* @__PURE__ */ jsx24(Skeleton2, { className: "h-4 w-64" })
2653
- ] })
2519
+ import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
2520
+ function Account() {
2521
+ const { user, isAuthenticated } = useSession();
2522
+ if (!(isAuthenticated && user)) {
2523
+ return /* @__PURE__ */ jsx20("div", { children: "Sign in required" });
2524
+ }
2525
+ return /* @__PURE__ */ jsxs18("div", { className: "p-6 max-w-4xl", children: [
2526
+ /* @__PURE__ */ jsxs18("div", { className: "mb-6", children: [
2527
+ /* @__PURE__ */ jsx20("h2", { className: "text-lg font-semibold mb-4", children: "Profile details" }),
2528
+ /* @__PURE__ */ jsx20(Separator, {})
2654
2529
  ] }),
2655
- /* @__PURE__ */ jsx24("div", { className: "space-y-6", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs22("div", { className: "space-y-4", children: [
2656
- /* @__PURE__ */ jsx24(Skeleton2, { className: "h-6 w-32" }),
2657
- /* @__PURE__ */ jsxs22("div", { className: "space-y-3", children: [
2658
- /* @__PURE__ */ jsxs22("div", { className: "flex justify-between items-center", children: [
2659
- /* @__PURE__ */ jsx24(Skeleton2, { className: "h-4 w-24" }),
2660
- /* @__PURE__ */ jsx24(Skeleton2, { className: "h-4 w-32" })
2661
- ] }),
2662
- /* @__PURE__ */ jsxs22("div", { className: "flex justify-between items-center", children: [
2663
- /* @__PURE__ */ jsx24(Skeleton2, { className: "h-4 w-24" }),
2664
- /* @__PURE__ */ jsx24(Skeleton2, { className: "h-4 w-40" })
2665
- ] })
2530
+ /* @__PURE__ */ jsxs18("div", { className: "space-y-6 transition-all duration-300 ease-in-out", children: [
2531
+ /* @__PURE__ */ jsx20("div", { className: "flex flex-col md:flex-row items-start gap-4 md:gap-12 min-h-[3rem]", children: /* @__PURE__ */ jsx20("div", { className: "w-full md:w-48 mt-4 shrink-0 h-fit", children: /* @__PURE__ */ jsx20("span", { className: "font-medium text-sm", children: "Profile" }) }) }),
2532
+ /* @__PURE__ */ jsx20(Separator, {}),
2533
+ /* @__PURE__ */ jsxs18("div", { className: "flex flex-col md:flex-row gap-4 md:gap-12 py-2", children: [
2534
+ /* @__PURE__ */ jsx20("div", { className: "w-full md:w-48 shrink-0", children: /* @__PURE__ */ jsx20("span", { className: "font-medium text-sm", children: "Email addresses" }) }),
2535
+ /* @__PURE__ */ jsx20("div", { className: "flex-1 space-y-4", children: /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-between group", children: user.email ? /* @__PURE__ */ jsx20("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsx20("span", { className: "text-sm", children: user.email }) }) : /* @__PURE__ */ jsx20("span", { className: "text-sm text-muted-foreground", children: "No email address" }) }) })
2536
+ ] }),
2537
+ /* @__PURE__ */ jsx20(Separator, {}),
2538
+ /* @__PURE__ */ jsxs18("div", { className: "flex flex-col md:flex-row gap-4 md:gap-12 py-2", children: [
2539
+ /* @__PURE__ */ jsx20("div", { className: "w-full md:w-48 shrink-0", children: /* @__PURE__ */ jsx20("span", { className: "font-medium text-sm", children: "Phone numbers" }) }),
2540
+ /* @__PURE__ */ jsx20("div", { className: "flex-1 space-y-4", children: user.phone ? /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsx20("span", { className: "text-sm", children: user.phone }) }) : /* @__PURE__ */ jsx20("span", { className: "text-sm text-muted-foreground", children: "No phone number" }) })
2666
2541
  ] })
2667
- ] }, i)) })
2542
+ ] })
2668
2543
  ] });
2669
2544
  }
2670
2545
 
2671
- // src/components/profile/profile-page.tsx
2672
- import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
2673
- function ProfilePage({ onEditClick }) {
2674
- const { user, isLoading } = useSession();
2675
- if (isLoading) {
2676
- return /* @__PURE__ */ jsx25(ProfileSkeleton, {});
2546
+ // src/components/profile/change-email-form.tsx
2547
+ import { Button as Button14 } from "@mesob/ui/components/button";
2548
+ import {
2549
+ Collapsible,
2550
+ CollapsibleContent,
2551
+ CollapsibleTrigger
2552
+ } from "@mesob/ui/components/collapsible";
2553
+ import { IconChevronDown } from "@tabler/icons-react";
2554
+ import { useState as useState16 } from "react";
2555
+
2556
+ // src/components/profile/request-change-email-form.tsx
2557
+ import { zodResolver as zodResolver6 } from "@hookform/resolvers/zod";
2558
+ import { Button as Button13 } from "@mesob/ui/components/button";
2559
+ import { Input as Input5 } from "@mesob/ui/components/input";
2560
+ import { Label } from "@mesob/ui/components/label";
2561
+ import { Spinner as Spinner6 } from "@mesob/ui/components/spinner";
2562
+ import { IconEye as IconEye4, IconEyeOff as IconEyeOff4 } from "@tabler/icons-react";
2563
+ import { useEffect as useEffect8, useState as useState14 } from "react";
2564
+ import { useForm as useForm6 } from "react-hook-form";
2565
+ import { toast as toast7 } from "sonner";
2566
+ import { z as z6 } from "zod";
2567
+ import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
2568
+ var emailPasswordSchema = z6.object({
2569
+ email: z6.string().email("Invalid email address"),
2570
+ password: z6.string().min(8, "Password must be at least 8 characters").max(128, "Password too long")
2571
+ });
2572
+ function isAuthError2(error) {
2573
+ return typeof error === "object" && error !== null && ("code" in error || "message" in error || "name" in error);
2574
+ }
2575
+ function getErrorCode(error) {
2576
+ if (error.code) {
2577
+ return error.code;
2677
2578
  }
2678
- if (!user) {
2679
- return /* @__PURE__ */ jsx25("div", { className: "flex items-center justify-center min-h-[400px]", children: /* @__PURE__ */ jsx25("p", { className: "text-muted-foreground", children: "Not authenticated" }) });
2579
+ if (error.message) {
2580
+ const upperMessage = error.message.toUpperCase().trim();
2581
+ const validCodes2 = [
2582
+ "USER_NOT_FOUND",
2583
+ "USER_EXISTS",
2584
+ "INVALID_PASSWORD",
2585
+ "VERIFICATION_EXPIRED",
2586
+ "VERIFICATION_MISMATCH",
2587
+ "VERIFICATION_NOT_FOUND",
2588
+ "TOO_MANY_ATTEMPTS",
2589
+ "UNAUTHORIZED"
2590
+ ];
2591
+ if (validCodes2.includes(upperMessage)) {
2592
+ return upperMessage;
2593
+ }
2680
2594
  }
2681
- return /* @__PURE__ */ jsxs23("div", { className: "w-full max-w-4xl mx-auto space-y-6 p-6", children: [
2682
- /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between", children: [
2683
- /* @__PURE__ */ jsxs23("div", { children: [
2684
- /* @__PURE__ */ jsx25("h1", { className: "text-3xl font-bold", children: user.fullName }),
2685
- /* @__PURE__ */ jsxs23("p", { className: "text-muted-foreground", children: [
2686
- "@",
2687
- user.handle
2595
+ return void 0;
2596
+ }
2597
+ function getErrorMessage(error) {
2598
+ if (isAuthError2(error)) {
2599
+ const errorCode = getErrorCode(error);
2600
+ switch (errorCode) {
2601
+ case "USER_EXISTS":
2602
+ return "This email is already taken. Please use a different email.";
2603
+ case "VERIFICATION_EXPIRED":
2604
+ return "Verification code has expired. Please request a new one.";
2605
+ case "VERIFICATION_MISMATCH":
2606
+ return "Invalid verification code. Please try again.";
2607
+ case "VERIFICATION_NOT_FOUND":
2608
+ return "Verification not found. Please request a new code.";
2609
+ default:
2610
+ return error.message || "An error occurred. Please try again.";
2611
+ }
2612
+ }
2613
+ if (error instanceof Error) {
2614
+ return error.message;
2615
+ }
2616
+ return "An error occurred. Please try again.";
2617
+ }
2618
+ function RequestChangeEmailForm({
2619
+ onSuccess,
2620
+ onCancel,
2621
+ buttonText
2622
+ }) {
2623
+ const { user } = useSession();
2624
+ const { hooks } = useApi();
2625
+ const [isSubmitting, setIsSubmitting] = useState14(false);
2626
+ const [isChecking, setIsChecking] = useState14(true);
2627
+ const [showPassword, setShowPassword] = useState14(false);
2628
+ const getPendingAccountChangeQuery = hooks.useQuery(
2629
+ "get",
2630
+ "/account-change/pending",
2631
+ {},
2632
+ { enabled: false }
2633
+ );
2634
+ const verifyPasswordMutation = hooks.useMutation("post", "/password/verify");
2635
+ const checkUserMutation = hooks.useMutation("post", "/check-account");
2636
+ const requestEmailVerificationMutation = hooks.useMutation(
2637
+ "post",
2638
+ "/email/verification/request"
2639
+ );
2640
+ const emailPasswordForm = useForm6({
2641
+ resolver: zodResolver6(emailPasswordSchema),
2642
+ defaultValues: {
2643
+ email: "",
2644
+ password: ""
2645
+ }
2646
+ });
2647
+ const {
2648
+ register,
2649
+ handleSubmit,
2650
+ getValues,
2651
+ setValue,
2652
+ formState: { errors }
2653
+ } = emailPasswordForm;
2654
+ useEffect8(() => {
2655
+ let active = true;
2656
+ const run = async () => {
2657
+ try {
2658
+ const data = await getPendingAccountChangeQuery.refetch();
2659
+ if (!active) {
2660
+ return;
2661
+ }
2662
+ const accountChange = data.data?.accountChange;
2663
+ const verificationId = data.data?.verificationId;
2664
+ if (accountChange?.changeType !== "email") {
2665
+ setIsChecking(false);
2666
+ return;
2667
+ }
2668
+ if (!accountChange.newEmail) {
2669
+ setIsChecking(false);
2670
+ return;
2671
+ }
2672
+ if (getValues("email")) {
2673
+ setIsChecking(false);
2674
+ return;
2675
+ }
2676
+ setValue("email", accountChange.newEmail, { shouldValidate: true });
2677
+ if (verificationId) {
2678
+ toast7.message("Resuming verification\u2026");
2679
+ onSuccess(verificationId, accountChange.newEmail);
2680
+ return;
2681
+ }
2682
+ setIsChecking(false);
2683
+ } catch {
2684
+ setIsChecking(false);
2685
+ }
2686
+ };
2687
+ run().catch(() => void 0);
2688
+ return () => {
2689
+ active = false;
2690
+ };
2691
+ }, [getPendingAccountChangeQuery.refetch, getValues, onSuccess, setValue]);
2692
+ const onEmailPasswordSubmit = async (data) => {
2693
+ if (!user) {
2694
+ toast7.error("User not found");
2695
+ return;
2696
+ }
2697
+ try {
2698
+ setIsSubmitting(true);
2699
+ await verifyPasswordMutation.mutateAsync({
2700
+ body: { password: data.password }
2701
+ });
2702
+ const checkResult = await checkUserMutation.mutateAsync({
2703
+ body: { identifier: data.email }
2704
+ });
2705
+ if (checkResult.data?.exists) {
2706
+ if (user?.email?.toLowerCase() === data.email.toLowerCase()) {
2707
+ toast7.error("This is already your current email address.");
2708
+ return;
2709
+ }
2710
+ toast7.error(
2711
+ "This email is already taken. Please use a different email."
2712
+ );
2713
+ return;
2714
+ }
2715
+ const verification = await requestEmailVerificationMutation.mutateAsync({
2716
+ body: { email: data.email }
2717
+ });
2718
+ toast7.success("Verification code sent to your email");
2719
+ onSuccess(verification.data?.verificationId ?? "", data.email);
2720
+ } catch (error) {
2721
+ const errorMessage = getErrorMessage(error);
2722
+ if (isAuthError2(error)) {
2723
+ const errorCode = getErrorCode(error);
2724
+ if (errorCode === "INVALID_PASSWORD" || errorCode === "USER_NOT_FOUND") {
2725
+ toast7.error("Incorrect password. Please try again.");
2726
+ return;
2727
+ }
2728
+ }
2729
+ toast7.error(errorMessage);
2730
+ } finally {
2731
+ setIsSubmitting(false);
2732
+ }
2733
+ };
2734
+ const isLoading = isSubmitting || isChecking;
2735
+ return /* @__PURE__ */ jsxs19(
2736
+ "form",
2737
+ {
2738
+ onSubmit: handleSubmit(onEmailPasswordSubmit),
2739
+ className: "p-4 space-y-4 border-t",
2740
+ children: [
2741
+ /* @__PURE__ */ jsxs19("div", { className: "space-y-4 w-full md:w-1/2", children: [
2742
+ /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
2743
+ /* @__PURE__ */ jsx21(Label, { htmlFor: "email", children: "New Email Address" }),
2744
+ /* @__PURE__ */ jsx21(
2745
+ Input5,
2746
+ {
2747
+ id: "email",
2748
+ type: "email",
2749
+ placeholder: "Enter your new email",
2750
+ ...register("email"),
2751
+ disabled: isLoading
2752
+ }
2753
+ ),
2754
+ errors.email && /* @__PURE__ */ jsx21("p", { className: "text-sm text-destructive", children: errors.email.message })
2755
+ ] }),
2756
+ /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
2757
+ /* @__PURE__ */ jsx21(Label, { htmlFor: "password", children: "Password" }),
2758
+ /* @__PURE__ */ jsxs19("div", { className: "relative", children: [
2759
+ /* @__PURE__ */ jsx21(
2760
+ Input5,
2761
+ {
2762
+ id: "password",
2763
+ type: showPassword ? "text" : "password",
2764
+ autoComplete: "current-password",
2765
+ placeholder: "Enter your password",
2766
+ ...register("password"),
2767
+ disabled: isLoading
2768
+ }
2769
+ ),
2770
+ /* @__PURE__ */ jsx21(
2771
+ "button",
2772
+ {
2773
+ type: "button",
2774
+ onClick: () => setShowPassword(!showPassword),
2775
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
2776
+ disabled: isLoading,
2777
+ children: showPassword ? /* @__PURE__ */ jsx21(IconEyeOff4, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx21(IconEye4, { className: "h-4 w-4" })
2778
+ }
2779
+ )
2780
+ ] }),
2781
+ errors.password && /* @__PURE__ */ jsx21("p", { className: "text-sm text-destructive", children: errors.password.message })
2782
+ ] })
2783
+ ] }),
2784
+ /* @__PURE__ */ jsxs19("div", { className: "flex justify-end gap-2", children: [
2785
+ /* @__PURE__ */ jsx21(
2786
+ Button13,
2787
+ {
2788
+ type: "button",
2789
+ variant: "outline",
2790
+ onClick: onCancel,
2791
+ disabled: isLoading,
2792
+ children: "Cancel"
2793
+ }
2794
+ ),
2795
+ /* @__PURE__ */ jsxs19(Button13, { type: "submit", disabled: isLoading, children: [
2796
+ isLoading && /* @__PURE__ */ jsx21(Spinner6, { className: "mr-2 h-4 w-4" }),
2797
+ isChecking ? "Checking\u2026" : buttonText
2798
+ ] })
2688
2799
  ] })
2689
- ] }),
2690
- onEditClick && /* @__PURE__ */ jsx25(Button13, { onClick: onEditClick, children: "Edit Profile" })
2691
- ] }),
2692
- /* @__PURE__ */ jsx25(Separator, {}),
2693
- /* @__PURE__ */ jsxs23("div", { className: "grid gap-6 md:grid-cols-2", children: [
2694
- /* @__PURE__ */ jsxs23(Card, { children: [
2695
- /* @__PURE__ */ jsxs23(CardHeader, { children: [
2696
- /* @__PURE__ */ jsx25(CardTitle, { children: "Contact Information" }),
2697
- /* @__PURE__ */ jsx25(CardDescription, { children: "Your contact details" })
2800
+ ]
2801
+ }
2802
+ );
2803
+ }
2804
+
2805
+ // src/components/profile/verify-change-email-form.tsx
2806
+ import { useState as useState15 } from "react";
2807
+ import { toast as toast8 } from "sonner";
2808
+
2809
+ // src/components/profile/otp-verification-modal.tsx
2810
+ import {
2811
+ Dialog,
2812
+ DialogContent,
2813
+ DialogDescription,
2814
+ DialogHeader,
2815
+ DialogTitle
2816
+ } from "@mesob/ui/components/dialog";
2817
+ import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
2818
+ function OtpVerificationModal({
2819
+ open,
2820
+ title,
2821
+ description,
2822
+ verificationId,
2823
+ isLoading,
2824
+ onSubmit,
2825
+ onResend,
2826
+ onCancel
2827
+ }) {
2828
+ return /* @__PURE__ */ jsx22(
2829
+ Dialog,
2830
+ {
2831
+ open,
2832
+ onOpenChange: (nextOpen) => {
2833
+ if (!nextOpen) {
2834
+ onCancel?.();
2835
+ }
2836
+ },
2837
+ children: /* @__PURE__ */ jsxs20(DialogContent, { children: [
2838
+ /* @__PURE__ */ jsxs20(DialogHeader, { children: [
2839
+ /* @__PURE__ */ jsx22(DialogTitle, { children: title }),
2840
+ description && /* @__PURE__ */ jsx22(DialogDescription, { children: description })
2698
2841
  ] }),
2699
- /* @__PURE__ */ jsxs23(CardContent, { className: "space-y-4", children: [
2700
- /* @__PURE__ */ jsxs23("div", { children: [
2701
- /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-muted-foreground", children: "Email" }),
2702
- /* @__PURE__ */ jsxs23("p", { className: "text-sm", children: [
2703
- user.email || "Not provided",
2704
- user.email && /* @__PURE__ */ jsx25(
2705
- "span",
2842
+ /* @__PURE__ */ jsx22(
2843
+ VerificationForm,
2844
+ {
2845
+ verificationId,
2846
+ isLoading,
2847
+ onSubmit: async ({ code }) => onSubmit(code),
2848
+ onResend: onResend ?? (() => void 0)
2849
+ }
2850
+ )
2851
+ ] })
2852
+ }
2853
+ );
2854
+ }
2855
+
2856
+ // src/components/profile/verify-change-email-form.tsx
2857
+ import { jsx as jsx23 } from "react/jsx-runtime";
2858
+ function isAuthError3(error) {
2859
+ return typeof error === "object" && error !== null && ("code" in error || "message" in error || "name" in error);
2860
+ }
2861
+ function getErrorCode2(error) {
2862
+ if (error.code) {
2863
+ return error.code;
2864
+ }
2865
+ if (error.message) {
2866
+ const upperMessage = error.message.toUpperCase().trim();
2867
+ const validCodes2 = [
2868
+ "USER_NOT_FOUND",
2869
+ "USER_EXISTS",
2870
+ "INVALID_PASSWORD",
2871
+ "VERIFICATION_EXPIRED",
2872
+ "VERIFICATION_MISMATCH",
2873
+ "VERIFICATION_NOT_FOUND",
2874
+ "TOO_MANY_ATTEMPTS",
2875
+ "UNAUTHORIZED"
2876
+ ];
2877
+ if (validCodes2.includes(upperMessage)) {
2878
+ return upperMessage;
2879
+ }
2880
+ }
2881
+ return void 0;
2882
+ }
2883
+ function getErrorMessage2(error) {
2884
+ if (isAuthError3(error)) {
2885
+ const errorCode = getErrorCode2(error);
2886
+ switch (errorCode) {
2887
+ case "USER_EXISTS":
2888
+ return "This email is already taken. Please use a different email.";
2889
+ case "VERIFICATION_EXPIRED":
2890
+ return "Verification code has expired. Please request a new one.";
2891
+ case "VERIFICATION_MISMATCH":
2892
+ return "Invalid verification code. Please try again.";
2893
+ case "VERIFICATION_NOT_FOUND":
2894
+ return "Verification not found. Please request a new code.";
2895
+ default:
2896
+ return error.message || "An error occurred. Please try again.";
2897
+ }
2898
+ }
2899
+ if (error instanceof Error) {
2900
+ return error.message;
2901
+ }
2902
+ return "An error occurred. Please try again.";
2903
+ }
2904
+ function VerifyChangeEmailForm({
2905
+ email,
2906
+ verificationId,
2907
+ onSuccess,
2908
+ onCancel
2909
+ }) {
2910
+ const { refresh } = useSession();
2911
+ const { hooks } = useApi();
2912
+ const [isSubmitting, setIsSubmitting] = useState15(false);
2913
+ const [currentVerificationId, setCurrentVerificationId] = useState15(verificationId);
2914
+ const verifyEmailMutation = hooks.useMutation(
2915
+ "post",
2916
+ "/email/verification/confirm"
2917
+ );
2918
+ const updateEmailMutation = hooks.useMutation("put", "/profile/email");
2919
+ const requestEmailVerificationMutation = hooks.useMutation(
2920
+ "post",
2921
+ "/email/verification/request"
2922
+ );
2923
+ const onOtpSubmit = async (code) => {
2924
+ if (!currentVerificationId) {
2925
+ toast8.error("Verification not found. Please request a new code.");
2926
+ return;
2927
+ }
2928
+ try {
2929
+ setIsSubmitting(true);
2930
+ await verifyEmailMutation.mutateAsync({
2931
+ body: {
2932
+ verificationId: currentVerificationId,
2933
+ code
2934
+ }
2935
+ });
2936
+ await updateEmailMutation.mutateAsync({
2937
+ body: { email }
2938
+ });
2939
+ toast8.success("Email updated successfully");
2940
+ await refresh();
2941
+ onSuccess();
2942
+ } catch (error) {
2943
+ const errorMessage = getErrorMessage2(error);
2944
+ toast8.error(errorMessage);
2945
+ } finally {
2946
+ setIsSubmitting(false);
2947
+ }
2948
+ };
2949
+ if (!currentVerificationId) {
2950
+ toast8.error("Verification not found. Please request a new code.");
2951
+ return null;
2952
+ }
2953
+ return /* @__PURE__ */ jsx23(
2954
+ OtpVerificationModal,
2955
+ {
2956
+ open: true,
2957
+ title: "Verify email",
2958
+ description: `Enter the verification code sent to ${email}`,
2959
+ verificationId: currentVerificationId,
2960
+ isLoading: isSubmitting,
2961
+ onSubmit: onOtpSubmit,
2962
+ onResend: async () => {
2963
+ try {
2964
+ setIsSubmitting(true);
2965
+ const next = await requestEmailVerificationMutation.mutateAsync({
2966
+ body: { email }
2967
+ });
2968
+ setCurrentVerificationId(next.data?.verificationId ?? null);
2969
+ toast8.success("Verification code resent");
2970
+ } catch (error) {
2971
+ toast8.error(getErrorMessage2(error));
2972
+ } finally {
2973
+ setIsSubmitting(false);
2974
+ }
2975
+ },
2976
+ onCancel
2977
+ }
2978
+ );
2979
+ }
2980
+
2981
+ // src/components/profile/change-email-form.tsx
2982
+ import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
2983
+ function ChangeEmailForm() {
2984
+ const { user } = useSession();
2985
+ const [isOpen, setIsOpen] = useState16(false);
2986
+ const [showOtp, setShowOtp] = useState16(false);
2987
+ const [verificationId, setVerificationId] = useState16(null);
2988
+ const [newEmail, setNewEmail] = useState16("");
2989
+ const resetForms = () => {
2990
+ setShowOtp(false);
2991
+ setVerificationId(null);
2992
+ setNewEmail("");
2993
+ };
2994
+ const handleRequestSuccess = (id, email) => {
2995
+ setVerificationId(id);
2996
+ setNewEmail(email);
2997
+ setShowOtp(true);
2998
+ };
2999
+ const handleVerifySuccess = () => {
3000
+ resetForms();
3001
+ setIsOpen(false);
3002
+ };
3003
+ const handleCancel = () => {
3004
+ resetForms();
3005
+ setIsOpen(false);
3006
+ };
3007
+ const title = user?.email ? "Change Email" : "Add Email";
3008
+ const description = user?.email ? "Update your email address" : "Add an email address to your account";
3009
+ return /* @__PURE__ */ jsx24(Collapsible, { open: isOpen, onOpenChange: setIsOpen, children: /* @__PURE__ */ jsxs21("div", { className: "border rounded-lg", children: [
3010
+ /* @__PURE__ */ jsx24(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsxs21(Button14, { variant: "ghost", className: "w-full justify-between p-4 h-auto", children: [
3011
+ /* @__PURE__ */ jsxs21("div", { className: "flex flex-col items-start", children: [
3012
+ /* @__PURE__ */ jsx24("span", { className: "font-medium", children: title }),
3013
+ /* @__PURE__ */ jsx24("span", { className: "text-sm text-muted-foreground", children: description })
3014
+ ] }),
3015
+ /* @__PURE__ */ jsx24(
3016
+ IconChevronDown,
3017
+ {
3018
+ className: `h-4 w-4 transition-transform ${isOpen ? "rotate-180" : ""}`
3019
+ }
3020
+ )
3021
+ ] }) }),
3022
+ /* @__PURE__ */ jsx24(CollapsibleContent, { children: showOtp ? /* @__PURE__ */ jsx24(
3023
+ VerifyChangeEmailForm,
3024
+ {
3025
+ email: newEmail,
3026
+ verificationId,
3027
+ onSuccess: handleVerifySuccess,
3028
+ onCancel: handleCancel
3029
+ }
3030
+ ) : /* @__PURE__ */ jsx24(
3031
+ RequestChangeEmailForm,
3032
+ {
3033
+ onSuccess: handleRequestSuccess,
3034
+ onCancel: handleCancel,
3035
+ buttonText: title
3036
+ }
3037
+ ) })
3038
+ ] }) });
3039
+ }
3040
+
3041
+ // src/components/profile/change-password-form.tsx
3042
+ import { zodResolver as zodResolver7 } from "@hookform/resolvers/zod";
3043
+ import { Button as Button15 } from "@mesob/ui/components/button";
3044
+ import {
3045
+ Collapsible as Collapsible2,
3046
+ CollapsibleContent as CollapsibleContent2,
3047
+ CollapsibleTrigger as CollapsibleTrigger2
3048
+ } from "@mesob/ui/components/collapsible";
3049
+ import { Input as Input6 } from "@mesob/ui/components/input";
3050
+ import { Label as Label2 } from "@mesob/ui/components/label";
3051
+ import { Spinner as Spinner7 } from "@mesob/ui/components/spinner";
3052
+ import { IconChevronDown as IconChevronDown2, IconEye as IconEye5, IconEyeOff as IconEyeOff5 } from "@tabler/icons-react";
3053
+ import { useState as useState17 } from "react";
3054
+ import { useForm as useForm7 } from "react-hook-form";
3055
+ import { toast as toast9 } from "sonner";
3056
+ import { z as z7 } from "zod";
3057
+ import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
3058
+ var changePasswordSchema = z7.object({
3059
+ currentPassword: z7.string().min(8, "Password must be at least 8 characters"),
3060
+ newPassword: z7.string().min(8, "Password must be at least 8 characters"),
3061
+ confirmPassword: z7.string().min(8, "Password must be at least 8 characters")
3062
+ }).refine((data) => data.newPassword === data.confirmPassword, {
3063
+ message: "Passwords don't match",
3064
+ path: ["confirmPassword"]
3065
+ });
3066
+ function isAuthError4(error) {
3067
+ return typeof error === "object" && error !== null && ("code" in error || "message" in error || "name" in error);
3068
+ }
3069
+ function getErrorCode3(error) {
3070
+ if (error.code) {
3071
+ return error.code;
3072
+ }
3073
+ if (error.message) {
3074
+ const upperMessage = error.message.toUpperCase().trim();
3075
+ const validCodes2 = [
3076
+ "INVALID_PASSWORD",
3077
+ "UNAUTHORIZED",
3078
+ "HAS_NO_PASSWORD",
3079
+ "USER_NOT_FOUND",
3080
+ "USER_EXISTS",
3081
+ "VERIFICATION_EXPIRED",
3082
+ "VERIFICATION_MISMATCH",
3083
+ "VERIFICATION_NOT_FOUND",
3084
+ "TOO_MANY_ATTEMPTS",
3085
+ "REQUIRES_VERIFICATION",
3086
+ "ACCESS_DENIED"
3087
+ ];
3088
+ if (validCodes2.includes(upperMessage)) {
3089
+ return upperMessage;
3090
+ }
3091
+ }
3092
+ return void 0;
3093
+ }
3094
+ function getPasswordChangeErrorMessage(error) {
3095
+ if (isAuthError4(error)) {
3096
+ const errorCode = getErrorCode3(error);
3097
+ switch (errorCode) {
3098
+ case "INVALID_PASSWORD":
3099
+ return "The current password you entered is incorrect. Please try again.";
3100
+ case "UNAUTHORIZED":
3101
+ return "You are not authorized to perform this action. Please sign in again.";
3102
+ case "HAS_NO_PASSWORD":
3103
+ return "Your account does not have a password set. Please use password reset instead.";
3104
+ default:
3105
+ return error.message || "Failed to change password. Please try again.";
3106
+ }
3107
+ }
3108
+ if (error instanceof Error) {
3109
+ return error.message;
3110
+ }
3111
+ return "Failed to change password. Please try again.";
3112
+ }
3113
+ function ChangePasswordForm() {
3114
+ const { user: _user } = useSession();
3115
+ const [isOpen, setIsOpen] = useState17(false);
3116
+ const [isSubmitting, setIsSubmitting] = useState17(false);
3117
+ const [showPassword, setShowPassword] = useState17(false);
3118
+ const [showNewPassword, setShowNewPassword] = useState17(false);
3119
+ const [showConfirmPassword, setShowConfirmPassword] = useState17(false);
3120
+ const form = useForm7({
3121
+ resolver: zodResolver7(changePasswordSchema),
3122
+ defaultValues: {
3123
+ currentPassword: "",
3124
+ newPassword: "",
3125
+ confirmPassword: ""
3126
+ }
3127
+ });
3128
+ const { register, handleSubmit, formState, reset } = form;
3129
+ const onSubmit = (_data) => {
3130
+ try {
3131
+ setIsSubmitting(true);
3132
+ toast9.error("Password change unavailable");
3133
+ setIsOpen(false);
3134
+ } catch (error) {
3135
+ const errorMessage = getPasswordChangeErrorMessage(error);
3136
+ toast9.error(errorMessage);
3137
+ } finally {
3138
+ setIsSubmitting(false);
3139
+ }
3140
+ };
3141
+ return /* @__PURE__ */ jsx25(Collapsible2, { open: isOpen, onOpenChange: setIsOpen, children: /* @__PURE__ */ jsxs22("div", { className: "border rounded-lg", children: [
3142
+ /* @__PURE__ */ jsx25(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs22(Button15, { variant: "ghost", className: "w-full justify-between p-4 h-auto", children: [
3143
+ /* @__PURE__ */ jsxs22("div", { className: "flex flex-col items-start", children: [
3144
+ /* @__PURE__ */ jsx25("span", { className: "font-medium", children: "Change Password" }),
3145
+ /* @__PURE__ */ jsx25("span", { className: "text-sm text-muted-foreground", children: "Update your account password" })
3146
+ ] }),
3147
+ /* @__PURE__ */ jsx25(
3148
+ IconChevronDown2,
3149
+ {
3150
+ className: `h-4 w-4 transition-transform ${isOpen ? "rotate-180" : ""}`
3151
+ }
3152
+ )
3153
+ ] }) }),
3154
+ /* @__PURE__ */ jsx25(CollapsibleContent2, { children: /* @__PURE__ */ jsxs22(
3155
+ "form",
3156
+ {
3157
+ onSubmit: handleSubmit(onSubmit),
3158
+ className: "p-4 space-y-4 border-t",
3159
+ children: [
3160
+ /* @__PURE__ */ jsxs22("div", { className: "space-y-2 w-full md:w-1/2", children: [
3161
+ /* @__PURE__ */ jsx25(Label2, { htmlFor: "currentPassword", children: "Old Password" }),
3162
+ /* @__PURE__ */ jsxs22("div", { className: "relative", children: [
3163
+ /* @__PURE__ */ jsx25(
3164
+ Input6,
2706
3165
  {
2707
- className: user.emailVerified ? "text-green-600 ml-2" : "text-yellow-600 ml-2",
2708
- children: user.emailVerified ? "(Verified)" : "(Not verified)"
3166
+ id: "currentPassword",
3167
+ type: showPassword ? "text" : "password",
3168
+ autoComplete: "current-password",
3169
+ placeholder: "Enter your current password",
3170
+ ...register("currentPassword")
3171
+ }
3172
+ ),
3173
+ /* @__PURE__ */ jsx25(
3174
+ "button",
3175
+ {
3176
+ type: "button",
3177
+ onClick: () => setShowPassword(!showPassword),
3178
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
3179
+ children: showPassword ? /* @__PURE__ */ jsx25(IconEyeOff5, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx25(IconEye5, { className: "h-4 w-4" })
2709
3180
  }
2710
3181
  )
2711
- ] })
3182
+ ] }),
3183
+ formState.errors.currentPassword && /* @__PURE__ */ jsx25("p", { className: "text-sm text-destructive", children: formState.errors.currentPassword.message })
2712
3184
  ] }),
2713
- /* @__PURE__ */ jsxs23("div", { children: [
2714
- /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-muted-foreground", children: "Phone" }),
2715
- /* @__PURE__ */ jsxs23("p", { className: "text-sm", children: [
2716
- user.phone || "Not provided",
2717
- user.phone && /* @__PURE__ */ jsx25(
2718
- "span",
3185
+ /* @__PURE__ */ jsxs22("div", { className: "space-y-2 w-full md:w-1/2", children: [
3186
+ /* @__PURE__ */ jsx25(Label2, { htmlFor: "newPassword", children: "New Password" }),
3187
+ /* @__PURE__ */ jsxs22("div", { className: "relative", children: [
3188
+ /* @__PURE__ */ jsx25(
3189
+ Input6,
2719
3190
  {
2720
- className: user.phoneVerified ? "text-green-600 ml-2" : "text-yellow-600 ml-2",
2721
- children: user.phoneVerified ? "(Verified)" : "(Not verified)"
3191
+ id: "newPassword",
3192
+ type: showNewPassword ? "text" : "password",
3193
+ placeholder: "Enter your new password",
3194
+ autoComplete: "new-password",
3195
+ ...register("newPassword")
3196
+ }
3197
+ ),
3198
+ /* @__PURE__ */ jsx25(
3199
+ "button",
3200
+ {
3201
+ type: "button",
3202
+ onClick: () => setShowNewPassword(!showNewPassword),
3203
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
3204
+ children: showNewPassword ? /* @__PURE__ */ jsx25(IconEyeOff5, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx25(IconEye5, { className: "h-4 w-4" })
2722
3205
  }
2723
3206
  )
3207
+ ] }),
3208
+ formState.errors.newPassword && /* @__PURE__ */ jsx25("p", { className: "text-sm text-destructive", children: formState.errors.newPassword.message })
3209
+ ] }),
3210
+ /* @__PURE__ */ jsxs22("div", { className: "space-y-2 w-full md:w-1/2", children: [
3211
+ /* @__PURE__ */ jsx25(Label2, { htmlFor: "confirmPassword", children: "Confirm New Password" }),
3212
+ /* @__PURE__ */ jsxs22("div", { className: "relative", children: [
3213
+ /* @__PURE__ */ jsx25(
3214
+ Input6,
3215
+ {
3216
+ id: "confirmPassword",
3217
+ type: showConfirmPassword ? "text" : "password",
3218
+ placeholder: "Confirm your new password",
3219
+ autoComplete: "new-password",
3220
+ ...register("confirmPassword")
3221
+ }
3222
+ ),
3223
+ /* @__PURE__ */ jsx25(
3224
+ "button",
3225
+ {
3226
+ type: "button",
3227
+ onClick: () => setShowConfirmPassword(!showConfirmPassword),
3228
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
3229
+ children: showConfirmPassword ? /* @__PURE__ */ jsx25(IconEyeOff5, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx25(IconEye5, { className: "h-4 w-4" })
3230
+ }
3231
+ )
3232
+ ] }),
3233
+ formState.errors.confirmPassword && /* @__PURE__ */ jsx25("p", { className: "text-sm text-destructive", children: formState.errors.confirmPassword.message })
3234
+ ] }),
3235
+ /* @__PURE__ */ jsxs22("div", { className: "flex justify-end gap-2", children: [
3236
+ /* @__PURE__ */ jsx25(
3237
+ Button15,
3238
+ {
3239
+ type: "button",
3240
+ variant: "outline",
3241
+ onClick: () => {
3242
+ reset();
3243
+ setIsOpen(false);
3244
+ },
3245
+ disabled: isSubmitting,
3246
+ children: "Cancel"
3247
+ }
3248
+ ),
3249
+ /* @__PURE__ */ jsxs22(Button15, { type: "submit", disabled: isSubmitting, children: [
3250
+ isSubmitting && /* @__PURE__ */ jsx25(Spinner7, { className: "mr-2 h-4 w-4" }),
3251
+ "Change Password"
2724
3252
  ] })
2725
3253
  ] })
2726
- ] })
2727
- ] }),
2728
- /* @__PURE__ */ jsxs23(Card, { children: [
2729
- /* @__PURE__ */ jsxs23(CardHeader, { children: [
2730
- /* @__PURE__ */ jsx25(CardTitle, { children: "Account Information" }),
2731
- /* @__PURE__ */ jsx25(CardDescription, { children: "Your account details" })
2732
- ] }),
2733
- /* @__PURE__ */ jsxs23(CardContent, { className: "space-y-4", children: [
2734
- /* @__PURE__ */ jsxs23("div", { children: [
2735
- /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-muted-foreground", children: "Tenant ID" }),
2736
- /* @__PURE__ */ jsx25("p", { className: "text-sm font-mono", children: user.tenantId })
3254
+ ]
3255
+ }
3256
+ ) })
3257
+ ] }) });
3258
+ }
3259
+
3260
+ // src/components/profile/change-phone-form.tsx
3261
+ import { Button as Button17 } from "@mesob/ui/components/button";
3262
+ import {
3263
+ Collapsible as Collapsible3,
3264
+ CollapsibleContent as CollapsibleContent3,
3265
+ CollapsibleTrigger as CollapsibleTrigger3
3266
+ } from "@mesob/ui/components/collapsible";
3267
+ import { IconChevronDown as IconChevronDown3 } from "@tabler/icons-react";
3268
+ import { useState as useState20 } from "react";
3269
+
3270
+ // src/components/profile/request-change-phone-form.tsx
3271
+ import { zodResolver as zodResolver8 } from "@hookform/resolvers/zod";
3272
+ import { Button as Button16 } from "@mesob/ui/components/button";
3273
+ import { Input as Input7 } from "@mesob/ui/components/input";
3274
+ import { Label as Label3 } from "@mesob/ui/components/label";
3275
+ import { Spinner as Spinner8 } from "@mesob/ui/components/spinner";
3276
+ import { IconEye as IconEye6, IconEyeOff as IconEyeOff6 } from "@tabler/icons-react";
3277
+ import { useEffect as useEffect9, useState as useState18 } from "react";
3278
+ import { useForm as useForm8 } from "react-hook-form";
3279
+ import { toast as toast10 } from "sonner";
3280
+ import { z as z8 } from "zod";
3281
+ import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
3282
+ var phonePasswordSchema = (phoneRegex) => z8.object({
3283
+ phone: z8.string().trim().min(1, { message: "Phone number is required" }).refine(
3284
+ (val) => {
3285
+ const isPhone3 = phoneRegex.test(val);
3286
+ return isPhone3;
3287
+ },
3288
+ {
3289
+ message: "Invalid phone number"
3290
+ }
3291
+ ),
3292
+ password: z8.string().min(8, "Password must be at least 8 characters").max(128, "Password too long")
3293
+ });
3294
+ function isAuthError5(error) {
3295
+ return typeof error === "object" && error !== null && ("code" in error || "message" in error || "name" in error);
3296
+ }
3297
+ function getErrorCode4(error) {
3298
+ if (error.code) {
3299
+ return error.code;
3300
+ }
3301
+ if (error.message) {
3302
+ const upperMessage = error.message.toUpperCase().trim();
3303
+ const validCodes2 = [
3304
+ "USER_NOT_FOUND",
3305
+ "USER_EXISTS",
3306
+ "INVALID_PASSWORD",
3307
+ "VERIFICATION_EXPIRED",
3308
+ "VERIFICATION_MISMATCH",
3309
+ "VERIFICATION_NOT_FOUND",
3310
+ "TOO_MANY_ATTEMPTS",
3311
+ "UNAUTHORIZED"
3312
+ ];
3313
+ if (validCodes2.includes(upperMessage)) {
3314
+ return upperMessage;
3315
+ }
3316
+ }
3317
+ return void 0;
3318
+ }
3319
+ function getErrorMessage3(error) {
3320
+ if (isAuthError5(error)) {
3321
+ const errorCode = getErrorCode4(error);
3322
+ switch (errorCode) {
3323
+ case "USER_EXISTS":
3324
+ return "This phone number is already taken. Please use a different number.";
3325
+ case "VERIFICATION_EXPIRED":
3326
+ return "Verification code has expired. Please request a new one.";
3327
+ case "VERIFICATION_MISMATCH":
3328
+ return "Invalid verification code. Please try again.";
3329
+ case "VERIFICATION_NOT_FOUND":
3330
+ return "Verification not found. Please request a new code.";
3331
+ default:
3332
+ return error.message || "An error occurred. Please try again.";
3333
+ }
3334
+ }
3335
+ if (error instanceof Error) {
3336
+ return error.message;
3337
+ }
3338
+ return "An error occurred. Please try again.";
3339
+ }
3340
+ function RequestChangePhoneForm({
3341
+ onSuccess,
3342
+ onCancel,
3343
+ buttonText
3344
+ }) {
3345
+ const { user } = useSession();
3346
+ const { hooks } = useApi();
3347
+ const { config } = useConfig();
3348
+ const [isSubmitting, setIsSubmitting] = useState18(false);
3349
+ const [isChecking, setIsChecking] = useState18(true);
3350
+ const [showPassword, setShowPassword] = useState18(false);
3351
+ const phoneRegex = typeof config.phoneRegex === "string" ? new RegExp(config.phoneRegex) : config.phoneRegex || /^(\+2519|\+2517|2519|2517|09|07)\d{8}$/;
3352
+ const getPendingAccountChangeQuery = hooks.useQuery(
3353
+ "get",
3354
+ "/account-change/pending",
3355
+ {},
3356
+ { enabled: false }
3357
+ );
3358
+ const verifyPasswordMutation = hooks.useMutation("post", "/password/verify");
3359
+ const checkUserMutation = hooks.useMutation("post", "/check-account");
3360
+ const requestPhoneOtpMutation = hooks.useMutation(
3361
+ "post",
3362
+ "/phone/verification/request"
3363
+ );
3364
+ const phonePasswordForm = useForm8({
3365
+ resolver: zodResolver8(phonePasswordSchema(phoneRegex)),
3366
+ defaultValues: {
3367
+ phone: "",
3368
+ password: ""
3369
+ }
3370
+ });
3371
+ const {
3372
+ register,
3373
+ handleSubmit,
3374
+ getValues,
3375
+ setValue,
3376
+ formState: { errors }
3377
+ } = phonePasswordForm;
3378
+ useEffect9(() => {
3379
+ let active = true;
3380
+ const run = async () => {
3381
+ try {
3382
+ const data = await getPendingAccountChangeQuery.refetch();
3383
+ if (!active) {
3384
+ return;
3385
+ }
3386
+ const accountChange = data.data?.accountChange;
3387
+ const verificationId = data.data?.verificationId;
3388
+ if (accountChange?.changeType !== "phone") {
3389
+ setIsChecking(false);
3390
+ return;
3391
+ }
3392
+ if (!accountChange.newPhone) {
3393
+ setIsChecking(false);
3394
+ return;
3395
+ }
3396
+ if (getValues("phone")) {
3397
+ setIsChecking(false);
3398
+ return;
3399
+ }
3400
+ setValue("phone", accountChange.newPhone, { shouldValidate: true });
3401
+ if (verificationId) {
3402
+ toast10.message("Resuming verification\u2026");
3403
+ onSuccess(verificationId, accountChange.newPhone);
3404
+ return;
3405
+ }
3406
+ setIsChecking(false);
3407
+ } catch {
3408
+ setIsChecking(false);
3409
+ }
3410
+ };
3411
+ run().catch(() => void 0);
3412
+ return () => {
3413
+ active = false;
3414
+ };
3415
+ }, [getPendingAccountChangeQuery.refetch, getValues, onSuccess, setValue]);
3416
+ const onPhonePasswordSubmit = async (data) => {
3417
+ if (!user) {
3418
+ toast10.error("User not found");
3419
+ return;
3420
+ }
3421
+ try {
3422
+ setIsSubmitting(true);
3423
+ const normalizedPhone = normalizePhone(data.phone);
3424
+ await verifyPasswordMutation.mutateAsync({
3425
+ body: { password: data.password }
3426
+ });
3427
+ const checkResult = await checkUserMutation.mutateAsync({
3428
+ body: { identifier: normalizedPhone }
3429
+ });
3430
+ if (checkResult.data?.exists) {
3431
+ if (user?.phone?.replace(/\s/g, "") === normalizedPhone.replace(/\s/g, "")) {
3432
+ toast10.error("This is already your current phone number.");
3433
+ return;
3434
+ }
3435
+ toast10.error(
3436
+ "This phone number is already taken. Please use a different number."
3437
+ );
3438
+ return;
3439
+ }
3440
+ const verification = await requestPhoneOtpMutation.mutateAsync({
3441
+ body: {
3442
+ phone: normalizedPhone,
3443
+ context: "change-phone"
3444
+ }
3445
+ });
3446
+ toast10.success("Verification code sent to your phone");
3447
+ onSuccess(verification.data?.verificationId ?? "", normalizedPhone);
3448
+ } catch (error) {
3449
+ const errorMessage = getErrorMessage3(error);
3450
+ if (isAuthError5(error)) {
3451
+ const errorCode = getErrorCode4(error);
3452
+ if (errorCode === "INVALID_PASSWORD" || errorCode === "USER_NOT_FOUND") {
3453
+ toast10.error("Incorrect password. Please try again.");
3454
+ return;
3455
+ }
3456
+ }
3457
+ toast10.error(errorMessage);
3458
+ } finally {
3459
+ setIsSubmitting(false);
3460
+ }
3461
+ };
3462
+ const isLoading = isSubmitting || isChecking;
3463
+ return /* @__PURE__ */ jsxs23(
3464
+ "form",
3465
+ {
3466
+ onSubmit: handleSubmit(onPhonePasswordSubmit),
3467
+ className: "p-4 space-y-4 border-t",
3468
+ children: [
3469
+ /* @__PURE__ */ jsxs23("div", { className: "space-y-4 w-full md:w-1/2", children: [
3470
+ /* @__PURE__ */ jsxs23("div", { className: "space-y-2", children: [
3471
+ /* @__PURE__ */ jsx26(Label3, { htmlFor: "phone", children: "Phone Number" }),
3472
+ /* @__PURE__ */ jsx26(
3473
+ Input7,
3474
+ {
3475
+ id: "phone",
3476
+ type: "tel",
3477
+ placeholder: "Enter your new phone number",
3478
+ ...register("phone"),
3479
+ disabled: isLoading
3480
+ }
3481
+ ),
3482
+ errors.phone && /* @__PURE__ */ jsx26("p", { className: "text-sm text-destructive", children: errors.phone.message })
2737
3483
  ] }),
2738
- /* @__PURE__ */ jsxs23("div", { children: [
2739
- /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-muted-foreground", children: "Last Sign In" }),
2740
- /* @__PURE__ */ jsx25("p", { className: "text-sm", children: user.lastSignInAt ? new Date(user.lastSignInAt).toLocaleString() : "Never" })
3484
+ /* @__PURE__ */ jsxs23("div", { className: "space-y-2", children: [
3485
+ /* @__PURE__ */ jsx26(Label3, { htmlFor: "password", children: "Password" }),
3486
+ /* @__PURE__ */ jsxs23("div", { className: "relative", children: [
3487
+ /* @__PURE__ */ jsx26(
3488
+ Input7,
3489
+ {
3490
+ id: "password",
3491
+ type: showPassword ? "text" : "password",
3492
+ autoComplete: "current-password",
3493
+ placeholder: "Enter your password",
3494
+ ...register("password"),
3495
+ disabled: isLoading
3496
+ }
3497
+ ),
3498
+ /* @__PURE__ */ jsx26(
3499
+ "button",
3500
+ {
3501
+ type: "button",
3502
+ onClick: () => setShowPassword(!showPassword),
3503
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
3504
+ children: showPassword ? /* @__PURE__ */ jsx26(IconEyeOff6, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx26(IconEye6, { className: "h-4 w-4" })
3505
+ }
3506
+ )
3507
+ ] }),
3508
+ errors.password && /* @__PURE__ */ jsx26("p", { className: "text-sm text-destructive", children: errors.password.message })
3509
+ ] })
3510
+ ] }),
3511
+ /* @__PURE__ */ jsxs23("div", { className: "flex justify-end gap-2", children: [
3512
+ /* @__PURE__ */ jsx26(
3513
+ Button16,
3514
+ {
3515
+ type: "button",
3516
+ variant: "outline",
3517
+ onClick: onCancel,
3518
+ disabled: isLoading,
3519
+ children: "Cancel"
3520
+ }
3521
+ ),
3522
+ /* @__PURE__ */ jsxs23(Button16, { type: "submit", disabled: isLoading, children: [
3523
+ isLoading && /* @__PURE__ */ jsx26(Spinner8, { className: "mr-2 h-4 w-4" }),
3524
+ isChecking ? "Checking\u2026" : buttonText
2741
3525
  ] })
2742
3526
  ] })
3527
+ ]
3528
+ }
3529
+ );
3530
+ }
3531
+
3532
+ // src/components/profile/verify-change-phone-form.tsx
3533
+ import { useState as useState19 } from "react";
3534
+ import { toast as toast11 } from "sonner";
3535
+ import { jsx as jsx27 } from "react/jsx-runtime";
3536
+ function isAuthError6(error) {
3537
+ return typeof error === "object" && error !== null && ("code" in error || "message" in error || "name" in error);
3538
+ }
3539
+ function getErrorCode5(error) {
3540
+ if (error.code) {
3541
+ return error.code;
3542
+ }
3543
+ if (error.message) {
3544
+ const upperMessage = error.message.toUpperCase().trim();
3545
+ const validCodes2 = [
3546
+ "USER_NOT_FOUND",
3547
+ "USER_EXISTS",
3548
+ "INVALID_PASSWORD",
3549
+ "VERIFICATION_EXPIRED",
3550
+ "VERIFICATION_MISMATCH",
3551
+ "VERIFICATION_NOT_FOUND",
3552
+ "TOO_MANY_ATTEMPTS",
3553
+ "UNAUTHORIZED"
3554
+ ];
3555
+ if (validCodes2.includes(upperMessage)) {
3556
+ return upperMessage;
3557
+ }
3558
+ }
3559
+ return void 0;
3560
+ }
3561
+ function getErrorMessage4(error) {
3562
+ if (isAuthError6(error)) {
3563
+ const errorCode = getErrorCode5(error);
3564
+ switch (errorCode) {
3565
+ case "USER_EXISTS":
3566
+ return "This phone number is already taken. Please use a different number.";
3567
+ case "VERIFICATION_EXPIRED":
3568
+ return "Verification code has expired. Please request a new one.";
3569
+ case "VERIFICATION_MISMATCH":
3570
+ return "Invalid verification code. Please try again.";
3571
+ case "VERIFICATION_NOT_FOUND":
3572
+ return "Verification not found. Please request a new code.";
3573
+ default:
3574
+ return error.message || "An error occurred. Please try again.";
3575
+ }
3576
+ }
3577
+ if (error instanceof Error) {
3578
+ return error.message;
3579
+ }
3580
+ return "An error occurred. Please try again.";
3581
+ }
3582
+ function VerifyChangePhoneForm({
3583
+ phone,
3584
+ verificationId,
3585
+ onSuccess,
3586
+ onCancel
3587
+ }) {
3588
+ const { refresh } = useSession();
3589
+ const { hooks } = useApi();
3590
+ const [isSubmitting, setIsSubmitting] = useState19(false);
3591
+ const [currentVerificationId, setCurrentVerificationId] = useState19(verificationId);
3592
+ const verifyPhoneOtpMutation = hooks.useMutation(
3593
+ "post",
3594
+ "/phone/verification/confirm"
3595
+ );
3596
+ const updatePhoneMutation = hooks.useMutation("put", "/profile/phone");
3597
+ const requestPhoneOtpMutation = hooks.useMutation(
3598
+ "post",
3599
+ "/phone/verification/request"
3600
+ );
3601
+ const onOtpSubmit = async (code) => {
3602
+ if (!currentVerificationId) {
3603
+ toast11.error("Verification not found. Please request a new code.");
3604
+ return;
3605
+ }
3606
+ try {
3607
+ setIsSubmitting(true);
3608
+ await verifyPhoneOtpMutation.mutateAsync({
3609
+ body: {
3610
+ verificationId: currentVerificationId,
3611
+ code,
3612
+ context: "change-phone"
3613
+ }
3614
+ });
3615
+ await updatePhoneMutation.mutateAsync({
3616
+ body: { phone }
3617
+ });
3618
+ toast11.success("Phone number updated successfully");
3619
+ await refresh();
3620
+ onSuccess();
3621
+ } catch (error) {
3622
+ const errorMessage = getErrorMessage4(error);
3623
+ toast11.error(errorMessage);
3624
+ } finally {
3625
+ setIsSubmitting(false);
3626
+ }
3627
+ };
3628
+ if (!currentVerificationId) {
3629
+ toast11.error("Verification not found. Please request a new code.");
3630
+ return null;
3631
+ }
3632
+ return /* @__PURE__ */ jsx27(
3633
+ OtpVerificationModal,
3634
+ {
3635
+ open: true,
3636
+ title: "Verify phone",
3637
+ description: `Enter the verification code sent to ${phone}`,
3638
+ verificationId: currentVerificationId,
3639
+ isLoading: isSubmitting,
3640
+ onSubmit: onOtpSubmit,
3641
+ onResend: async () => {
3642
+ try {
3643
+ setIsSubmitting(true);
3644
+ const next = await requestPhoneOtpMutation.mutateAsync({
3645
+ body: {
3646
+ phone,
3647
+ context: "change-phone"
3648
+ }
3649
+ });
3650
+ setCurrentVerificationId(next.data?.verificationId ?? null);
3651
+ toast11.success("Verification code resent");
3652
+ } catch (error) {
3653
+ toast11.error(getErrorMessage4(error));
3654
+ } finally {
3655
+ setIsSubmitting(false);
3656
+ }
3657
+ },
3658
+ onCancel
3659
+ }
3660
+ );
3661
+ }
3662
+
3663
+ // src/components/profile/change-phone-form.tsx
3664
+ import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
3665
+ function ChangePhoneForm() {
3666
+ const { user } = useSession();
3667
+ const [isOpen, setIsOpen] = useState20(false);
3668
+ const [showOtp, setShowOtp] = useState20(false);
3669
+ const [verificationId, setVerificationId] = useState20(null);
3670
+ const [newPhone, setNewPhone] = useState20("");
3671
+ const resetForms = () => {
3672
+ setShowOtp(false);
3673
+ setVerificationId(null);
3674
+ setNewPhone("");
3675
+ };
3676
+ const handleRequestSuccess = (id, phone) => {
3677
+ setVerificationId(id);
3678
+ setNewPhone(phone);
3679
+ setShowOtp(true);
3680
+ };
3681
+ const handleVerifySuccess = () => {
3682
+ resetForms();
3683
+ setIsOpen(false);
3684
+ };
3685
+ const handleCancel = () => {
3686
+ resetForms();
3687
+ setIsOpen(false);
3688
+ };
3689
+ const title = user?.phone ? "Change Phone" : "Add Phone";
3690
+ const description = user?.phone ? "Update your phone number" : "Add a phone number to your account";
3691
+ return /* @__PURE__ */ jsx28(Collapsible3, { open: isOpen, onOpenChange: setIsOpen, children: /* @__PURE__ */ jsxs24("div", { className: "border rounded-lg", children: [
3692
+ /* @__PURE__ */ jsx28(CollapsibleTrigger3, { asChild: true, children: /* @__PURE__ */ jsxs24(Button17, { variant: "ghost", className: "w-full justify-between p-4 h-auto", children: [
3693
+ /* @__PURE__ */ jsxs24("div", { className: "flex flex-col items-start", children: [
3694
+ /* @__PURE__ */ jsx28("span", { className: "font-medium", children: title }),
3695
+ /* @__PURE__ */ jsx28("span", { className: "text-sm text-muted-foreground", children: description })
2743
3696
  ] }),
2744
- user.userRoles && user.userRoles.length > 0 && /* @__PURE__ */ jsxs23(Card, { className: "md:col-span-2", children: [
2745
- /* @__PURE__ */ jsxs23(CardHeader, { children: [
2746
- /* @__PURE__ */ jsx25(CardTitle, { children: "Roles" }),
2747
- /* @__PURE__ */ jsx25(CardDescription, { children: "Your assigned roles" })
2748
- ] }),
2749
- /* @__PURE__ */ jsx25(CardContent, { children: /* @__PURE__ */ jsx25("div", { className: "flex flex-wrap gap-2", children: user.userRoles.map((role) => /* @__PURE__ */ jsx25(
2750
- "div",
2751
- {
2752
- className: "px-3 py-1 bg-primary/10 text-primary rounded-full text-sm",
2753
- children: role.name
2754
- },
2755
- role.id
2756
- )) }) })
2757
- ] })
3697
+ /* @__PURE__ */ jsx28(
3698
+ IconChevronDown3,
3699
+ {
3700
+ className: `h-4 w-4 transition-transform ${isOpen ? "rotate-180" : ""}`
3701
+ }
3702
+ )
3703
+ ] }) }),
3704
+ /* @__PURE__ */ jsx28(CollapsibleContent3, { children: showOtp ? /* @__PURE__ */ jsx28(
3705
+ VerifyChangePhoneForm,
3706
+ {
3707
+ phone: newPhone,
3708
+ verificationId,
3709
+ onSuccess: handleVerifySuccess,
3710
+ onCancel: handleCancel
3711
+ }
3712
+ ) : /* @__PURE__ */ jsx28(
3713
+ RequestChangePhoneForm,
3714
+ {
3715
+ onSuccess: handleRequestSuccess,
3716
+ onCancel: handleCancel,
3717
+ buttonText: title
3718
+ }
3719
+ ) })
3720
+ ] }) });
3721
+ }
3722
+
3723
+ // src/components/profile/security.tsx
3724
+ import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
3725
+ function Security() {
3726
+ return /* @__PURE__ */ jsxs25("div", { className: "p-6 space-y-6", children: [
3727
+ /* @__PURE__ */ jsxs25("div", { children: [
3728
+ /* @__PURE__ */ jsx29("h1", { className: "text-2xl font-semibold", children: "Security" }),
3729
+ /* @__PURE__ */ jsx29("p", { className: "text-muted-foreground", children: "Manage your security settings" })
3730
+ ] }),
3731
+ /* @__PURE__ */ jsxs25("div", { className: "space-y-4", children: [
3732
+ /* @__PURE__ */ jsx29(ChangePasswordForm, {}),
3733
+ /* @__PURE__ */ jsx29(ChangeEmailForm, {}),
3734
+ /* @__PURE__ */ jsx29(ChangePhoneForm, {})
2758
3735
  ] })
2759
3736
  ] });
2760
3737
  }
2761
3738
 
2762
3739
  // src/components/skeletons/auth-form-skeleton.tsx
2763
- import { Skeleton as Skeleton3 } from "@mesob/ui/components/skeleton";
2764
- import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
3740
+ import { Skeleton as Skeleton2 } from "@mesob/ui/components/skeleton";
3741
+ import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
2765
3742
  function AuthFormSkeleton() {
2766
- return /* @__PURE__ */ jsxs24("div", { className: "w-full max-w-md space-y-6 p-6", children: [
2767
- /* @__PURE__ */ jsxs24("div", { className: "space-y-2 text-center", children: [
2768
- /* @__PURE__ */ jsx26(Skeleton3, { className: "h-8 w-48 mx-auto" }),
2769
- /* @__PURE__ */ jsx26(Skeleton3, { className: "h-4 w-64 mx-auto" })
3743
+ return /* @__PURE__ */ jsxs26("div", { className: "w-full max-w-md space-y-6 p-6", children: [
3744
+ /* @__PURE__ */ jsxs26("div", { className: "space-y-2 text-center", children: [
3745
+ /* @__PURE__ */ jsx30(Skeleton2, { className: "h-8 w-48 mx-auto" }),
3746
+ /* @__PURE__ */ jsx30(Skeleton2, { className: "h-4 w-64 mx-auto" })
2770
3747
  ] }),
2771
- /* @__PURE__ */ jsxs24("div", { className: "space-y-4", children: [
2772
- /* @__PURE__ */ jsxs24("div", { className: "space-y-2", children: [
2773
- /* @__PURE__ */ jsx26(Skeleton3, { className: "h-4 w-24" }),
2774
- /* @__PURE__ */ jsx26(Skeleton3, { className: "h-10 w-full" })
3748
+ /* @__PURE__ */ jsxs26("div", { className: "space-y-4", children: [
3749
+ /* @__PURE__ */ jsxs26("div", { className: "space-y-2", children: [
3750
+ /* @__PURE__ */ jsx30(Skeleton2, { className: "h-4 w-24" }),
3751
+ /* @__PURE__ */ jsx30(Skeleton2, { className: "h-10 w-full" })
2775
3752
  ] }),
2776
- /* @__PURE__ */ jsxs24("div", { className: "space-y-2", children: [
2777
- /* @__PURE__ */ jsx26(Skeleton3, { className: "h-4 w-24" }),
2778
- /* @__PURE__ */ jsx26(Skeleton3, { className: "h-10 w-full" })
3753
+ /* @__PURE__ */ jsxs26("div", { className: "space-y-2", children: [
3754
+ /* @__PURE__ */ jsx30(Skeleton2, { className: "h-4 w-24" }),
3755
+ /* @__PURE__ */ jsx30(Skeleton2, { className: "h-10 w-full" })
2779
3756
  ] }),
2780
- /* @__PURE__ */ jsx26(Skeleton3, { className: "h-10 w-full" })
3757
+ /* @__PURE__ */ jsx30(Skeleton2, { className: "h-10 w-full" })
2781
3758
  ] }),
2782
- /* @__PURE__ */ jsxs24("div", { className: "space-y-2", children: [
2783
- /* @__PURE__ */ jsx26(Skeleton3, { className: "h-px w-full" }),
2784
- /* @__PURE__ */ jsx26(Skeleton3, { className: "h-4 w-32 mx-auto" })
3759
+ /* @__PURE__ */ jsxs26("div", { className: "space-y-2", children: [
3760
+ /* @__PURE__ */ jsx30(Skeleton2, { className: "h-px w-full" }),
3761
+ /* @__PURE__ */ jsx30(Skeleton2, { className: "h-4 w-32 mx-auto" })
2785
3762
  ] })
2786
3763
  ] });
2787
3764
  }
2788
3765
 
2789
- // src/utils/cookie.ts
2790
- var isProduction = typeof process !== "undefined" && process.env.NODE_ENV === "production";
2791
- var getSessionCookieName = (config) => {
2792
- const prefix = config.cookiePrefix || "";
2793
- const baseName = "session_token";
2794
- if (prefix) {
2795
- return `${prefix}_${baseName}`;
2796
- }
2797
- return isProduction ? "__Host-session_token" : baseName;
2798
- };
3766
+ // src/components/skeletons/profile-skeleton.tsx
3767
+ import { Skeleton as Skeleton3 } from "@mesob/ui/components/skeleton";
3768
+ import { jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
3769
+ function ProfileSkeleton() {
3770
+ return /* @__PURE__ */ jsxs27("div", { className: "w-full max-w-4xl space-y-8 p-6", children: [
3771
+ /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-6", children: [
3772
+ /* @__PURE__ */ jsx31(Skeleton3, { className: "h-24 w-24 rounded-full" }),
3773
+ /* @__PURE__ */ jsxs27("div", { className: "space-y-2 flex-1", children: [
3774
+ /* @__PURE__ */ jsx31(Skeleton3, { className: "h-8 w-48" }),
3775
+ /* @__PURE__ */ jsx31(Skeleton3, { className: "h-4 w-64" })
3776
+ ] })
3777
+ ] }),
3778
+ /* @__PURE__ */ jsx31("div", { className: "space-y-6", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs27("div", { className: "space-y-4", children: [
3779
+ /* @__PURE__ */ jsx31(Skeleton3, { className: "h-6 w-32" }),
3780
+ /* @__PURE__ */ jsxs27("div", { className: "space-y-3", children: [
3781
+ /* @__PURE__ */ jsxs27("div", { className: "flex justify-between items-center", children: [
3782
+ /* @__PURE__ */ jsx31(Skeleton3, { className: "h-4 w-24" }),
3783
+ /* @__PURE__ */ jsx31(Skeleton3, { className: "h-4 w-32" })
3784
+ ] }),
3785
+ /* @__PURE__ */ jsxs27("div", { className: "flex justify-between items-center", children: [
3786
+ /* @__PURE__ */ jsx31(Skeleton3, { className: "h-4 w-24" }),
3787
+ /* @__PURE__ */ jsx31(Skeleton3, { className: "h-4 w-40" })
3788
+ ] })
3789
+ ] })
3790
+ ] }, i)) })
3791
+ ] });
3792
+ }
2799
3793
 
2800
3794
  // src/hooks/use-session-cookie-name.ts
2801
3795
  function useSessionCookieName() {
@@ -2803,32 +3797,36 @@ function useSessionCookieName() {
2803
3797
  return getSessionCookieName(config);
2804
3798
  }
2805
3799
  export {
3800
+ Account,
2806
3801
  AuthCard,
2807
3802
  AuthErrorBoundary,
2808
3803
  AuthFormSkeleton,
2809
3804
  DataTable,
2810
3805
  ErrorBoundary,
2811
- ForgotPasswordPage,
3806
+ ForgotPassword,
2812
3807
  MesobAuthProvider,
2813
- PermissionsPage,
2814
- ProfilePage,
3808
+ Permissions,
2815
3809
  ProfileSkeleton,
2816
- ResetPasswordPage,
2817
- RolesPage,
2818
- SessionsPage,
2819
- SignInPage,
2820
- SignUpPage,
3810
+ ResetPasswordForm,
3811
+ Roles,
3812
+ Security,
3813
+ Sessions,
3814
+ SignIn,
3815
+ SignUp,
2821
3816
  TableSkeleton,
2822
- TenantsPage,
2823
- UsersPage,
3817
+ Tenants,
3818
+ Users,
2824
3819
  VerificationForm,
2825
- VerifyEmailPage,
2826
- VerifyPhonePage,
3820
+ VerifyEmail,
3821
+ VerifyPhone,
2827
3822
  getSessionCookieName,
2828
3823
  handleError,
3824
+ hasAuthCookie,
2829
3825
  normalizePhone,
2830
3826
  useApi,
2831
3827
  useConfig,
3828
+ useHasAuthCookie,
3829
+ useHasAuthCookie as useIsAuthenticated,
2832
3830
  useSession,
2833
3831
  useSessionCookieName,
2834
3832
  useTranslator