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