@mesob/auth-react 0.3.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/dist/components/auth/auth-layout.d.ts +1 -1
  2. package/dist/components/auth/auth-layout.js +10 -2
  3. package/dist/components/auth/auth-layout.js.map +1 -1
  4. package/dist/components/auth/countdown.js +8 -6
  5. package/dist/components/auth/countdown.js.map +1 -1
  6. package/dist/components/auth/forgot-password.js +21 -19
  7. package/dist/components/auth/forgot-password.js.map +1 -1
  8. package/dist/components/auth/reset-password-form.js +22 -21
  9. package/dist/components/auth/reset-password-form.js.map +1 -1
  10. package/dist/components/auth/set-password.d.ts +9 -0
  11. package/dist/components/auth/set-password.js +527 -0
  12. package/dist/components/auth/set-password.js.map +1 -0
  13. package/dist/components/auth/sign-in.js +45 -26
  14. package/dist/components/auth/sign-in.js.map +1 -1
  15. package/dist/components/auth/sign-up.js +25 -29
  16. package/dist/components/auth/sign-up.js.map +1 -1
  17. package/dist/components/auth/verification-form.js +24 -27
  18. package/dist/components/auth/verification-form.js.map +1 -1
  19. package/dist/components/auth/verify-email.js +40 -31
  20. package/dist/components/auth/verify-email.js.map +1 -1
  21. package/dist/components/auth/verify-phone.js +40 -31
  22. package/dist/components/auth/verify-phone.js.map +1 -1
  23. package/dist/components/authorization/deny.d.ts +11 -0
  24. package/dist/components/authorization/deny.js +52 -0
  25. package/dist/components/authorization/deny.js.map +1 -0
  26. package/dist/components/authorization/grant.d.ts +12 -0
  27. package/dist/components/authorization/grant.js +57 -0
  28. package/dist/components/authorization/grant.js.map +1 -0
  29. package/dist/components/iam/permission-selector.d.ts +19 -0
  30. package/dist/components/iam/permission-selector.js +122 -0
  31. package/dist/components/iam/permission-selector.js.map +1 -0
  32. package/dist/components/iam/permissions.js +21 -33
  33. package/dist/components/iam/permissions.js.map +1 -1
  34. package/dist/components/iam/role-detail-layout.d.ts +11 -0
  35. package/dist/components/iam/role-detail-layout.js +137 -0
  36. package/dist/components/iam/role-detail-layout.js.map +1 -0
  37. package/dist/components/iam/role-detail-page.d.ts +9 -0
  38. package/dist/components/iam/role-detail-page.js +229 -0
  39. package/dist/components/iam/role-detail-page.js.map +1 -0
  40. package/dist/components/iam/role-permissions-page.d.ts +8 -0
  41. package/dist/components/iam/role-permissions-page.js +397 -0
  42. package/dist/components/iam/role-permissions-page.js.map +1 -0
  43. package/dist/components/iam/roles.js +20 -10
  44. package/dist/components/iam/roles.js.map +1 -1
  45. package/dist/components/iam/tenants.js +9 -2
  46. package/dist/components/iam/tenants.js.map +1 -1
  47. package/dist/components/iam/users.js +10 -9
  48. package/dist/components/iam/users.js.map +1 -1
  49. package/dist/components/profile/account.js +110 -19
  50. package/dist/components/profile/account.js.map +1 -1
  51. package/dist/components/profile/change-email-form.js +26 -29
  52. package/dist/components/profile/change-email-form.js.map +1 -1
  53. package/dist/components/profile/change-phone-form.js +26 -29
  54. package/dist/components/profile/change-phone-form.js.map +1 -1
  55. package/dist/components/profile/change-profile.d.ts +2 -1
  56. package/dist/components/profile/change-profile.js +16 -8
  57. package/dist/components/profile/change-profile.js.map +1 -1
  58. package/dist/components/profile/otp-verification-modal.js +24 -27
  59. package/dist/components/profile/otp-verification-modal.js.map +1 -1
  60. package/dist/components/profile/security.js +88 -57
  61. package/dist/components/profile/security.js.map +1 -1
  62. package/dist/components/profile/verify-change-email-form.js +24 -27
  63. package/dist/components/profile/verify-change-email-form.js.map +1 -1
  64. package/dist/components/profile/verify-change-phone-form.js +24 -27
  65. package/dist/components/profile/verify-change-phone-form.js.map +1 -1
  66. package/dist/index.d.ts +9 -1
  67. package/dist/index.js +1897 -821
  68. package/dist/index.js.map +1 -1
  69. package/dist/pages/auth/forgot-password.d.ts +7 -0
  70. package/dist/pages/auth/forgot-password.js +784 -0
  71. package/dist/pages/auth/forgot-password.js.map +1 -0
  72. package/dist/pages/auth/layout.d.ts +8 -0
  73. package/dist/pages/auth/layout.js +562 -0
  74. package/dist/pages/auth/layout.js.map +1 -0
  75. package/dist/pages/auth/reset-password.d.ts +10 -0
  76. package/dist/pages/auth/reset-password.js +913 -0
  77. package/dist/pages/auth/reset-password.js.map +1 -0
  78. package/dist/pages/auth/set-password.d.ts +10 -0
  79. package/dist/pages/auth/set-password.js +946 -0
  80. package/dist/pages/auth/set-password.js.map +1 -0
  81. package/dist/pages/auth/sign-in.d.ts +10 -0
  82. package/dist/pages/auth/sign-in.js +984 -0
  83. package/dist/pages/auth/sign-in.js.map +1 -0
  84. package/dist/pages/auth/sign-up.d.ts +10 -0
  85. package/dist/pages/auth/sign-up.js +940 -0
  86. package/dist/pages/auth/sign-up.js.map +1 -0
  87. package/dist/pages/auth/verify-email.d.ts +10 -0
  88. package/dist/pages/auth/verify-email.js +950 -0
  89. package/dist/pages/auth/verify-email.js.map +1 -0
  90. package/dist/pages/auth/verify-phone.d.ts +10 -0
  91. package/dist/pages/auth/verify-phone.js +964 -0
  92. package/dist/pages/auth/verify-phone.js.map +1 -0
  93. package/dist/pages/iam/permissions.d.ts +5 -0
  94. package/dist/pages/iam/permissions.js +308 -0
  95. package/dist/pages/iam/permissions.js.map +1 -0
  96. package/dist/pages/iam/role-detail-layout.d.ts +12 -0
  97. package/dist/pages/iam/role-detail-layout.js +145 -0
  98. package/dist/pages/iam/role-detail-layout.js.map +1 -0
  99. package/dist/pages/iam/role-detail.d.ts +12 -0
  100. package/dist/pages/iam/role-detail.js +241 -0
  101. package/dist/pages/iam/role-detail.js.map +1 -0
  102. package/dist/pages/iam/role-permissions.d.ts +12 -0
  103. package/dist/pages/iam/role-permissions.js +409 -0
  104. package/dist/pages/iam/role-permissions.js.map +1 -0
  105. package/dist/pages/iam/role-users.d.ts +12 -0
  106. package/dist/pages/iam/role-users.js +825 -0
  107. package/dist/pages/iam/role-users.js.map +1 -0
  108. package/dist/pages/iam/roles.d.ts +5 -0
  109. package/dist/pages/iam/roles.js +684 -0
  110. package/dist/pages/iam/roles.js.map +1 -0
  111. package/dist/pages/iam/sessions.d.ts +5 -0
  112. package/dist/pages/iam/sessions.js +315 -0
  113. package/dist/pages/iam/sessions.js.map +1 -0
  114. package/dist/pages/iam/tenant-detail.d.ts +10 -0
  115. package/dist/pages/iam/tenant-detail.js +186 -0
  116. package/dist/pages/iam/tenant-detail.js.map +1 -0
  117. package/dist/pages/iam/tenants.d.ts +5 -0
  118. package/dist/pages/iam/tenants.js +610 -0
  119. package/dist/pages/iam/tenants.js.map +1 -0
  120. package/dist/pages/iam/user-activity.d.ts +10 -0
  121. package/dist/pages/iam/user-activity.js +850 -0
  122. package/dist/pages/iam/user-activity.js.map +1 -0
  123. package/dist/pages/iam/user-detail-layout.d.ts +12 -0
  124. package/dist/pages/iam/user-detail-layout.js +106 -0
  125. package/dist/pages/iam/user-detail-layout.js.map +1 -0
  126. package/dist/pages/iam/user-detail.d.ts +10 -0
  127. package/dist/pages/iam/user-detail.js +102 -0
  128. package/dist/pages/iam/user-detail.js.map +1 -0
  129. package/dist/pages/iam/users.d.ts +5 -0
  130. package/dist/pages/iam/users.js +1275 -0
  131. package/dist/pages/iam/users.js.map +1 -0
  132. package/dist/pages/profile/account.d.ts +5 -0
  133. package/dist/pages/profile/account.js +182 -0
  134. package/dist/pages/profile/account.js.map +1 -0
  135. package/dist/pages/profile/layout.d.ts +8 -0
  136. package/dist/pages/profile/layout.js +133 -0
  137. package/dist/pages/profile/layout.js.map +1 -0
  138. package/dist/pages/profile/security.d.ts +5 -0
  139. package/dist/pages/profile/security.js +1539 -0
  140. package/dist/pages/profile/security.js.map +1 -0
  141. package/dist/{types-vcfvnAzQ.d.ts → types-g9QcNRxT.d.ts} +13 -7
  142. package/package.json +102 -3
package/dist/index.js CHANGED
@@ -20,8 +20,7 @@ import {
20
20
  FormItem,
21
21
  FormLabel,
22
22
  FormMessage,
23
- Input,
24
- Spinner
23
+ Input
25
24
  } from "@mesob/ui/components";
26
25
  import { useMesob as useMesob2 } from "@mesob/ui/providers";
27
26
  import { IconAlertCircle } from "@tabler/icons-react";
@@ -367,7 +366,11 @@ var AUTH_ERROR_MAPPING = {
367
366
  },
368
367
  HAS_NO_PASSWORD: {
369
368
  title: "No Password Set",
370
- description: "Your account does not have a password set (e.g. social login). Please sign in with your provider or reset your password."
369
+ description: "Your account does not have a password yet. Continue to set a password before signing in."
370
+ },
371
+ PASSWORD_ALREADY_SET: {
372
+ title: "Password Already Set",
373
+ description: "This account already has a password. Use the normal sign-in form instead."
371
374
  }
372
375
  };
373
376
  var validCodes = Object.keys(AUTH_ERROR_MAPPING);
@@ -440,13 +443,21 @@ var AuthLayout = ({
440
443
  logoImage
441
444
  }) => {
442
445
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
443
- /* @__PURE__ */ jsx3("div", { className: "flex size-8 mb-6 w-full items-center justify-center rounded-md", children: /* @__PURE__ */ jsx3("img", { src: logoImage || "", alt: "Mesob", width: 42, height: 42 }) }),
446
+ /* @__PURE__ */ jsx3("div", { className: "flex size-8 mb-6 w-full items-center justify-center rounded-md", children: /* @__PURE__ */ jsx3(
447
+ "img",
448
+ {
449
+ src: logoImage || "",
450
+ alt: title,
451
+ width: 42,
452
+ height: 42
453
+ }
454
+ ) }),
444
455
  /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
445
456
  /* @__PURE__ */ jsx3("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
446
457
  description && /* @__PURE__ */ jsx3("p", { className: "mt-2 text-sm text-muted-foreground", children: description })
447
458
  ] }),
448
459
  children,
449
- /* @__PURE__ */ jsx3("div", { className: "mt-2 w-full", children: footer && /* @__PURE__ */ jsx3("div", { className: "w-full text-center text-sm text-muted-foreground", children: footer }) })
460
+ 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 }) })
450
461
  ] });
451
462
  };
452
463
 
@@ -517,7 +528,7 @@ var ForgotPassword = () => {
517
528
  return /* @__PURE__ */ jsxs2(
518
529
  AuthLayout,
519
530
  {
520
- title: t("title"),
531
+ title: config.ui.name,
521
532
  description: t("description"),
522
533
  logoImage,
523
534
  footer: Link ? /* @__PURE__ */ jsx4(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.backToSignIn") }) : /* @__PURE__ */ jsx4(
@@ -547,29 +558,20 @@ var ForgotPassword = () => {
547
558
  name: "account",
548
559
  render: ({ field }) => /* @__PURE__ */ jsxs2(FormItem, { children: [
549
560
  /* @__PURE__ */ jsx4(FormLabel, { children: t("form.accountLabel") }),
550
- /* @__PURE__ */ jsx4(FormControl, { children: /* @__PURE__ */ jsx4(
551
- Input,
552
- {
553
- ...field,
554
- type: "text",
555
- placeholder: t("form.accountPlaceholder")
556
- }
557
- ) }),
561
+ /* @__PURE__ */ jsx4(FormControl, { children: /* @__PURE__ */ jsx4(Input, { ...field, type: "text" }) }),
558
562
  /* @__PURE__ */ jsx4(FormMessage, {})
559
563
  ] })
560
564
  }
561
565
  ),
562
- /* @__PURE__ */ jsxs2(
566
+ /* @__PURE__ */ jsx4(
563
567
  Button,
564
568
  {
565
569
  type: "submit",
566
570
  form: "forgot-password-form",
567
571
  className: "w-full",
568
572
  disabled: isLoading || forgotPasswordMutation.isPending,
569
- children: [
570
- isLoading || forgotPasswordMutation.isPending && /* @__PURE__ */ jsx4(Spinner, {}),
571
- isLoading || forgotPasswordMutation.isPending ? t("form.submitting") : t("form.submit")
572
- ]
573
+ loading: isLoading || forgotPasswordMutation.isPending,
574
+ children: isLoading || forgotPasswordMutation.isPending ? t("form.submitting") : t("form.submit")
573
575
  }
574
576
  )
575
577
  ]
@@ -602,7 +604,6 @@ import {
602
604
  InputOTP,
603
605
  InputOTPGroup,
604
606
  InputOTPSlot,
605
- Spinner as Spinner2,
606
607
  useFormField
607
608
  } from "@mesob/ui/components";
608
609
  import { useMesob as useMesob3 } from "@mesob/ui/providers";
@@ -612,12 +613,7 @@ import { useForm as useForm2 } from "react-hook-form";
612
613
  import { toast as toast2 } from "sonner";
613
614
  import { z as z2 } from "zod";
614
615
  import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
615
- function PasswordInput({
616
- field,
617
- show,
618
- onToggle,
619
- placeholder
620
- }) {
616
+ function PasswordInput({ field, show, onToggle }) {
621
617
  const { formItemId, error } = useFormField();
622
618
  return /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
623
619
  /* @__PURE__ */ jsx5(
@@ -626,7 +622,6 @@ function PasswordInput({
626
622
  ...field,
627
623
  id: formItemId,
628
624
  type: show ? "text" : "password",
629
- placeholder,
630
625
  "aria-invalid": !!error,
631
626
  className: "pr-10"
632
627
  }
@@ -747,7 +742,7 @@ var ResetPasswordForm = ({
747
742
  return /* @__PURE__ */ jsxs3(
748
743
  AuthLayout,
749
744
  {
750
- title: t("title"),
745
+ title: config.ui.name,
751
746
  description: t("description"),
752
747
  logoImage,
753
748
  footer: /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between w-full gap-2", children: [
@@ -810,8 +805,7 @@ var ResetPasswordForm = ({
810
805
  {
811
806
  field,
812
807
  show: showPassword,
813
- onToggle: () => setShowPassword(!showPassword),
814
- placeholder: t("form.passwordPlaceholder")
808
+ onToggle: () => setShowPassword(!showPassword)
815
809
  }
816
810
  ),
817
811
  /* @__PURE__ */ jsx5(FormMessage2, {})
@@ -830,25 +824,22 @@ var ResetPasswordForm = ({
830
824
  {
831
825
  field,
832
826
  show: showPassword,
833
- onToggle: () => setShowPassword(!showPassword),
834
- placeholder: t("form.passwordPlaceholder")
827
+ onToggle: () => setShowPassword(!showPassword)
835
828
  }
836
829
  ),
837
830
  /* @__PURE__ */ jsx5(FormMessage2, {})
838
831
  ] })
839
832
  }
840
833
  ),
841
- /* @__PURE__ */ jsxs3(
834
+ /* @__PURE__ */ jsx5(
842
835
  Button2,
843
836
  {
844
837
  type: "submit",
845
838
  form: "reset-password-form",
846
839
  className: "w-full",
847
840
  disabled: isLoading || resetPasswordMutation.isPending,
848
- children: [
849
- isLoading || resetPasswordMutation.isPending && /* @__PURE__ */ jsx5(Spinner2, {}),
850
- isLoading || resetPasswordMutation.isPending ? t("form.submitting") : t("form.submit")
851
- ]
841
+ loading: isLoading || resetPasswordMutation.isPending,
842
+ children: isLoading || resetPasswordMutation.isPending ? t("form.submitting") : t("form.submit")
852
843
  }
853
844
  )
854
845
  ]
@@ -864,7 +855,7 @@ var ResetPasswordForm = ({
864
855
  );
865
856
  };
866
857
 
867
- // src/components/auth/sign-in.tsx
858
+ // src/components/auth/set-password.tsx
868
859
  import { zodResolver as zodResolver3 } from "@hookform/resolvers/zod";
869
860
  import {
870
861
  Alert as Alert3,
@@ -882,7 +873,7 @@ import {
882
873
  } from "@mesob/ui/components";
883
874
  import { useMesob as useMesob4 } from "@mesob/ui/providers";
884
875
  import { IconAlertCircle as IconAlertCircle3, IconEye as IconEye2, IconEyeOff as IconEyeOff2 } from "@tabler/icons-react";
885
- import { useEffect as useEffect3, useState as useState4 } from "react";
876
+ import { useEffect as useEffect3, useEffectEvent, useState as useState4 } from "react";
886
877
  import { useForm as useForm3 } from "react-hook-form";
887
878
  import { toast as toast3 } from "sonner";
888
879
  import { z as z3 } from "zod";
@@ -905,15 +896,9 @@ function normalizePhone(phone) {
905
896
  return cleaned;
906
897
  }
907
898
 
908
- // src/components/auth/sign-in.tsx
909
- import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
910
- var isPhone = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
911
- function PasswordInput2({
912
- field,
913
- show,
914
- onToggle,
915
- placeholder
916
- }) {
899
+ // src/components/auth/set-password.tsx
900
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
901
+ function PasswordInput2({ field, show, onToggle }) {
917
902
  const { formItemId, error } = useFormField2();
918
903
  return /* @__PURE__ */ jsxs4("div", { className: "relative", children: [
919
904
  /* @__PURE__ */ jsx6(
@@ -922,8 +907,6 @@ function PasswordInput2({
922
907
  ...field,
923
908
  id: formItemId,
924
909
  type: show ? "text" : "password",
925
- placeholder,
926
- autoComplete: "current-password",
927
910
  "aria-invalid": !!error,
928
911
  className: "pr-10"
929
912
  }
@@ -942,52 +925,339 @@ function PasswordInput2({
942
925
  )
943
926
  ] });
944
927
  }
945
- var signInSchema = (t, phoneRegex) => z3.object({
946
- username: z3.string().trim().min(1, { message: t("errors.requiredField") }).refine(
928
+ var setPasswordSchema = (t) => z3.object({
929
+ password: z3.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError")),
930
+ confirmPassword: z3.string()
931
+ }).refine((data) => data.password === data.confirmPassword, {
932
+ message: t("errors.passwordsMismatch"),
933
+ path: ["confirmPassword"]
934
+ });
935
+ var getPhoneRegex = (phoneRegex) => {
936
+ if (typeof phoneRegex === "string") {
937
+ return new RegExp(phoneRegex);
938
+ }
939
+ return phoneRegex || /^(\+2519|\+2517|2519|2517|09|07)\d{8}$/;
940
+ };
941
+ var normalizeIdentifier = (identifier, phoneRegex) => {
942
+ const resolvedPhoneRegex = getPhoneRegex(phoneRegex);
943
+ return resolvedPhoneRegex.test(identifier) ? normalizePhone(identifier) : identifier;
944
+ };
945
+ var SetPassword = function SetPassword2({
946
+ identifier,
947
+ redirectUrl
948
+ } = {}) {
949
+ const { hooks, setAuth } = useApi();
950
+ const { config } = useConfig();
951
+ const mesob = useMesob4();
952
+ const t = useTranslator("Auth.setPassword");
953
+ const Link = mesob?.navigation?.Link;
954
+ const [error, setError] = useState4(null);
955
+ const [isLoading, setIsLoading] = useState4(false);
956
+ const [isChecking, setIsChecking] = useState4(true);
957
+ const [showPassword, setShowPassword] = useState4(false);
958
+ const [showConfirmPassword, setShowConfirmPassword] = useState4(false);
959
+ const [account, setAccount] = useState4(null);
960
+ const checkAccountMutation = hooks.useMutation("post", "/check-account");
961
+ const setPasswordMutation = hooks.useMutation("post", "/password/set");
962
+ const onNavigate = config.navigation?.onNavigate || ((path) => {
963
+ if (typeof window !== "undefined") {
964
+ window.location.href = path;
965
+ }
966
+ });
967
+ const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
968
+ const logoImage = config.ui.logoImage;
969
+ const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
970
+ const form = useForm3({
971
+ resolver: zodResolver3(setPasswordSchema(t)),
972
+ defaultValues: {
973
+ password: "",
974
+ confirmPassword: ""
975
+ }
976
+ });
977
+ useEffect3(() => {
978
+ if (error) {
979
+ toast3.error(error.title || "Error", {
980
+ description: error.description
981
+ });
982
+ }
983
+ }, [error]);
984
+ const loadAccount = useEffectEvent(async () => {
985
+ if (!identifier) {
986
+ setError({
987
+ title: t("errors.fallback"),
988
+ description: t("errors.missingIdentifier")
989
+ });
990
+ setIsChecking(false);
991
+ return;
992
+ }
993
+ try {
994
+ const normalizedIdentifier = normalizeIdentifier(
995
+ identifier,
996
+ config.phoneRegex
997
+ );
998
+ const res = await checkAccountMutation.mutateAsync({
999
+ body: { username: normalizedIdentifier }
1000
+ });
1001
+ if (!(res.exists && res.account && res.requiresPasswordSetup)) {
1002
+ setError({
1003
+ title: t("errors.fallback"),
1004
+ description: t("errors.accountNotEligible")
1005
+ });
1006
+ setIsChecking(false);
1007
+ return;
1008
+ }
1009
+ setAccount({
1010
+ fullName: res.account.fullName,
1011
+ email: res.account.email,
1012
+ phone: res.account.phone
1013
+ });
1014
+ } catch {
1015
+ setError({
1016
+ title: t("errors.fallback"),
1017
+ description: t("errors.accountLookupFailed")
1018
+ });
1019
+ } finally {
1020
+ setIsChecking(false);
1021
+ }
1022
+ });
1023
+ useEffect3(() => {
1024
+ loadAccount().catch(() => {
1025
+ setIsChecking(false);
1026
+ });
1027
+ }, [identifier]);
1028
+ const handleSubmit = form.handleSubmit(async (values) => {
1029
+ if (!identifier) {
1030
+ return;
1031
+ }
1032
+ setIsLoading(true);
1033
+ setError(null);
1034
+ try {
1035
+ const normalizedIdentifier = normalizeIdentifier(
1036
+ identifier,
1037
+ config.phoneRegex
1038
+ );
1039
+ const res = await setPasswordMutation.mutateAsync({
1040
+ body: {
1041
+ identifier: normalizedIdentifier,
1042
+ password: values.password
1043
+ }
1044
+ });
1045
+ if ("user" in res && "session" in res) {
1046
+ setAuth(res);
1047
+ }
1048
+ onNavigate(defaultRedirect);
1049
+ } catch (err) {
1050
+ handleError(err, setError, t);
1051
+ } finally {
1052
+ setIsLoading(false);
1053
+ }
1054
+ });
1055
+ const accountLabel = account?.email ? t("form.emailLabel") : t("form.phoneLabel");
1056
+ const accountValue = account?.email || account?.phone || identifier || "";
1057
+ let errorContent = null;
1058
+ if (error) {
1059
+ errorContent = typeof error === "string" ? { title: "Error", description: error } : error;
1060
+ }
1061
+ const showError = !isChecking && !!errorContent;
1062
+ const errorAlert = showError && errorContent && /* @__PURE__ */ jsxs4(Alert3, { variant: "destructive", className: "mt-4", children: [
1063
+ /* @__PURE__ */ jsx6(IconAlertCircle3, { className: "h-4 w-4" }),
1064
+ /* @__PURE__ */ jsx6(AlertTitle3, { children: errorContent.title }),
1065
+ /* @__PURE__ */ jsx6(AlertDescription3, { children: errorContent.description })
1066
+ ] });
1067
+ return /* @__PURE__ */ jsxs4(
1068
+ AuthLayout,
1069
+ {
1070
+ title: config.ui.name,
1071
+ description: t("description"),
1072
+ logoImage,
1073
+ footer: /* @__PURE__ */ jsxs4("p", { children: [
1074
+ t("footer.hasPassword"),
1075
+ " ",
1076
+ Link ? /* @__PURE__ */ jsx6(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.signInCta") }) : /* @__PURE__ */ jsx6(
1077
+ "a",
1078
+ {
1079
+ href: signInLink,
1080
+ onClick: (e) => {
1081
+ e.preventDefault();
1082
+ onNavigate(signInLink);
1083
+ },
1084
+ className: "text-primary hover:underline",
1085
+ children: t("footer.signInCta")
1086
+ }
1087
+ )
1088
+ ] }),
1089
+ children: [
1090
+ /* @__PURE__ */ jsx6(Form3, { ...form, children: /* @__PURE__ */ jsxs4(
1091
+ "form",
1092
+ {
1093
+ id: "set-password-form",
1094
+ onSubmit: handleSubmit,
1095
+ className: "space-y-4",
1096
+ children: [
1097
+ /* @__PURE__ */ jsxs4(FormItem3, { children: [
1098
+ /* @__PURE__ */ jsx6(FormLabel3, { children: t("form.fullNameLabel") }),
1099
+ /* @__PURE__ */ jsx6(FormControl3, { children: /* @__PURE__ */ jsx6(Input3, { value: account?.fullName || "", disabled: true }) })
1100
+ ] }),
1101
+ /* @__PURE__ */ jsxs4(FormItem3, { children: [
1102
+ /* @__PURE__ */ jsx6(FormLabel3, { children: accountLabel }),
1103
+ /* @__PURE__ */ jsx6(FormControl3, { children: /* @__PURE__ */ jsx6(Input3, { value: accountValue, disabled: true }) })
1104
+ ] }),
1105
+ /* @__PURE__ */ jsx6(
1106
+ FormField3,
1107
+ {
1108
+ control: form.control,
1109
+ name: "password",
1110
+ render: ({ field }) => /* @__PURE__ */ jsxs4(FormItem3, { children: [
1111
+ /* @__PURE__ */ jsx6(FormLabel3, { children: t("form.passwordLabel") }),
1112
+ /* @__PURE__ */ jsx6(
1113
+ PasswordInput2,
1114
+ {
1115
+ field,
1116
+ show: showPassword,
1117
+ onToggle: () => setShowPassword(!showPassword)
1118
+ }
1119
+ ),
1120
+ /* @__PURE__ */ jsx6(FormMessage3, {})
1121
+ ] })
1122
+ }
1123
+ ),
1124
+ /* @__PURE__ */ jsx6(
1125
+ FormField3,
1126
+ {
1127
+ control: form.control,
1128
+ name: "confirmPassword",
1129
+ render: ({ field }) => /* @__PURE__ */ jsxs4(FormItem3, { children: [
1130
+ /* @__PURE__ */ jsx6(FormLabel3, { children: t("form.confirmPasswordLabel") }),
1131
+ /* @__PURE__ */ jsx6(
1132
+ PasswordInput2,
1133
+ {
1134
+ field,
1135
+ show: showConfirmPassword,
1136
+ onToggle: () => setShowConfirmPassword(!showConfirmPassword)
1137
+ }
1138
+ ),
1139
+ /* @__PURE__ */ jsx6(FormMessage3, {})
1140
+ ] })
1141
+ }
1142
+ ),
1143
+ /* @__PURE__ */ jsx6(
1144
+ Button3,
1145
+ {
1146
+ type: "submit",
1147
+ form: "set-password-form",
1148
+ className: "w-full",
1149
+ disabled: isChecking || !account || isLoading || setPasswordMutation.isPending,
1150
+ children: isLoading || setPasswordMutation.isPending ? t("form.submitting") : t("form.submit")
1151
+ }
1152
+ )
1153
+ ]
1154
+ }
1155
+ ) }),
1156
+ errorAlert
1157
+ ]
1158
+ }
1159
+ );
1160
+ };
1161
+
1162
+ // src/components/auth/sign-in.tsx
1163
+ import { zodResolver as zodResolver4 } from "@hookform/resolvers/zod";
1164
+ import {
1165
+ Alert as Alert4,
1166
+ AlertDescription as AlertDescription4,
1167
+ AlertTitle as AlertTitle4,
1168
+ Button as Button4,
1169
+ Form as Form4,
1170
+ FormControl as FormControl4,
1171
+ FormField as FormField4,
1172
+ FormItem as FormItem4,
1173
+ FormLabel as FormLabel4,
1174
+ FormMessage as FormMessage4,
1175
+ Input as Input4,
1176
+ useFormField as useFormField3
1177
+ } from "@mesob/ui/components";
1178
+ import { useMesob as useMesob5 } from "@mesob/ui/providers";
1179
+ import { IconAlertCircle as IconAlertCircle4, IconEye as IconEye3, IconEyeOff as IconEyeOff3 } from "@tabler/icons-react";
1180
+ import { useEffect as useEffect4, useState as useState5 } from "react";
1181
+ import { useForm as useForm4 } from "react-hook-form";
1182
+ import { toast as toast4 } from "sonner";
1183
+ import { z as z4 } from "zod";
1184
+ import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1185
+ var isPhone = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
1186
+ function PasswordInput3({ field, show, onToggle }) {
1187
+ const { formItemId, error } = useFormField3();
1188
+ return /* @__PURE__ */ jsxs5("div", { className: "relative", children: [
1189
+ /* @__PURE__ */ jsx7(
1190
+ Input4,
1191
+ {
1192
+ ...field,
1193
+ id: formItemId,
1194
+ type: show ? "text" : "password",
1195
+ autoComplete: "current-password",
1196
+ "aria-invalid": !!error,
1197
+ className: "pr-10"
1198
+ }
1199
+ ),
1200
+ /* @__PURE__ */ jsx7(
1201
+ Button4,
1202
+ {
1203
+ type: "button",
1204
+ variant: "ghost",
1205
+ size: "icon",
1206
+ className: "absolute right-0 top-0 h-full px-3 text-muted-foreground hover:text-foreground",
1207
+ onClick: onToggle,
1208
+ "aria-label": show ? "Hide password" : "Show password",
1209
+ children: show ? /* @__PURE__ */ jsx7(IconEyeOff3, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx7(IconEye3, { className: "h-4 w-4" })
1210
+ }
1211
+ )
1212
+ ] });
1213
+ }
1214
+ var signInSchema = (t, phoneRegex) => z4.object({
1215
+ username: z4.string().trim().min(1, { message: t("errors.requiredField") }).refine(
947
1216
  (val) => {
948
- const isEmail = z3.email().safeParse(val).success;
1217
+ const isEmail = z4.email().safeParse(val).success;
949
1218
  const isPhone3 = phoneRegex.test(val);
950
1219
  return isEmail || isPhone3;
951
1220
  },
952
1221
  { message: t("errors.invalidEmailOrPhone") }
953
1222
  ),
954
- password: z3.union([
955
- z3.literal(""),
956
- z3.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError"))
1223
+ password: z4.union([
1224
+ z4.literal(""),
1225
+ z4.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError"))
957
1226
  ]).optional()
958
1227
  });
959
1228
  var SignIn = ({ redirectUrl } = {}) => {
960
1229
  const { hooks, setAuth } = useApi();
961
1230
  const { config } = useConfig();
962
- const mesob = useMesob4();
1231
+ const mesob = useMesob5();
963
1232
  const t = useTranslator("Auth.signIn");
964
1233
  const Link = mesob?.navigation?.Link;
965
- const [isLoading, setIsLoading] = useState4(false);
966
- const [error, setError] = useState4(null);
967
- const [showPasswordField, setShowPasswordField] = useState4(false);
968
- const [showPassword, setShowPassword] = useState4(false);
969
- const [username, setUsername] = useState4("");
970
- const [isChecking, setIsChecking] = useState4(false);
1234
+ const [isLoading, setIsLoading] = useState5(false);
1235
+ const [error, setError] = useState5(null);
1236
+ const [showPasswordField, setShowPasswordField] = useState5(false);
1237
+ const [showPassword, setShowPassword] = useState5(false);
1238
+ const [username, setUsername] = useState5("");
1239
+ const [isChecking, setIsChecking] = useState5(false);
971
1240
  const checkUserMutation = hooks.useMutation("post", "/check-account");
972
1241
  const signInMutation = hooks.useMutation("post", "/sign-in");
973
1242
  const phoneRegex = typeof config.phoneRegex === "string" ? new RegExp(config.phoneRegex) : config.phoneRegex || /^(\+2519|\+2517|2519|2517|09|07)\d{8}$/;
974
1243
  const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/dashboard";
975
1244
  const forgotPasswordLink = config.navigation?.links?.forgotPassword || "/auth/forgot-password";
976
1245
  const signUpLink = config.navigation?.links?.signUp || "/auth/sign-up";
1246
+ const setPasswordLink = config.navigation?.links?.setPassword || "/auth/set-password";
977
1247
  const onNavigate = config.navigation?.onNavigate || ((path) => {
978
1248
  if (typeof window !== "undefined") {
979
1249
  window.location.href = path;
980
1250
  }
981
1251
  });
982
1252
  const logoImage = config.ui.logoImage;
983
- const form = useForm3({
984
- resolver: zodResolver3(signInSchema(t, phoneRegex)),
1253
+ const form = useForm4({
1254
+ resolver: zodResolver4(signInSchema(t, phoneRegex)),
985
1255
  defaultValues: { username: "", password: "" },
986
- mode: "onChange"
1256
+ mode: "onBlur"
987
1257
  });
988
- useEffect3(() => {
1258
+ useEffect4(() => {
989
1259
  if (error) {
990
- toast3.error(error.title || "Error", {
1260
+ toast4.error(error.title || "Error", {
991
1261
  description: error.description
992
1262
  });
993
1263
  }
@@ -1002,16 +1272,26 @@ var SignIn = ({ redirectUrl } = {}) => {
1002
1272
  }
1003
1273
  });
1004
1274
  if (result.exists) {
1275
+ if (result.requiresPasswordSetup) {
1276
+ const redirectParam = defaultRedirect ? `&redirect=${encodeURIComponent(defaultRedirect)}` : "";
1277
+ onNavigate(
1278
+ `${setPasswordLink}?identifier=${encodeURIComponent(normalizedUsername)}${redirectParam}`
1279
+ );
1280
+ return;
1281
+ }
1005
1282
  setUsername(normalizedUsername);
1006
1283
  form.setValue("username", normalizedUsername);
1007
1284
  setShowPasswordField(true);
1008
1285
  } else {
1009
1286
  const email = isPhone(normalizedUsername) ? "" : normalizedUsername;
1287
+ const redirectParam = defaultRedirect ? `&redirect=${encodeURIComponent(defaultRedirect)}` : "";
1010
1288
  if (email) {
1011
- onNavigate(`${signUpLink}?email=${encodeURIComponent(email)}`);
1289
+ onNavigate(
1290
+ `${signUpLink}?email=${encodeURIComponent(email)}${redirectParam}`
1291
+ );
1012
1292
  } else {
1013
1293
  onNavigate(
1014
- `${signUpLink}?phone=${encodeURIComponent(normalizedUsername)}`
1294
+ `${signUpLink}?phone=${encodeURIComponent(normalizedUsername)}${redirectParam}`
1015
1295
  );
1016
1296
  }
1017
1297
  }
@@ -1044,7 +1324,8 @@ var SignIn = ({ redirectUrl } = {}) => {
1044
1324
  }
1045
1325
  });
1046
1326
  if ("verificationId" in res && res.verificationId) {
1047
- const verifyPath = isPhone(username) ? `/auth/verify-phone?context=sign-in&verificationId=${res.verificationId}&identifier=${encodeURIComponent(username)}` : `/auth/verify-email?verificationId=${res.verificationId}`;
1327
+ const redirectParam = defaultRedirect ? `&redirect=${encodeURIComponent(defaultRedirect)}` : "";
1328
+ const verifyPath = isPhone(username) ? `/auth/verify-phone?context=sign-in&verificationId=${res.verificationId}&identifier=${encodeURIComponent(username)}${redirectParam}` : `/auth/verify-email?verificationId=${res.verificationId}${redirectParam}`;
1048
1329
  onNavigate(verifyPath);
1049
1330
  return;
1050
1331
  }
@@ -1053,6 +1334,15 @@ var SignIn = ({ redirectUrl } = {}) => {
1053
1334
  }
1054
1335
  onNavigate(defaultRedirect);
1055
1336
  } catch (err) {
1337
+ const authError = err;
1338
+ const errorCode = authError.code || authError.message;
1339
+ if (errorCode === "HAS_NO_PASSWORD") {
1340
+ const redirectParam = defaultRedirect ? `&redirect=${encodeURIComponent(defaultRedirect)}` : "";
1341
+ onNavigate(
1342
+ `${setPasswordLink}?identifier=${encodeURIComponent(username)}${redirectParam}`
1343
+ );
1344
+ return;
1345
+ }
1056
1346
  handleError(err, setError, t);
1057
1347
  } finally {
1058
1348
  setIsLoading(false);
@@ -1078,19 +1368,19 @@ var SignIn = ({ redirectUrl } = {}) => {
1078
1368
  errorContent = error;
1079
1369
  }
1080
1370
  }
1081
- const formContent = /* @__PURE__ */ jsx6(Form3, { ...form, children: /* @__PURE__ */ jsxs4(
1371
+ const formContent = /* @__PURE__ */ jsx7(Form4, { ...form, children: /* @__PURE__ */ jsxs5(
1082
1372
  "form",
1083
1373
  {
1084
1374
  id: "sign-in-form",
1085
1375
  onSubmit: form.handleSubmit(onSubmit),
1086
1376
  className: "space-y-4",
1087
1377
  children: [
1088
- showPasswordField ? /* @__PURE__ */ jsxs4(Fragment, { children: [
1089
- /* @__PURE__ */ jsxs4(FormItem3, { children: [
1090
- /* @__PURE__ */ jsxs4(FormLabel3, { className: "flex justify-between items-center", children: [
1378
+ showPasswordField ? /* @__PURE__ */ jsxs5(Fragment, { children: [
1379
+ /* @__PURE__ */ jsxs5(FormItem4, { children: [
1380
+ /* @__PURE__ */ jsxs5(FormLabel4, { className: "flex justify-between items-center", children: [
1091
1381
  t("form.accountLabel"),
1092
- /* @__PURE__ */ jsx6(
1093
- Button3,
1382
+ /* @__PURE__ */ jsx7(
1383
+ Button4,
1094
1384
  {
1095
1385
  type: "button",
1096
1386
  variant: "link",
@@ -1101,58 +1391,50 @@ var SignIn = ({ redirectUrl } = {}) => {
1101
1391
  }
1102
1392
  )
1103
1393
  ] }),
1104
- /* @__PURE__ */ jsx6(
1105
- Input3,
1394
+ /* @__PURE__ */ jsx7(
1395
+ Input4,
1106
1396
  {
1107
1397
  id: "sign-in-username",
1108
1398
  type: "text",
1109
1399
  value: username,
1400
+ autoComplete: "username",
1110
1401
  disabled: true
1111
1402
  }
1112
1403
  )
1113
1404
  ] }),
1114
- /* @__PURE__ */ jsx6(
1115
- FormField3,
1405
+ /* @__PURE__ */ jsx7(
1406
+ FormField4,
1116
1407
  {
1117
1408
  control: form.control,
1118
1409
  name: "password",
1119
- render: ({ field }) => /* @__PURE__ */ jsxs4(FormItem3, { children: [
1120
- /* @__PURE__ */ jsx6(FormLabel3, { children: t("form.passwordLabel") }),
1121
- /* @__PURE__ */ jsx6(
1122
- PasswordInput2,
1410
+ render: ({ field }) => /* @__PURE__ */ jsxs5(FormItem4, { children: [
1411
+ /* @__PURE__ */ jsx7(FormLabel4, { children: t("form.passwordLabel") }),
1412
+ /* @__PURE__ */ jsx7(
1413
+ PasswordInput3,
1123
1414
  {
1124
1415
  field: { ...field, value: field.value ?? "" },
1125
1416
  show: showPassword,
1126
- onToggle: () => setShowPassword(!showPassword),
1127
- placeholder: t("form.passwordPlaceholder")
1417
+ onToggle: () => setShowPassword(!showPassword)
1128
1418
  }
1129
1419
  ),
1130
- /* @__PURE__ */ jsx6(FormMessage3, {})
1420
+ /* @__PURE__ */ jsx7(FormMessage4, {})
1131
1421
  ] })
1132
1422
  }
1133
1423
  )
1134
- ] }) : /* @__PURE__ */ jsx6(
1135
- FormField3,
1424
+ ] }) : /* @__PURE__ */ jsx7(
1425
+ FormField4,
1136
1426
  {
1137
1427
  control: form.control,
1138
1428
  name: "username",
1139
- render: ({ field }) => /* @__PURE__ */ jsxs4(FormItem3, { children: [
1140
- /* @__PURE__ */ jsx6(FormLabel3, { children: t("form.accountLabel") }),
1141
- /* @__PURE__ */ jsx6(FormControl3, { children: /* @__PURE__ */ jsx6(
1142
- Input3,
1143
- {
1144
- ...field,
1145
- type: "text",
1146
- placeholder: t("form.accountPlaceholder"),
1147
- autoComplete: "username"
1148
- }
1149
- ) }),
1150
- /* @__PURE__ */ jsx6(FormMessage3, {})
1429
+ render: ({ field }) => /* @__PURE__ */ jsxs5(FormItem4, { children: [
1430
+ /* @__PURE__ */ jsx7(FormLabel4, { children: t("form.accountLabel") }),
1431
+ /* @__PURE__ */ jsx7(FormControl4, { children: /* @__PURE__ */ jsx7(Input4, { ...field, type: "text", autoComplete: "username" }) }),
1432
+ /* @__PURE__ */ jsx7(FormMessage4, {})
1151
1433
  ] })
1152
1434
  }
1153
1435
  ),
1154
- /* @__PURE__ */ jsx6(
1155
- Button3,
1436
+ /* @__PURE__ */ jsx7(
1437
+ Button4,
1156
1438
  {
1157
1439
  type: "submit",
1158
1440
  className: "w-full",
@@ -1164,20 +1446,20 @@ var SignIn = ({ redirectUrl } = {}) => {
1164
1446
  ]
1165
1447
  }
1166
1448
  ) });
1167
- return /* @__PURE__ */ jsx6("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs4(
1449
+ return /* @__PURE__ */ jsx7("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs5(
1168
1450
  AuthLayout,
1169
1451
  {
1170
- title: t("title"),
1452
+ title: config.ui.name,
1171
1453
  description: t("description"),
1172
1454
  logoImage,
1173
- footer: showPasswordField ? /* @__PURE__ */ jsx6("div", { className: "flex items-center justify-center w-full", children: Link ? /* @__PURE__ */ jsx6(
1455
+ footer: showPasswordField ? /* @__PURE__ */ jsx7("div", { className: "flex items-center justify-center w-full", children: Link ? /* @__PURE__ */ jsx7(
1174
1456
  Link,
1175
1457
  {
1176
1458
  href: forgotPasswordLink,
1177
1459
  className: "text-primary inline-block hover:underline",
1178
1460
  children: t("footer.forgotPassword")
1179
1461
  }
1180
- ) : /* @__PURE__ */ jsx6(
1462
+ ) : /* @__PURE__ */ jsx7(
1181
1463
  "a",
1182
1464
  {
1183
1465
  href: forgotPasswordLink,
@@ -1191,10 +1473,10 @@ var SignIn = ({ redirectUrl } = {}) => {
1191
1473
  ) }) : void 0,
1192
1474
  children: [
1193
1475
  formContent,
1194
- errorContent && /* @__PURE__ */ jsxs4(Alert3, { variant: "destructive", className: "mt-4", children: [
1195
- /* @__PURE__ */ jsx6(IconAlertCircle3, { className: "h-4 w-4" }),
1196
- /* @__PURE__ */ jsx6(AlertTitle3, { children: errorContent.title }),
1197
- /* @__PURE__ */ jsx6(AlertDescription3, { children: errorContent.description })
1476
+ errorContent && /* @__PURE__ */ jsxs5(Alert4, { variant: "destructive", className: "mt-4", children: [
1477
+ /* @__PURE__ */ jsx7(IconAlertCircle4, { className: "h-4 w-4" }),
1478
+ /* @__PURE__ */ jsx7(AlertTitle4, { children: errorContent.title }),
1479
+ /* @__PURE__ */ jsx7(AlertDescription4, { children: errorContent.description })
1198
1480
  ] })
1199
1481
  ]
1200
1482
  }
@@ -1202,50 +1484,44 @@ var SignIn = ({ redirectUrl } = {}) => {
1202
1484
  };
1203
1485
 
1204
1486
  // src/components/auth/sign-up.tsx
1205
- import { zodResolver as zodResolver4 } from "@hookform/resolvers/zod";
1487
+ import { zodResolver as zodResolver5 } from "@hookform/resolvers/zod";
1206
1488
  import {
1207
- Alert as Alert4,
1208
- AlertDescription as AlertDescription4,
1209
- AlertTitle as AlertTitle4,
1210
- Button as Button4,
1211
- Form as Form4,
1212
- FormControl as FormControl4,
1213
- FormField as FormField4,
1214
- FormItem as FormItem4,
1215
- FormLabel as FormLabel4,
1216
- FormMessage as FormMessage4,
1217
- Input as Input4,
1218
- useFormField as useFormField3
1489
+ Alert as Alert5,
1490
+ AlertDescription as AlertDescription5,
1491
+ AlertTitle as AlertTitle5,
1492
+ Button as Button5,
1493
+ Form as Form5,
1494
+ FormControl as FormControl5,
1495
+ FormField as FormField5,
1496
+ FormItem as FormItem5,
1497
+ FormLabel as FormLabel5,
1498
+ FormMessage as FormMessage5,
1499
+ Input as Input5,
1500
+ useFormField as useFormField4
1219
1501
  } from "@mesob/ui/components";
1220
- import { useMesob as useMesob5 } from "@mesob/ui/providers";
1221
- import { IconAlertCircle as IconAlertCircle4, IconEye as IconEye3, IconEyeOff as IconEyeOff3 } from "@tabler/icons-react";
1222
- import { useEffect as useEffect4, useState as useState5 } from "react";
1223
- import { useForm as useForm4 } from "react-hook-form";
1224
- import { toast as toast4 } from "sonner";
1225
- import { z as z4 } from "zod";
1226
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1502
+ import { useMesob as useMesob6 } from "@mesob/ui/providers";
1503
+ import { IconAlertCircle as IconAlertCircle5, IconEye as IconEye4, IconEyeOff as IconEyeOff4 } from "@tabler/icons-react";
1504
+ import { useEffect as useEffect5, useState as useState6 } from "react";
1505
+ import { useForm as useForm5 } from "react-hook-form";
1506
+ import { toast as toast5 } from "sonner";
1507
+ import { z as z5 } from "zod";
1508
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1227
1509
  var isPhone2 = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
1228
- function PasswordInput3({
1229
- field,
1230
- show,
1231
- onToggle,
1232
- placeholder
1233
- }) {
1234
- const { formItemId, error } = useFormField3();
1235
- return /* @__PURE__ */ jsxs5("div", { className: "relative", children: [
1236
- /* @__PURE__ */ jsx7(
1237
- Input4,
1510
+ function PasswordInput4({ field, show, onToggle }) {
1511
+ const { formItemId, error } = useFormField4();
1512
+ return /* @__PURE__ */ jsxs6("div", { className: "relative", children: [
1513
+ /* @__PURE__ */ jsx8(
1514
+ Input5,
1238
1515
  {
1239
1516
  ...field,
1240
1517
  id: formItemId,
1241
1518
  type: show ? "text" : "password",
1242
- placeholder,
1243
1519
  "aria-invalid": !!error,
1244
1520
  className: "pr-10"
1245
1521
  }
1246
1522
  ),
1247
- /* @__PURE__ */ jsx7(
1248
- Button4,
1523
+ /* @__PURE__ */ jsx8(
1524
+ Button5,
1249
1525
  {
1250
1526
  type: "button",
1251
1527
  variant: "ghost",
@@ -1253,14 +1529,14 @@ function PasswordInput3({
1253
1529
  className: "absolute right-0 top-0 h-full px-3 text-muted-foreground hover:text-foreground",
1254
1530
  onClick: onToggle,
1255
1531
  "aria-label": show ? "Hide password" : "Show password",
1256
- children: show ? /* @__PURE__ */ jsx7(IconEyeOff3, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx7(IconEye3, { className: "h-4 w-4" })
1532
+ children: show ? /* @__PURE__ */ jsx8(IconEyeOff4, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx8(IconEye4, { className: "h-4 w-4" })
1257
1533
  }
1258
1534
  )
1259
1535
  ] });
1260
1536
  }
1261
- var signUpSchema = (t) => z4.object({
1262
- fullName: z4.string().min(1, t("errors.fullNameRequired")),
1263
- identifier: z4.string().min(1, t("errors.contactRequired")).refine(
1537
+ var signUpSchema = (t) => z5.object({
1538
+ fullName: z5.string().min(1, t("errors.fullNameRequired")),
1539
+ identifier: z5.string().min(1, t("errors.contactRequired")).refine(
1264
1540
  (val) => {
1265
1541
  if (!val) {
1266
1542
  return false;
@@ -1271,8 +1547,8 @@ var signUpSchema = (t) => z4.object({
1271
1547
  message: t("errors.invalidEmailOrPhone")
1272
1548
  }
1273
1549
  ),
1274
- password: z4.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError")),
1275
- confirmPassword: z4.string()
1550
+ password: z5.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError")),
1551
+ confirmPassword: z5.string()
1276
1552
  }).refine((data) => data.password === data.confirmPassword, {
1277
1553
  message: t("errors.passwordsMismatch"),
1278
1554
  path: ["confirmPassword"]
@@ -1283,13 +1559,13 @@ var SignUp = ({
1283
1559
  } = {}) => {
1284
1560
  const { hooks, setAuth } = useApi();
1285
1561
  const { config } = useConfig();
1286
- const mesob = useMesob5();
1562
+ const mesob = useMesob6();
1287
1563
  const t = useTranslator("Auth.signUp");
1288
1564
  const Link = mesob?.navigation?.Link;
1289
- const [isLoading, setIsLoading] = useState5(false);
1290
- const [error, setError] = useState5(null);
1291
- const [showPassword, setShowPassword] = useState5(false);
1292
- const [showConfirmPassword, setShowConfirmPassword] = useState5(false);
1565
+ const [isLoading, setIsLoading] = useState6(false);
1566
+ const [error, setError] = useState6(null);
1567
+ const [showPassword, setShowPassword] = useState6(false);
1568
+ const [showConfirmPassword, setShowConfirmPassword] = useState6(false);
1293
1569
  const signUpMutation = hooks.useMutation("post", "/sign-up");
1294
1570
  const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
1295
1571
  const onNavigate = config.navigation?.onNavigate || ((path) => {
@@ -1300,8 +1576,8 @@ var SignUp = ({
1300
1576
  const logoImage = config.ui.logoImage;
1301
1577
  const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
1302
1578
  const hasInitialIdentifier = !!initialIdentifier;
1303
- const form = useForm4({
1304
- resolver: zodResolver4(signUpSchema(t)),
1579
+ const form = useForm5({
1580
+ resolver: zodResolver5(signUpSchema(t)),
1305
1581
  defaultValues: {
1306
1582
  fullName: "",
1307
1583
  identifier: initialIdentifier || "",
@@ -1309,14 +1585,14 @@ var SignUp = ({
1309
1585
  confirmPassword: ""
1310
1586
  }
1311
1587
  });
1312
- useEffect4(() => {
1588
+ useEffect5(() => {
1313
1589
  if (initialIdentifier) {
1314
1590
  form.setValue("identifier", initialIdentifier);
1315
1591
  }
1316
1592
  }, [initialIdentifier, form]);
1317
- useEffect4(() => {
1593
+ useEffect5(() => {
1318
1594
  if (error) {
1319
- toast4.error(error.title || "Error", {
1595
+ toast5.error(error.title || "Error", {
1320
1596
  description: error.description
1321
1597
  });
1322
1598
  }
@@ -1331,23 +1607,22 @@ var SignUp = ({
1331
1607
  body: usingPhone ? {
1332
1608
  phone: identifier,
1333
1609
  password: values.password,
1334
- fullName: values.fullName,
1335
- handle: values.handle
1610
+ fullName: values.fullName
1336
1611
  } : {
1337
1612
  email: identifier,
1338
1613
  password: values.password,
1339
- fullName: values.fullName,
1340
- handle: values.handle
1614
+ fullName: values.fullName
1341
1615
  }
1342
1616
  });
1343
1617
  if ("verificationId" in res && res.verificationId) {
1618
+ const redirectParam = defaultRedirect ? `&redirect=${encodeURIComponent(defaultRedirect)}` : "";
1344
1619
  if (usingPhone) {
1345
1620
  onNavigate(
1346
- `/auth/verify-phone?context=sign-up&verificationId=${res.verificationId}&phone=${encodeURIComponent(identifier)}`
1621
+ `/auth/verify-phone?context=sign-up&verificationId=${res.verificationId}&phone=${encodeURIComponent(identifier)}${redirectParam}`
1347
1622
  );
1348
1623
  } else {
1349
1624
  onNavigate(
1350
- `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(identifier)}`
1625
+ `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(identifier)}${redirectParam}`
1351
1626
  );
1352
1627
  }
1353
1628
  return;
@@ -1380,16 +1655,16 @@ var SignUp = ({
1380
1655
  errorContent = error;
1381
1656
  }
1382
1657
  }
1383
- return /* @__PURE__ */ jsxs5(
1658
+ return /* @__PURE__ */ jsxs6(
1384
1659
  AuthLayout,
1385
1660
  {
1386
- title: t("title"),
1661
+ title: config.ui.name,
1387
1662
  description: t("description"),
1388
1663
  logoImage,
1389
- footer: /* @__PURE__ */ jsxs5("p", { children: [
1664
+ footer: /* @__PURE__ */ jsxs6("p", { children: [
1390
1665
  t("footer.hasAccount"),
1391
1666
  " ",
1392
- Link ? /* @__PURE__ */ jsx7(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.signInCta") }) : /* @__PURE__ */ jsx7(
1667
+ Link ? /* @__PURE__ */ jsx8(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.signInCta") }) : /* @__PURE__ */ jsx8(
1393
1668
  "a",
1394
1669
  {
1395
1670
  href: signInLink,
@@ -1403,93 +1678,84 @@ var SignUp = ({
1403
1678
  )
1404
1679
  ] }),
1405
1680
  children: [
1406
- /* @__PURE__ */ jsx7(Form4, { ...form, children: /* @__PURE__ */ jsxs5("form", { id: "sign-up-form", onSubmit: handleSubmit, className: "space-y-4", children: [
1407
- /* @__PURE__ */ jsx7(
1408
- FormField4,
1681
+ /* @__PURE__ */ jsx8(Form5, { ...form, children: /* @__PURE__ */ jsxs6("form", { id: "sign-up-form", onSubmit: handleSubmit, className: "space-y-4", children: [
1682
+ /* @__PURE__ */ jsx8(
1683
+ FormField5,
1409
1684
  {
1410
1685
  control: form.control,
1411
1686
  name: "fullName",
1412
- render: ({ field }) => /* @__PURE__ */ jsxs5(FormItem4, { children: [
1413
- /* @__PURE__ */ jsx7(FormLabel4, { children: t("form.fullNameLabel") }),
1414
- /* @__PURE__ */ jsx7(FormControl4, { children: /* @__PURE__ */ jsx7(
1415
- Input4,
1416
- {
1417
- ...field,
1418
- placeholder: t("form.fullNamePlaceholder")
1419
- }
1420
- ) }),
1421
- /* @__PURE__ */ jsx7(FormMessage4, {})
1687
+ render: ({ field }) => /* @__PURE__ */ jsxs6(FormItem5, { children: [
1688
+ /* @__PURE__ */ jsx8(FormLabel5, { children: t("form.fullNameLabel") }),
1689
+ /* @__PURE__ */ jsx8(FormControl5, { children: /* @__PURE__ */ jsx8(Input5, { ...field }) }),
1690
+ /* @__PURE__ */ jsx8(FormMessage5, {})
1422
1691
  ] })
1423
1692
  }
1424
1693
  ),
1425
- /* @__PURE__ */ jsx7(
1426
- FormField4,
1694
+ /* @__PURE__ */ jsx8(
1695
+ FormField5,
1427
1696
  {
1428
1697
  control: form.control,
1429
1698
  name: "identifier",
1430
- render: ({ field }) => /* @__PURE__ */ jsxs5(FormItem4, { children: [
1431
- /* @__PURE__ */ jsx7(
1432
- FormLabel4,
1699
+ render: ({ field }) => /* @__PURE__ */ jsxs6(FormItem5, { children: [
1700
+ /* @__PURE__ */ jsx8(
1701
+ FormLabel5,
1433
1702
  {
1434
1703
  className: hasInitialIdentifier ? "block" : void 0,
1435
1704
  children: identifierLabel
1436
1705
  }
1437
1706
  ),
1438
- /* @__PURE__ */ jsx7(FormControl4, { children: /* @__PURE__ */ jsx7(
1439
- Input4,
1707
+ /* @__PURE__ */ jsx8(FormControl5, { children: /* @__PURE__ */ jsx8(
1708
+ Input5,
1440
1709
  {
1441
1710
  ...field,
1442
1711
  type: field.value.includes("@") ? "email" : "tel",
1443
- placeholder: hasInitialIdentifier ? void 0 : t("form.accountPlaceholder") || "Email or phone number",
1444
1712
  disabled: hasInitialIdentifier
1445
1713
  }
1446
1714
  ) }),
1447
- /* @__PURE__ */ jsx7(FormMessage4, {})
1715
+ /* @__PURE__ */ jsx8(FormMessage5, {})
1448
1716
  ] })
1449
1717
  }
1450
1718
  ),
1451
- /* @__PURE__ */ jsx7(
1452
- FormField4,
1719
+ /* @__PURE__ */ jsx8(
1720
+ FormField5,
1453
1721
  {
1454
1722
  control: form.control,
1455
1723
  name: "password",
1456
- render: ({ field }) => /* @__PURE__ */ jsxs5(FormItem4, { children: [
1457
- /* @__PURE__ */ jsx7(FormLabel4, { children: t("form.passwordLabel") }),
1458
- /* @__PURE__ */ jsx7(
1459
- PasswordInput3,
1724
+ render: ({ field }) => /* @__PURE__ */ jsxs6(FormItem5, { children: [
1725
+ /* @__PURE__ */ jsx8(FormLabel5, { children: t("form.passwordLabel") }),
1726
+ /* @__PURE__ */ jsx8(
1727
+ PasswordInput4,
1460
1728
  {
1461
1729
  field,
1462
1730
  show: showPassword,
1463
- onToggle: () => setShowPassword(!showPassword),
1464
- placeholder: t("form.passwordPlaceholder")
1731
+ onToggle: () => setShowPassword(!showPassword)
1465
1732
  }
1466
1733
  ),
1467
- /* @__PURE__ */ jsx7(FormMessage4, {})
1734
+ /* @__PURE__ */ jsx8(FormMessage5, {})
1468
1735
  ] })
1469
1736
  }
1470
1737
  ),
1471
- /* @__PURE__ */ jsx7(
1472
- FormField4,
1738
+ /* @__PURE__ */ jsx8(
1739
+ FormField5,
1473
1740
  {
1474
1741
  control: form.control,
1475
1742
  name: "confirmPassword",
1476
- render: ({ field }) => /* @__PURE__ */ jsxs5(FormItem4, { children: [
1477
- /* @__PURE__ */ jsx7(FormLabel4, { children: t("form.confirmPasswordLabel") }),
1478
- /* @__PURE__ */ jsx7(
1479
- PasswordInput3,
1743
+ render: ({ field }) => /* @__PURE__ */ jsxs6(FormItem5, { children: [
1744
+ /* @__PURE__ */ jsx8(FormLabel5, { children: t("form.confirmPasswordLabel") }),
1745
+ /* @__PURE__ */ jsx8(
1746
+ PasswordInput4,
1480
1747
  {
1481
1748
  field,
1482
1749
  show: showConfirmPassword,
1483
- onToggle: () => setShowConfirmPassword(!showConfirmPassword),
1484
- placeholder: t("form.passwordPlaceholder")
1750
+ onToggle: () => setShowConfirmPassword(!showConfirmPassword)
1485
1751
  }
1486
1752
  ),
1487
- /* @__PURE__ */ jsx7(FormMessage4, {})
1753
+ /* @__PURE__ */ jsx8(FormMessage5, {})
1488
1754
  ] })
1489
1755
  }
1490
1756
  ),
1491
- /* @__PURE__ */ jsx7(
1492
- Button4,
1757
+ /* @__PURE__ */ jsx8(
1758
+ Button5,
1493
1759
  {
1494
1760
  type: "submit",
1495
1761
  form: "sign-up-form",
@@ -1499,10 +1765,10 @@ var SignUp = ({
1499
1765
  }
1500
1766
  )
1501
1767
  ] }) }),
1502
- errorContent && /* @__PURE__ */ jsxs5(Alert4, { variant: "destructive", className: "mt-4", children: [
1503
- /* @__PURE__ */ jsx7(IconAlertCircle4, { className: "h-4 w-4" }),
1504
- /* @__PURE__ */ jsx7(AlertTitle4, { children: errorContent.title }),
1505
- /* @__PURE__ */ jsx7(AlertDescription4, { children: errorContent.description })
1768
+ errorContent && /* @__PURE__ */ jsxs6(Alert5, { variant: "destructive", className: "mt-4", children: [
1769
+ /* @__PURE__ */ jsx8(IconAlertCircle5, { className: "h-4 w-4" }),
1770
+ /* @__PURE__ */ jsx8(AlertTitle5, { children: errorContent.title }),
1771
+ /* @__PURE__ */ jsx8(AlertDescription5, { children: errorContent.description })
1506
1772
  ] })
1507
1773
  ]
1508
1774
  }
@@ -1510,36 +1776,35 @@ var SignUp = ({
1510
1776
  };
1511
1777
 
1512
1778
  // src/components/auth/verification-form.tsx
1513
- import { zodResolver as zodResolver5 } from "@hookform/resolvers/zod";
1779
+ import { zodResolver as zodResolver6 } from "@hookform/resolvers/zod";
1514
1780
  import {
1515
1781
  Button as Button6,
1516
- Form as Form5,
1517
- FormControl as FormControl5,
1518
- FormField as FormField5,
1519
- FormItem as FormItem5,
1520
- FormLabel as FormLabel5,
1521
- FormMessage as FormMessage5,
1782
+ Form as Form6,
1783
+ FormControl as FormControl6,
1784
+ FormField as FormField6,
1785
+ FormItem as FormItem6,
1786
+ FormLabel as FormLabel6,
1787
+ FormMessage as FormMessage6,
1522
1788
  InputOTP as InputOTP2,
1523
1789
  InputOTPGroup as InputOTPGroup2,
1524
- InputOTPSlot as InputOTPSlot2,
1525
- Spinner as Spinner4
1790
+ InputOTPSlot as InputOTPSlot2
1526
1791
  } from "@mesob/ui/components";
1527
- import { useForm as useForm5 } from "react-hook-form";
1528
- import { z as z5 } from "zod";
1792
+ import { useForm as useForm6 } from "react-hook-form";
1793
+ import { z as z6 } from "zod";
1529
1794
 
1530
1795
  // src/components/auth/countdown.tsx
1531
- import { Button as Button5, Spinner as Spinner3 } from "@mesob/ui/components";
1532
- import { useEffect as useEffect5, useState as useState6 } from "react";
1533
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1796
+ import { Spinner } from "@mesob/ui/components";
1797
+ import { useEffect as useEffect6, useState as useState7 } from "react";
1798
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1534
1799
  var Countdown = ({
1535
1800
  initialSeconds = 60,
1536
1801
  onResend,
1537
1802
  resending = false
1538
1803
  }) => {
1539
1804
  const t = useTranslator("Common");
1540
- const [seconds, setSeconds] = useState6(initialSeconds);
1541
- const [isResending, setIsResending] = useState6(false);
1542
- useEffect5(() => {
1805
+ const [seconds, setSeconds] = useState7(initialSeconds);
1806
+ const [isResending, setIsResending] = useState7(false);
1807
+ useEffect6(() => {
1543
1808
  if (seconds <= 0) {
1544
1809
  return;
1545
1810
  }
@@ -1564,17 +1829,19 @@ var Countdown = ({
1564
1829
  setIsResending(false);
1565
1830
  }
1566
1831
  };
1832
+ const busy = isResending || resending;
1567
1833
  if (seconds > 0) {
1568
- return /* @__PURE__ */ jsx8(Button5, { variant: "ghost", disabled: true, children: t("resendIn", { seconds }) });
1834
+ return /* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground", children: t("resendIn", { seconds }) });
1569
1835
  }
1570
- return /* @__PURE__ */ jsxs6(
1571
- Button5,
1836
+ return /* @__PURE__ */ jsxs7(
1837
+ "button",
1572
1838
  {
1573
- variant: "ghost",
1839
+ type: "button",
1574
1840
  onClick: handleResend,
1575
- disabled: isResending || resending,
1841
+ disabled: busy,
1842
+ className: "text-sm text-primary hover:underline disabled:opacity-50 flex items-center gap-1",
1576
1843
  children: [
1577
- isResending || resending && /* @__PURE__ */ jsx8(Spinner3, {}),
1844
+ busy && /* @__PURE__ */ jsx9(Spinner, { className: "h-3 w-3" }),
1578
1845
  t("resend")
1579
1846
  ]
1580
1847
  }
@@ -1582,9 +1849,9 @@ var Countdown = ({
1582
1849
  };
1583
1850
 
1584
1851
  // src/components/auth/verification-form.tsx
1585
- import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1586
- var verificationSchema = (t) => z5.object({
1587
- code: z5.string().length(6, t("form.codeLength"))
1852
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1853
+ var verificationSchema = (t) => z6.object({
1854
+ code: z6.string().length(6, t("form.codeLength"))
1588
1855
  });
1589
1856
  var VerificationForm = ({
1590
1857
  onSubmit,
@@ -1592,30 +1859,29 @@ var VerificationForm = ({
1592
1859
  isLoading = false
1593
1860
  }) => {
1594
1861
  const t = useTranslator("Auth.verification");
1595
- const form = useForm5({
1596
- resolver: zodResolver5(verificationSchema(t)),
1597
- defaultValues: {
1598
- code: ""
1599
- }
1862
+ const form = useForm6({
1863
+ resolver: zodResolver6(verificationSchema(t)),
1864
+ defaultValues: { code: "" }
1600
1865
  });
1601
1866
  const handleSubmit = form.handleSubmit(async (values) => {
1602
1867
  await onSubmit(values);
1603
1868
  });
1604
- return /* @__PURE__ */ jsx9(Form5, { ...form, children: /* @__PURE__ */ jsxs7(
1869
+ const codeLength = form.watch("code").length;
1870
+ return /* @__PURE__ */ jsx10(Form6, { ...form, children: /* @__PURE__ */ jsxs8(
1605
1871
  "form",
1606
1872
  {
1607
1873
  id: "verification-form",
1608
1874
  onSubmit: handleSubmit,
1609
1875
  className: "space-y-4",
1610
1876
  children: [
1611
- /* @__PURE__ */ jsx9(
1612
- FormField5,
1877
+ /* @__PURE__ */ jsx10(
1878
+ FormField6,
1613
1879
  {
1614
1880
  control: form.control,
1615
1881
  name: "code",
1616
- render: ({ field }) => /* @__PURE__ */ jsxs7(FormItem5, { children: [
1617
- /* @__PURE__ */ jsx9("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx9(FormLabel5, { children: t("form.codeLabel") }) }),
1618
- /* @__PURE__ */ jsx9(FormControl5, { children: /* @__PURE__ */ jsx9(
1882
+ render: ({ field }) => /* @__PURE__ */ jsxs8(FormItem6, { children: [
1883
+ /* @__PURE__ */ jsx10("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx10(FormLabel6, { children: t("form.codeLabel") }) }),
1884
+ /* @__PURE__ */ jsx10(FormControl6, { children: /* @__PURE__ */ jsx10(
1619
1885
  InputOTP2,
1620
1886
  {
1621
1887
  maxLength: 6,
@@ -1624,47 +1890,44 @@ var VerificationForm = ({
1624
1890
  onChange: field.onChange,
1625
1891
  onBlur: field.onBlur,
1626
1892
  containerClassName: "gap-4 justify-center mb-2 flex items-center",
1627
- 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: [
1628
- /* @__PURE__ */ jsx9(InputOTPSlot2, { className: "h-12", index: 0 }),
1629
- /* @__PURE__ */ jsx9(InputOTPSlot2, { className: "h-12", index: 1 }),
1630
- /* @__PURE__ */ jsx9(InputOTPSlot2, { className: "h-12", index: 2 }),
1631
- /* @__PURE__ */ jsx9(InputOTPSlot2, { className: "h-12", index: 3 }),
1632
- /* @__PURE__ */ jsx9(InputOTPSlot2, { className: "h-12", index: 4 }),
1633
- /* @__PURE__ */ jsx9(InputOTPSlot2, { className: "h-12", index: 5 })
1893
+ children: /* @__PURE__ */ jsxs8(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: [
1894
+ /* @__PURE__ */ jsx10(InputOTPSlot2, { className: "h-12", index: 0 }),
1895
+ /* @__PURE__ */ jsx10(InputOTPSlot2, { className: "h-12", index: 1 }),
1896
+ /* @__PURE__ */ jsx10(InputOTPSlot2, { className: "h-12", index: 2 }),
1897
+ /* @__PURE__ */ jsx10(InputOTPSlot2, { className: "h-12", index: 3 }),
1898
+ /* @__PURE__ */ jsx10(InputOTPSlot2, { className: "h-12", index: 4 }),
1899
+ /* @__PURE__ */ jsx10(InputOTPSlot2, { className: "h-12", index: 5 })
1634
1900
  ] })
1635
1901
  }
1636
1902
  ) }),
1637
- /* @__PURE__ */ jsx9(FormMessage5, {})
1903
+ /* @__PURE__ */ jsx10(FormMessage6, {})
1638
1904
  ] })
1639
1905
  }
1640
1906
  ),
1641
- /* @__PURE__ */ jsxs7("div", { className: "flex justify-between items-center", children: [
1642
- /* @__PURE__ */ jsx9(Countdown, { onResend, resending: isLoading }),
1643
- /* @__PURE__ */ jsxs7(
1644
- Button6,
1645
- {
1646
- type: "submit",
1647
- form: "verification-form",
1648
- disabled: isLoading || form.watch("code").length !== 6,
1649
- children: [
1650
- isLoading && /* @__PURE__ */ jsx9(Spinner4, {}),
1651
- t("form.confirm")
1652
- ]
1653
- }
1654
- )
1655
- ] })
1907
+ /* @__PURE__ */ jsx10(
1908
+ Button6,
1909
+ {
1910
+ type: "submit",
1911
+ form: "verification-form",
1912
+ className: "w-full",
1913
+ disabled: isLoading || codeLength !== 6,
1914
+ loading: isLoading,
1915
+ children: t("form.confirm")
1916
+ }
1917
+ ),
1918
+ /* @__PURE__ */ jsx10("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx10(Countdown, { onResend, resending: isLoading }) })
1656
1919
  ]
1657
1920
  }
1658
1921
  ) });
1659
1922
  };
1660
1923
 
1661
1924
  // src/components/auth/verify-email.tsx
1662
- import { Alert as Alert5, AlertDescription as AlertDescription5, AlertTitle as AlertTitle5 } from "@mesob/ui/components";
1663
- import { useMesob as useMesob6 } from "@mesob/ui/providers";
1664
- import { IconAlertCircle as IconAlertCircle5 } from "@tabler/icons-react";
1665
- import { useEffect as useEffect6, useState as useState7 } from "react";
1666
- import { toast as toast5 } from "sonner";
1667
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1925
+ import { Alert as Alert6, AlertDescription as AlertDescription6, AlertTitle as AlertTitle6 } from "@mesob/ui/components";
1926
+ import { useMesob as useMesob7 } from "@mesob/ui/providers";
1927
+ import { IconAlertCircle as IconAlertCircle6 } from "@tabler/icons-react";
1928
+ import { useEffect as useEffect7, useState as useState8 } from "react";
1929
+ import { toast as toast6 } from "sonner";
1930
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1668
1931
  var VerifyEmail = ({
1669
1932
  verificationId,
1670
1933
  email,
@@ -1672,13 +1935,13 @@ var VerifyEmail = ({
1672
1935
  }) => {
1673
1936
  const { hooks, setAuth } = useApi();
1674
1937
  const { config } = useConfig();
1675
- const mesob = useMesob6();
1938
+ const mesob = useMesob7();
1676
1939
  const t = useTranslator("Auth.verification");
1677
1940
  const common = useTranslator("Common");
1678
1941
  const footer = useTranslator("Auth.forgotPassword.footer");
1679
1942
  const Link = mesob?.navigation?.Link;
1680
- const [isLoading, setIsLoading] = useState7(false);
1681
- const [error, setError] = useState7(null);
1943
+ const [isLoading, setIsLoading] = useState8(false);
1944
+ const [error, setError] = useState8(null);
1682
1945
  const verifyEmailMutation = hooks.useMutation(
1683
1946
  "post",
1684
1947
  "/email/verification/confirm"
@@ -1695,9 +1958,9 @@ var VerifyEmail = ({
1695
1958
  });
1696
1959
  const logoImage = config.ui.logoImage;
1697
1960
  const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
1698
- useEffect6(() => {
1961
+ useEffect7(() => {
1699
1962
  if (error) {
1700
- toast5.error(error.title || "Error", {
1963
+ toast6.error(error.title || "Error", {
1701
1964
  description: error.description
1702
1965
  });
1703
1966
  }
@@ -1752,12 +2015,12 @@ var VerifyEmail = ({
1752
2015
  }
1753
2016
  };
1754
2017
  if (!verificationId) {
1755
- return /* @__PURE__ */ jsx10(
2018
+ return /* @__PURE__ */ jsx11(
1756
2019
  AuthLayout,
1757
2020
  {
1758
2021
  title: common("invalidLinkTitle"),
1759
2022
  description: common("invalidLinkDescription"),
1760
- footer: Link ? /* @__PURE__ */ jsx10(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx10(
2023
+ footer: Link ? /* @__PURE__ */ jsx11(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx11(
1761
2024
  "a",
1762
2025
  {
1763
2026
  href: signInLink,
@@ -1769,7 +2032,7 @@ var VerifyEmail = ({
1769
2032
  children: footer("backToSignIn")
1770
2033
  }
1771
2034
  ),
1772
- children: /* @__PURE__ */ jsx10("div", {})
2035
+ children: /* @__PURE__ */ jsx11("div", {})
1773
2036
  }
1774
2037
  );
1775
2038
  }
@@ -1781,13 +2044,13 @@ var VerifyEmail = ({
1781
2044
  errorContent = error;
1782
2045
  }
1783
2046
  }
1784
- return /* @__PURE__ */ jsxs8(
2047
+ return /* @__PURE__ */ jsxs9(
1785
2048
  AuthLayout,
1786
2049
  {
1787
- title: t("email.title"),
2050
+ title: config.ui.name,
1788
2051
  description: t("email.description"),
1789
2052
  logoImage,
1790
- footer: Link ? /* @__PURE__ */ jsx10(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx10(
2053
+ footer: Link ? /* @__PURE__ */ jsx11(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx11(
1791
2054
  "a",
1792
2055
  {
1793
2056
  href: signInLink,
@@ -1800,7 +2063,7 @@ var VerifyEmail = ({
1800
2063
  }
1801
2064
  ),
1802
2065
  children: [
1803
- /* @__PURE__ */ jsx10(
2066
+ /* @__PURE__ */ jsx11(
1804
2067
  VerificationForm,
1805
2068
  {
1806
2069
  verificationId,
@@ -1810,10 +2073,10 @@ var VerifyEmail = ({
1810
2073
  error
1811
2074
  }
1812
2075
  ),
1813
- errorContent && /* @__PURE__ */ jsxs8(Alert5, { variant: "destructive", className: "mt-4", children: [
1814
- /* @__PURE__ */ jsx10(IconAlertCircle5, { className: "h-4 w-4" }),
1815
- /* @__PURE__ */ jsx10(AlertTitle5, { children: errorContent.title }),
1816
- /* @__PURE__ */ jsx10(AlertDescription5, { children: errorContent.description })
2076
+ errorContent && /* @__PURE__ */ jsxs9(Alert6, { variant: "destructive", className: "mt-4", children: [
2077
+ /* @__PURE__ */ jsx11(IconAlertCircle6, { className: "h-4 w-4" }),
2078
+ /* @__PURE__ */ jsx11(AlertTitle6, { children: errorContent.title }),
2079
+ /* @__PURE__ */ jsx11(AlertDescription6, { children: errorContent.description })
1817
2080
  ] })
1818
2081
  ]
1819
2082
  }
@@ -1821,12 +2084,12 @@ var VerifyEmail = ({
1821
2084
  };
1822
2085
 
1823
2086
  // src/components/auth/verify-phone.tsx
1824
- import { Alert as Alert6, AlertDescription as AlertDescription6, AlertTitle as AlertTitle6 } from "@mesob/ui/components";
1825
- import { useMesob as useMesob7 } from "@mesob/ui/providers";
1826
- import { IconAlertCircle as IconAlertCircle6 } from "@tabler/icons-react";
1827
- import { useEffect as useEffect7, useState as useState8 } from "react";
1828
- import { toast as toast6 } from "sonner";
1829
- import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2087
+ import { Alert as Alert7, AlertDescription as AlertDescription7, AlertTitle as AlertTitle7 } from "@mesob/ui/components";
2088
+ import { useMesob as useMesob8 } from "@mesob/ui/providers";
2089
+ import { IconAlertCircle as IconAlertCircle7 } from "@tabler/icons-react";
2090
+ import { useEffect as useEffect8, useState as useState9 } from "react";
2091
+ import { toast as toast7 } from "sonner";
2092
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1830
2093
  var VerifyPhone = ({
1831
2094
  verificationId,
1832
2095
  context,
@@ -1835,13 +2098,13 @@ var VerifyPhone = ({
1835
2098
  }) => {
1836
2099
  const { hooks, refresh, setAuth } = useApi();
1837
2100
  const { config } = useConfig();
1838
- const mesob = useMesob7();
2101
+ const mesob = useMesob8();
1839
2102
  const Link = mesob?.navigation?.Link;
1840
2103
  const t = useTranslator("Auth.verification");
1841
2104
  const common = useTranslator("Common");
1842
2105
  const footer = useTranslator("Auth.forgotPassword.footer");
1843
- const [isLoading, setIsLoading] = useState8(false);
1844
- const [error, setError] = useState8(null);
2106
+ const [isLoading, setIsLoading] = useState9(false);
2107
+ const [error, setError] = useState9(null);
1845
2108
  const verifyPhoneMutation = hooks.useMutation(
1846
2109
  "post",
1847
2110
  "/phone/verification/confirm"
@@ -1858,9 +2121,9 @@ var VerifyPhone = ({
1858
2121
  });
1859
2122
  const logoImage = config.ui.logoImage;
1860
2123
  const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
1861
- useEffect7(() => {
2124
+ useEffect8(() => {
1862
2125
  if (error) {
1863
- toast6.error(error.title || "Error", {
2126
+ toast7.error(error.title || "Error", {
1864
2127
  description: error.description
1865
2128
  });
1866
2129
  }
@@ -1928,13 +2191,13 @@ var VerifyPhone = ({
1928
2191
  }
1929
2192
  };
1930
2193
  if (!verificationId) {
1931
- return /* @__PURE__ */ jsx11(
2194
+ return /* @__PURE__ */ jsx12(
1932
2195
  AuthLayout,
1933
2196
  {
1934
2197
  title: common("invalidLinkTitle"),
1935
2198
  description: common("invalidLinkDescription"),
1936
- footer: /* @__PURE__ */ jsx11(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }),
1937
- children: /* @__PURE__ */ jsx11("div", {})
2199
+ footer: /* @__PURE__ */ jsx12(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }),
2200
+ children: /* @__PURE__ */ jsx12("div", {})
1938
2201
  }
1939
2202
  );
1940
2203
  }
@@ -1946,15 +2209,15 @@ var VerifyPhone = ({
1946
2209
  errorContent = error;
1947
2210
  }
1948
2211
  }
1949
- return /* @__PURE__ */ jsxs9(
2212
+ return /* @__PURE__ */ jsxs10(
1950
2213
  AuthLayout,
1951
2214
  {
1952
- title: t("phone.title"),
2215
+ title: config.ui.name,
1953
2216
  description: t("phone.description", {
1954
2217
  target: phone || t("phone.missingPhone")
1955
2218
  }),
1956
2219
  logoImage,
1957
- footer: Link ? /* @__PURE__ */ jsx11(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx11(
2220
+ footer: Link ? /* @__PURE__ */ jsx12(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx12(
1958
2221
  "a",
1959
2222
  {
1960
2223
  href: signInLink,
@@ -1967,7 +2230,7 @@ var VerifyPhone = ({
1967
2230
  }
1968
2231
  ),
1969
2232
  children: [
1970
- /* @__PURE__ */ jsx11(
2233
+ /* @__PURE__ */ jsx12(
1971
2234
  VerificationForm,
1972
2235
  {
1973
2236
  verificationId,
@@ -1977,20 +2240,55 @@ var VerifyPhone = ({
1977
2240
  error
1978
2241
  }
1979
2242
  ),
1980
- errorContent && /* @__PURE__ */ jsxs9(Alert6, { variant: "destructive", className: "mt-4", children: [
1981
- /* @__PURE__ */ jsx11(IconAlertCircle6, { className: "h-4 w-4" }),
1982
- /* @__PURE__ */ jsx11(AlertTitle6, { children: errorContent.title }),
1983
- /* @__PURE__ */ jsx11(AlertDescription6, { children: errorContent.description })
2243
+ errorContent && /* @__PURE__ */ jsxs10(Alert7, { variant: "destructive", className: "mt-4", children: [
2244
+ /* @__PURE__ */ jsx12(IconAlertCircle7, { className: "h-4 w-4" }),
2245
+ /* @__PURE__ */ jsx12(AlertTitle7, { children: errorContent.title }),
2246
+ /* @__PURE__ */ jsx12(AlertDescription7, { children: errorContent.description })
1984
2247
  ] })
1985
2248
  ]
1986
2249
  }
1987
2250
  );
1988
2251
  };
1989
2252
 
2253
+ // src/components/authorization/deny.tsx
2254
+ import { deny as canDeny } from "@mesob/common";
2255
+ import { Fragment as Fragment2, jsx as jsx13 } from "react/jsx-runtime";
2256
+ function Deny({ permissions, userPermissions, children }) {
2257
+ const { isLoading, user } = useSession();
2258
+ if (userPermissions === void 0 && isLoading) {
2259
+ return null;
2260
+ }
2261
+ const resolvedPermissions = userPermissions ?? user?.permissions ?? [];
2262
+ if (canDeny(permissions, resolvedPermissions)) {
2263
+ return /* @__PURE__ */ jsx13(Fragment2, { children });
2264
+ }
2265
+ return null;
2266
+ }
2267
+
2268
+ // src/components/authorization/grant.tsx
2269
+ import { grant as canGrant } from "@mesob/common";
2270
+ import { Fragment as Fragment3, jsx as jsx14 } from "react/jsx-runtime";
2271
+ function Grant({
2272
+ permissions,
2273
+ userPermissions,
2274
+ fallback = null,
2275
+ children
2276
+ }) {
2277
+ const { isLoading, user } = useSession();
2278
+ if (userPermissions === void 0 && isLoading) {
2279
+ return null;
2280
+ }
2281
+ const resolvedPermissions = userPermissions ?? user?.permissions ?? [];
2282
+ if (canGrant(permissions, resolvedPermissions)) {
2283
+ return /* @__PURE__ */ jsx14(Fragment3, { children });
2284
+ }
2285
+ return /* @__PURE__ */ jsx14(Fragment3, { children: fallback });
2286
+ }
2287
+
1990
2288
  // src/components/error-boundary.tsx
1991
2289
  import { Button as Button7 } from "@mesob/ui/components";
1992
2290
  import { Component } from "react";
1993
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2291
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
1994
2292
  var ErrorBoundary = class extends Component {
1995
2293
  constructor(props) {
1996
2294
  super(props);
@@ -2012,28 +2310,112 @@ var ErrorBoundary = class extends Component {
2012
2310
  reset: this.reset
2013
2311
  });
2014
2312
  }
2015
- return /* @__PURE__ */ jsx12(ErrorFallback, { error: this.state.error, reset: this.reset });
2313
+ return /* @__PURE__ */ jsx15(ErrorFallback, { error: this.state.error, reset: this.reset });
2016
2314
  }
2017
2315
  return this.props.children;
2018
2316
  }
2019
2317
  };
2020
2318
  function ErrorFallback({ error, reset }) {
2021
- 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: [
2022
- /* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
2023
- /* @__PURE__ */ jsx12("h2", { className: "text-2xl font-bold text-destructive", children: "Something went wrong" }),
2024
- /* @__PURE__ */ jsx12("p", { className: "text-muted-foreground", children: error.message || "An unexpected error occurred" })
2319
+ return /* @__PURE__ */ jsx15("div", { className: "flex flex-col items-center justify-center min-h-[400px] p-6", children: /* @__PURE__ */ jsxs11("div", { className: "max-w-md w-full space-y-4 text-center", children: [
2320
+ /* @__PURE__ */ jsxs11("div", { className: "space-y-2", children: [
2321
+ /* @__PURE__ */ jsx15("h2", { className: "text-2xl font-bold text-destructive", children: "Something went wrong" }),
2322
+ /* @__PURE__ */ jsx15("p", { className: "text-muted-foreground", children: error.message || "An unexpected error occurred" })
2025
2323
  ] }),
2026
- /* @__PURE__ */ jsx12(Button7, { onClick: reset, variant: "outline", children: "Try again" })
2324
+ /* @__PURE__ */ jsx15(Button7, { onClick: reset, variant: "outline", children: "Try again" })
2027
2325
  ] }) });
2028
2326
  }
2029
2327
  function AuthErrorBoundary({ children }) {
2030
- return /* @__PURE__ */ jsx12(ErrorBoundary, { children });
2328
+ return /* @__PURE__ */ jsx15(ErrorBoundary, { children });
2329
+ }
2330
+
2331
+ // src/components/iam/permission-selector.tsx
2332
+ import {
2333
+ Badge,
2334
+ EntitySelector,
2335
+ useEntitySectionState
2336
+ } from "@mesob/ui/components";
2337
+ import { IconKey } from "@tabler/icons-react";
2338
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
2339
+ var permissionColumns = [
2340
+ {
2341
+ key: "permission",
2342
+ header: "Permission",
2343
+ cell: (permission) => /* @__PURE__ */ jsxs12("div", { className: "space-y-1", children: [
2344
+ /* @__PURE__ */ jsx16("p", { className: "font-medium", children: permission.activity }),
2345
+ /* @__PURE__ */ jsx16("p", { className: "font-mono text-xs text-muted-foreground", children: permission.id })
2346
+ ] })
2347
+ },
2348
+ {
2349
+ key: "scope",
2350
+ header: "Scope",
2351
+ cell: (permission) => /* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap gap-2", children: [
2352
+ /* @__PURE__ */ jsx16(Badge, { variant: "secondary", children: permission.application }),
2353
+ /* @__PURE__ */ jsx16(Badge, { variant: "outline", children: permission.feature })
2354
+ ] })
2355
+ }
2356
+ ];
2357
+ function PermissionSelector({
2358
+ trigger,
2359
+ multiple = true,
2360
+ onSelect,
2361
+ excludeIds = []
2362
+ }) {
2363
+ const { hooks } = useApi();
2364
+ const state = useEntitySectionState({
2365
+ defaultSort: "id",
2366
+ defaultOrder: "asc",
2367
+ defaultPageSize: 10,
2368
+ searchParamName: "search"
2369
+ });
2370
+ const permissionsQuery = state.queryConfig;
2371
+ const { data, isPending, isFetching } = hooks.useQuery(
2372
+ "get",
2373
+ "/permissions",
2374
+ permissionsQuery
2375
+ );
2376
+ const items = (data?.permissions ?? []).filter(
2377
+ (permission) => !excludeIds.includes(permission.id)
2378
+ );
2379
+ const config = {
2380
+ title: "Select permission(s)",
2381
+ multiple,
2382
+ entityName: "permission",
2383
+ entityIcon: IconKey,
2384
+ columns: permissionColumns,
2385
+ getItemLabel: (permission) => permission.id,
2386
+ searchPlaceholder: "Search permissions...",
2387
+ filterOptions: [
2388
+ { label: "All", value: "" },
2389
+ { label: "Application", value: "application" },
2390
+ { label: "Feature", value: "feature" },
2391
+ { label: "Activity", value: "activity" }
2392
+ ],
2393
+ sortOptions: [
2394
+ { label: "ID", value: "id" },
2395
+ { label: "Application", value: "application" },
2396
+ { label: "Feature", value: "feature" },
2397
+ { label: "Activity", value: "activity" }
2398
+ ],
2399
+ showViewToggle: false,
2400
+ wrapHeaderInCard: false
2401
+ };
2402
+ return /* @__PURE__ */ jsx16(
2403
+ EntitySelector,
2404
+ {
2405
+ trigger,
2406
+ config,
2407
+ onSelect,
2408
+ items,
2409
+ total: items.length,
2410
+ isLoading: isPending || isFetching,
2411
+ state
2412
+ }
2413
+ );
2031
2414
  }
2032
2415
 
2033
2416
  // src/components/iam/permissions.tsx
2034
- import { Badge, Button as Button8 } from "@mesob/ui/components";
2035
- import { useLocale } from "next-intl";
2036
- import { useState as useState9 } from "react";
2417
+ import { Badge as Badge2, Button as Button8 } from "@mesob/ui/components";
2418
+ import { useState as useState10 } from "react";
2037
2419
 
2038
2420
  // src/components/shared/data-table.tsx
2039
2421
  import {
@@ -2047,7 +2429,7 @@ import {
2047
2429
 
2048
2430
  // src/components/skeletons/table-skeleton.tsx
2049
2431
  import { Skeleton } from "@mesob/ui/components";
2050
- import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
2432
+ import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
2051
2433
  function TableSkeleton({ columns = 5, rows = 10 }) {
2052
2434
  const headerKeys = Array.from({ length: columns }, (_, i) => `header-${i}`);
2053
2435
  const rowKeys = Array.from({ length: rows }, (_, i) => `row-${i}`);
@@ -2055,32 +2437,32 @@ function TableSkeleton({ columns = 5, rows = 10 }) {
2055
2437
  { length: rows },
2056
2438
  (_, rowIdx) => Array.from({ length: columns }, (_2, colIdx) => `cell-${rowIdx}-${colIdx}`)
2057
2439
  );
2058
- return /* @__PURE__ */ jsxs11("div", { className: "w-full space-y-4", children: [
2059
- /* @__PURE__ */ jsxs11("div", { className: "flex justify-between items-center", children: [
2060
- /* @__PURE__ */ jsx13(Skeleton, { className: "h-8 w-48" }),
2061
- /* @__PURE__ */ jsx13(Skeleton, { className: "h-10 w-32" })
2440
+ return /* @__PURE__ */ jsxs13("div", { className: "w-full space-y-4", children: [
2441
+ /* @__PURE__ */ jsxs13("div", { className: "flex justify-between items-center", children: [
2442
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-8 w-48" }),
2443
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-32" })
2062
2444
  ] }),
2063
- /* @__PURE__ */ jsxs11("div", { className: "flex gap-4", children: [
2064
- /* @__PURE__ */ jsx13(Skeleton, { className: "h-10 flex-1 max-w-sm" }),
2065
- /* @__PURE__ */ jsx13(Skeleton, { className: "h-10 w-24" }),
2066
- /* @__PURE__ */ jsx13(Skeleton, { className: "h-10 w-24" })
2445
+ /* @__PURE__ */ jsxs13("div", { className: "flex gap-4", children: [
2446
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 flex-1 max-w-sm" }),
2447
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-24" }),
2448
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-24" })
2067
2449
  ] }),
2068
- /* @__PURE__ */ jsxs11("div", { className: "border rounded-lg overflow-hidden", children: [
2069
- /* @__PURE__ */ jsx13("div", { className: "flex gap-4 p-4 bg-muted", children: headerKeys.map((key) => /* @__PURE__ */ jsx13(Skeleton, { className: "h-4 flex-1" }, key)) }),
2070
- 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))
2450
+ /* @__PURE__ */ jsxs13("div", { className: "border rounded-lg overflow-hidden", children: [
2451
+ /* @__PURE__ */ jsx17("div", { className: "flex gap-4 p-4 bg-muted", children: headerKeys.map((key) => /* @__PURE__ */ jsx17(Skeleton, { className: "h-4 flex-1" }, key)) }),
2452
+ rowKeys.map((rowKey, rowIdx) => /* @__PURE__ */ jsx17("div", { className: "flex gap-4 p-4 border-t", children: cellKeys[rowIdx]?.map((cellKey) => /* @__PURE__ */ jsx17(Skeleton, { className: "h-4 flex-1" }, cellKey)) }, rowKey))
2071
2453
  ] }),
2072
- /* @__PURE__ */ jsxs11("div", { className: "flex justify-between items-center", children: [
2073
- /* @__PURE__ */ jsx13(Skeleton, { className: "h-4 w-32" }),
2074
- /* @__PURE__ */ jsxs11("div", { className: "flex gap-2", children: [
2075
- /* @__PURE__ */ jsx13(Skeleton, { className: "h-10 w-20" }),
2076
- /* @__PURE__ */ jsx13(Skeleton, { className: "h-10 w-20" })
2454
+ /* @__PURE__ */ jsxs13("div", { className: "flex justify-between items-center", children: [
2455
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-4 w-32" }),
2456
+ /* @__PURE__ */ jsxs13("div", { className: "flex gap-2", children: [
2457
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-20" }),
2458
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-20" })
2077
2459
  ] })
2078
2460
  ] })
2079
2461
  ] });
2080
2462
  }
2081
2463
 
2082
2464
  // src/components/shared/data-table.tsx
2083
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
2465
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
2084
2466
  function DataTable({
2085
2467
  data,
2086
2468
  columns,
@@ -2090,24 +2472,24 @@ function DataTable({
2090
2472
  actions
2091
2473
  }) {
2092
2474
  if (isLoading) {
2093
- return /* @__PURE__ */ jsx14(TableSkeleton, { columns: columns.length, rows: 5 });
2475
+ return /* @__PURE__ */ jsx18(TableSkeleton, { columns: columns.length, rows: 5 });
2094
2476
  }
2095
2477
  if (data.length === 0) {
2096
- return /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center min-h-[400px] p-6", children: [
2097
- /* @__PURE__ */ jsx14("p", { className: "text-muted-foreground", children: emptyMessage }),
2098
- actions && /* @__PURE__ */ jsx14("div", { className: "mt-4", children: actions })
2478
+ return /* @__PURE__ */ jsxs14("div", { className: "flex flex-col items-center justify-center min-h-[400px] p-6", children: [
2479
+ /* @__PURE__ */ jsx18("p", { className: "text-muted-foreground", children: emptyMessage }),
2480
+ actions && /* @__PURE__ */ jsx18("div", { className: "mt-4", children: actions })
2099
2481
  ] });
2100
2482
  }
2101
- return /* @__PURE__ */ jsxs12("div", { className: "w-full space-y-4", children: [
2102
- actions && /* @__PURE__ */ jsx14("div", { className: "flex justify-end", children: actions }),
2103
- /* @__PURE__ */ jsx14("div", { className: "border rounded-lg overflow-hidden", children: /* @__PURE__ */ jsxs12(Table, { children: [
2104
- /* @__PURE__ */ jsx14(TableHeader, { children: /* @__PURE__ */ jsx14(TableRow, { children: columns.map((column) => /* @__PURE__ */ jsx14(TableHead, { children: column.header }, column.key)) }) }),
2105
- /* @__PURE__ */ jsx14(TableBody, { children: data.map((row) => /* @__PURE__ */ jsx14(
2483
+ return /* @__PURE__ */ jsxs14("div", { className: "w-full space-y-4", children: [
2484
+ actions && /* @__PURE__ */ jsx18("div", { className: "flex justify-end", children: actions }),
2485
+ /* @__PURE__ */ jsx18("div", { className: "border rounded-lg overflow-hidden", children: /* @__PURE__ */ jsxs14(Table, { children: [
2486
+ /* @__PURE__ */ jsx18(TableHeader, { children: /* @__PURE__ */ jsx18(TableRow, { children: columns.map((column) => /* @__PURE__ */ jsx18(TableHead, { children: column.header }, column.key)) }) }),
2487
+ /* @__PURE__ */ jsx18(TableBody, { children: data.map((row) => /* @__PURE__ */ jsx18(
2106
2488
  TableRow,
2107
2489
  {
2108
2490
  onClick: () => onRowClick?.(row),
2109
2491
  className: onRowClick ? "cursor-pointer hover:bg-muted/50" : "",
2110
- children: columns.map((column) => /* @__PURE__ */ jsx14(TableCell, { children: column.cell(row) }, `${row.id}-${column.key}`))
2492
+ children: columns.map((column) => /* @__PURE__ */ jsx18(TableCell, { children: column.cell(row) }, `${row.id}-${column.key}`))
2111
2493
  },
2112
2494
  row.id
2113
2495
  )) })
@@ -2116,23 +2498,10 @@ function DataTable({
2116
2498
  }
2117
2499
 
2118
2500
  // src/components/iam/permissions.tsx
2119
- import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
2120
- function getTranslation(value, locale) {
2121
- if (!value) {
2122
- return "";
2123
- }
2124
- if (typeof value === "string") {
2125
- return value;
2126
- }
2127
- if (typeof value === "object") {
2128
- return value[locale] ?? value.en ?? value.am ?? "";
2129
- }
2130
- return "";
2131
- }
2501
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
2132
2502
  function Permissions() {
2133
2503
  const { hooks } = useApi();
2134
- const locale = useLocale();
2135
- const [page, setPage] = useState9(1);
2504
+ const [page, setPage] = useState10(1);
2136
2505
  const limit = 20;
2137
2506
  const { data, isLoading, error } = hooks.useQuery("get", "/permissions", {
2138
2507
  params: {
@@ -2142,81 +2511,636 @@ function Permissions() {
2142
2511
  }
2143
2512
  }
2144
2513
  });
2145
- const columns = [
2146
- {
2147
- key: "name",
2148
- header: "Permission",
2149
- cell: (permission) => /* @__PURE__ */ jsxs13("div", { children: [
2150
- /* @__PURE__ */ jsx15("p", { className: "font-medium", children: getTranslation(permission.name, locale) }),
2151
- /* @__PURE__ */ jsx15(Badge, { variant: "outline", className: "mt-1 font-mono text-xs", children: permission.code })
2152
- ] })
2153
- },
2154
- {
2155
- key: "resource",
2156
- header: "Resource",
2157
- cell: (permission) => /* @__PURE__ */ jsx15(Badge, { variant: "secondary", children: permission.resource })
2158
- },
2159
- {
2160
- key: "action",
2161
- header: "Action",
2162
- cell: (permission) => /* @__PURE__ */ jsx15(Badge, { variant: "outline", children: permission.action })
2163
- },
2514
+ const columns = [
2515
+ {
2516
+ key: "activity",
2517
+ header: "Permission",
2518
+ cell: (permission) => /* @__PURE__ */ jsxs15("div", { children: [
2519
+ /* @__PURE__ */ jsx19("p", { className: "font-medium", children: permission.activity }),
2520
+ /* @__PURE__ */ jsx19(Badge2, { variant: "outline", className: "mt-1 font-mono text-xs", children: permission.id })
2521
+ ] })
2522
+ },
2523
+ {
2524
+ key: "application",
2525
+ header: "Application",
2526
+ cell: (permission) => /* @__PURE__ */ jsx19(Badge2, { variant: "secondary", children: permission.application })
2527
+ },
2528
+ {
2529
+ key: "feature",
2530
+ header: "Feature",
2531
+ cell: (permission) => /* @__PURE__ */ jsx19(Badge2, { variant: "outline", children: permission.feature })
2532
+ },
2533
+ {
2534
+ key: "description",
2535
+ header: "Description",
2536
+ cell: (permission) => /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground max-w-xs truncate", children: String(permission.description ?? "\u2014") })
2537
+ }
2538
+ ];
2539
+ if (error) {
2540
+ return /* @__PURE__ */ jsx19("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx19("p", { className: "text-destructive", children: "Error loading permissions" }) });
2541
+ }
2542
+ return /* @__PURE__ */ jsxs15("div", { className: "w-full p-6 space-y-4", children: [
2543
+ /* @__PURE__ */ jsxs15("div", { className: "flex justify-between items-center", children: [
2544
+ /* @__PURE__ */ jsxs15("div", { children: [
2545
+ /* @__PURE__ */ jsx19("h1", { className: "text-3xl font-bold", children: "Permissions" }),
2546
+ /* @__PURE__ */ jsx19("p", { className: "text-muted-foreground", children: "View the permission catalog for this tenant" })
2547
+ ] }),
2548
+ /* @__PURE__ */ jsx19(Button8, { variant: "outline", children: "Seed Permissions" })
2549
+ ] }),
2550
+ /* @__PURE__ */ jsx19(
2551
+ DataTable,
2552
+ {
2553
+ data: data?.permissions || [],
2554
+ columns,
2555
+ isLoading,
2556
+ emptyMessage: "No permissions found"
2557
+ }
2558
+ ),
2559
+ data && "permissions" in data && data.permissions && data.permissions.length >= limit && /* @__PURE__ */ jsxs15("div", { className: "flex justify-between items-center", children: [
2560
+ /* @__PURE__ */ jsx19(
2561
+ Button8,
2562
+ {
2563
+ variant: "outline",
2564
+ disabled: page === 1,
2565
+ onClick: () => setPage((prev) => prev - 1),
2566
+ children: "Previous"
2567
+ }
2568
+ ),
2569
+ /* @__PURE__ */ jsxs15("span", { className: "text-sm text-muted-foreground", children: [
2570
+ "Page ",
2571
+ page
2572
+ ] }),
2573
+ /* @__PURE__ */ jsx19(
2574
+ Button8,
2575
+ {
2576
+ variant: "outline",
2577
+ onClick: () => setPage((prev) => prev + 1),
2578
+ children: "Next"
2579
+ }
2580
+ )
2581
+ ] })
2582
+ ] });
2583
+ }
2584
+
2585
+ // src/components/iam/role-detail-layout.tsx
2586
+ import {
2587
+ EntityDetailHeader,
2588
+ EntityEmptyState,
2589
+ PageContainer,
2590
+ useBreadcrumbs
2591
+ } from "@mesob/ui/components";
2592
+ import { IconShield } from "@tabler/icons-react";
2593
+ import { useMemo as useMemo2 } from "react";
2594
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
2595
+ function str(value) {
2596
+ if (value == null) {
2597
+ return "";
2598
+ }
2599
+ if (typeof value === "string") {
2600
+ return value;
2601
+ }
2602
+ if (typeof value === "object" && value !== null && "en" in value) {
2603
+ const localized = value;
2604
+ return localized.en ?? localized.am ?? "";
2605
+ }
2606
+ return String(value);
2607
+ }
2608
+ function RoleDetailLayout({
2609
+ roleId,
2610
+ basePath = "/iam/roles",
2611
+ children
2612
+ }) {
2613
+ const { hooks } = useApi();
2614
+ const { config } = useConfig();
2615
+ const { data, isLoading, isFetching, isError } = hooks.useQuery(
2616
+ "get",
2617
+ "/roles/{id}",
2618
+ { params: { path: { id: roleId } } },
2619
+ { enabled: !!roleId }
2620
+ );
2621
+ const role = data?.role;
2622
+ const title = role ? str(role.name) || role.code : roleId ?? "Role";
2623
+ useBreadcrumbs({
2624
+ items: [
2625
+ { label: "Home", href: "/dashboard" },
2626
+ { label: "IAM", href: "/iam" },
2627
+ { label: "Roles", href: basePath },
2628
+ { label: title }
2629
+ ]
2630
+ });
2631
+ const tabs = useMemo2(
2632
+ () => [
2633
+ { value: "detail", name: "Detail", href: `${basePath}/${roleId}` },
2634
+ {
2635
+ value: "permissions",
2636
+ name: "Permissions",
2637
+ href: `${basePath}/${roleId}/permissions`
2638
+ },
2639
+ {
2640
+ value: "users",
2641
+ name: "Users",
2642
+ href: `${basePath}/${roleId}/users`
2643
+ }
2644
+ ],
2645
+ [basePath, roleId]
2646
+ );
2647
+ if (!roleId) {
2648
+ return null;
2649
+ }
2650
+ const loading = isLoading || isFetching;
2651
+ if (!(loading || role)) {
2652
+ return /* @__PURE__ */ jsx20(PageContainer, { className: "flex flex-1 flex-col gap-4 p-4 pt-0", children: /* @__PURE__ */ jsx20(
2653
+ EntityEmptyState,
2654
+ {
2655
+ icon: IconShield,
2656
+ entityName: "role",
2657
+ title: isError ? "Role unavailable" : "Role not found",
2658
+ description: isError ? "Failed to load this role." : "This role no longer exists.",
2659
+ actionLabel: "Back to roles",
2660
+ onAction: () => config.navigation?.onNavigate?.(basePath) ?? window.history.back()
2661
+ }
2662
+ ) });
2663
+ }
2664
+ return /* @__PURE__ */ jsxs16(PageContainer, { className: "flex flex-1 flex-col gap-4 p-4 pt-0", children: [
2665
+ /* @__PURE__ */ jsx20(
2666
+ EntityDetailHeader,
2667
+ {
2668
+ title,
2669
+ icon: /* @__PURE__ */ jsx20(IconShield, { className: "h-5 w-5" }),
2670
+ loading,
2671
+ tabs
2672
+ }
2673
+ ),
2674
+ children
2675
+ ] });
2676
+ }
2677
+
2678
+ // src/components/iam/role-detail-page.tsx
2679
+ import { zodResolver as zodResolver7 } from "@hookform/resolvers/zod";
2680
+ import {
2681
+ EntityFormActions,
2682
+ Form as Form7,
2683
+ FormControl as FormControl7,
2684
+ FormField as FormField7,
2685
+ FormItem as FormItem7,
2686
+ FormLabel as FormLabel7,
2687
+ FormMessage as FormMessage7,
2688
+ Input as Input6,
2689
+ LocaleInputText,
2690
+ LocaleInputTextarea,
2691
+ Section,
2692
+ Skeleton as Skeleton2
2693
+ } from "@mesob/ui/components";
2694
+ import { useLocaleSchemas } from "@mesob/ui/providers";
2695
+ import { useQueryClient } from "@tanstack/react-query";
2696
+ import { useEffect as useEffect9, useMemo as useMemo3 } from "react";
2697
+ import { useForm as useForm7 } from "react-hook-form";
2698
+ import { toast as toast8 } from "sonner";
2699
+ import { z as z7 } from "zod";
2700
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
2701
+ function RoleDetailPage({
2702
+ roleId,
2703
+ basePath = "/iam/roles"
2704
+ }) {
2705
+ const { hooks } = useApi();
2706
+ const { config } = useConfig();
2707
+ const qc = useQueryClient();
2708
+ const { localeInputDefault, requiredSchema, optionalSchema } = useLocaleSchemas();
2709
+ const schema = useMemo3(
2710
+ () => z7.object({
2711
+ name: requiredSchema,
2712
+ code: z7.string().min(1, "Code is required"),
2713
+ description: optionalSchema
2714
+ }),
2715
+ [requiredSchema, optionalSchema]
2716
+ );
2717
+ const defaults = useMemo3(
2718
+ () => ({
2719
+ name: { ...localeInputDefault },
2720
+ code: "",
2721
+ description: { ...localeInputDefault }
2722
+ }),
2723
+ [localeInputDefault]
2724
+ );
2725
+ const { data, isLoading } = hooks.useQuery(
2726
+ "get",
2727
+ "/roles/{id}",
2728
+ { params: { path: { id: roleId } } },
2729
+ { enabled: !!roleId }
2730
+ );
2731
+ const update = hooks.useMutation("put", "/roles/{id}", {
2732
+ onSuccess: () => {
2733
+ qc.invalidateQueries({ queryKey: ["get", "/roles"] });
2734
+ qc.invalidateQueries({ queryKey: ["get", "/roles/{id}"] });
2735
+ toast8.success("Role updated");
2736
+ },
2737
+ onError: () => {
2738
+ toast8.error("Failed to update role");
2739
+ }
2740
+ });
2741
+ const remove = hooks.useMutation("delete", "/roles/{id}", {
2742
+ onSuccess: () => {
2743
+ qc.invalidateQueries({ queryKey: ["get", "/roles"] });
2744
+ toast8.success("Role deleted");
2745
+ config.navigation?.onNavigate?.(basePath);
2746
+ },
2747
+ onError: () => {
2748
+ toast8.error("Failed to delete role");
2749
+ }
2750
+ });
2751
+ const form = useForm7({
2752
+ resolver: zodResolver7(schema),
2753
+ defaultValues: defaults
2754
+ });
2755
+ const { reset, formState, control, register } = form;
2756
+ useEffect9(() => {
2757
+ if (!data?.role) {
2758
+ return;
2759
+ }
2760
+ const r = data.role;
2761
+ reset({
2762
+ name: r.name ?? {},
2763
+ code: r.code,
2764
+ description: r.description ?? {}
2765
+ });
2766
+ }, [data?.role, reset]);
2767
+ if (!roleId) {
2768
+ return null;
2769
+ }
2770
+ const role = data?.role;
2771
+ const editable = role?.isEditable !== false;
2772
+ const deletable = role?.isDeletable !== false;
2773
+ const onSubmit = form.handleSubmit(async (d) => {
2774
+ await update.mutateAsync({
2775
+ params: { path: { id: roleId } },
2776
+ body: {
2777
+ name: d.name,
2778
+ code: d.code,
2779
+ description: d.description ?? void 0
2780
+ }
2781
+ });
2782
+ });
2783
+ const footer = role ? /* @__PURE__ */ jsx21(
2784
+ EntityFormActions,
2785
+ {
2786
+ mode: "edit",
2787
+ onSubmit,
2788
+ onDelete: deletable ? () => remove.mutate({
2789
+ params: { path: { id: roleId } }
2790
+ }) : void 0,
2791
+ isSubmitting: update.isPending,
2792
+ isDeleting: remove.isPending,
2793
+ disabled: !editable,
2794
+ itemName: "role"
2795
+ }
2796
+ ) : null;
2797
+ return /* @__PURE__ */ jsx21(Section, { title: "Role details", footer, defaultOpen: true, children: isLoading || !role ? /* @__PURE__ */ jsx21(RoleDetailSkeleton, {}) : /* @__PURE__ */ jsx21(Form7, { ...form, children: /* @__PURE__ */ jsxs17("form", { onSubmit, className: "space-y-4", children: [
2798
+ /* @__PURE__ */ jsx21(
2799
+ LocaleInputText,
2800
+ {
2801
+ label: "Name",
2802
+ field: "name",
2803
+ required: true,
2804
+ register,
2805
+ errors: formState.errors,
2806
+ placeholder: "e.g. Administrator",
2807
+ disabled: !editable
2808
+ }
2809
+ ),
2810
+ /* @__PURE__ */ jsx21(
2811
+ FormField7,
2812
+ {
2813
+ control,
2814
+ name: "code",
2815
+ render: ({ field }) => /* @__PURE__ */ jsxs17(FormItem7, { children: [
2816
+ /* @__PURE__ */ jsxs17(FormLabel7, { children: [
2817
+ "Code ",
2818
+ /* @__PURE__ */ jsx21("span", { className: "text-destructive", children: "*" })
2819
+ ] }),
2820
+ /* @__PURE__ */ jsx21(FormControl7, { children: /* @__PURE__ */ jsx21(
2821
+ Input6,
2822
+ {
2823
+ placeholder: "e.g. admin",
2824
+ disabled: !editable,
2825
+ ...field
2826
+ }
2827
+ ) }),
2828
+ /* @__PURE__ */ jsx21(FormMessage7, {})
2829
+ ] })
2830
+ }
2831
+ ),
2832
+ /* @__PURE__ */ jsx21(
2833
+ LocaleInputTextarea,
2834
+ {
2835
+ label: "Description",
2836
+ field: "description",
2837
+ register,
2838
+ errors: formState.errors,
2839
+ placeholder: "Description",
2840
+ rows: 3,
2841
+ disabled: !editable
2842
+ }
2843
+ )
2844
+ ] }) }) });
2845
+ }
2846
+ function RoleDetailSkeleton() {
2847
+ return /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
2848
+ /* @__PURE__ */ jsxs17("div", { className: "space-y-2", children: [
2849
+ /* @__PURE__ */ jsx21(Skeleton2, { className: "h-4 w-16" }),
2850
+ /* @__PURE__ */ jsx21(Skeleton2, { className: "h-10 w-full" })
2851
+ ] }),
2852
+ /* @__PURE__ */ jsxs17("div", { className: "space-y-2", children: [
2853
+ /* @__PURE__ */ jsx21(Skeleton2, { className: "h-4 w-14" }),
2854
+ /* @__PURE__ */ jsx21(Skeleton2, { className: "h-10 w-full" })
2855
+ ] }),
2856
+ /* @__PURE__ */ jsxs17("div", { className: "space-y-2", children: [
2857
+ /* @__PURE__ */ jsx21(Skeleton2, { className: "h-4 w-24" }),
2858
+ /* @__PURE__ */ jsx21(Skeleton2, { className: "h-20 w-full" })
2859
+ ] })
2860
+ ] });
2861
+ }
2862
+
2863
+ // src/components/iam/role-permissions-page.tsx
2864
+ import {
2865
+ Badge as Badge3,
2866
+ Button as Button9,
2867
+ DataTablePagination,
2868
+ DeleteConfirmButton,
2869
+ DisplayTable,
2870
+ EntityEmptyState as EntityEmptyState2,
2871
+ EntityFilter,
2872
+ EntityHeader,
2873
+ EntityLoadingState,
2874
+ EntitySearch,
2875
+ EntitySort,
2876
+ EntityViewToggle,
2877
+ PageBody,
2878
+ Tbody,
2879
+ Td,
2880
+ Th,
2881
+ Thead,
2882
+ Tr,
2883
+ useEntityPagination,
2884
+ useEntityParams
2885
+ } from "@mesob/ui/components";
2886
+ import { IconKey as IconKey2, IconPlus, IconTrash } from "@tabler/icons-react";
2887
+ import { useQueryClient as useQueryClient2 } from "@tanstack/react-query";
2888
+ import { useMemo as useMemo4 } from "react";
2889
+ import { toast as toast9 } from "sonner";
2890
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
2891
+ var TABLE_COLUMN_COUNT = 4;
2892
+ function RolePermissionsPage({ roleId }) {
2893
+ const { hooks } = useApi();
2894
+ const qc = useQueryClient2();
2895
+ const { queryConfig, params, setParams } = useEntityParams({
2896
+ searchKey: "search",
2897
+ defaultSort: "application",
2898
+ defaultOrder: "asc"
2899
+ });
2900
+ const permissionsQuery = useMemo4(
2901
+ () => ({
2902
+ params: {
2903
+ path: { id: roleId },
2904
+ query: queryConfig.params.query
2905
+ }
2906
+ }),
2907
+ [queryConfig, roleId]
2908
+ );
2909
+ const { data, isPending, isFetching } = hooks.useQuery(
2910
+ "get",
2911
+ "/roles/{id}/permissions",
2912
+ permissionsQuery,
2913
+ { enabled: !!roleId }
2914
+ );
2915
+ const assignPermissions = hooks.useMutation(
2916
+ "post",
2917
+ "/roles/{id}/permissions",
2164
2918
  {
2165
- key: "description",
2166
- header: "Description",
2167
- cell: (permission) => /* @__PURE__ */ jsx15("p", { className: "text-sm text-muted-foreground max-w-xs truncate", children: getTranslation(permission.description, locale) })
2168
- },
2919
+ onSuccess: (result) => {
2920
+ qc.invalidateQueries({ queryKey: ["get", "/roles"] });
2921
+ qc.invalidateQueries({ queryKey: ["get", "/roles/{id}"] });
2922
+ qc.invalidateQueries({ queryKey: ["get", "/roles/{id}/permissions"] });
2923
+ toast9.success(
2924
+ result?.created ? `${result.created} permission(s) added` : "No changes"
2925
+ );
2926
+ },
2927
+ onError: () => {
2928
+ toast9.error("Failed to assign permissions");
2929
+ }
2930
+ }
2931
+ );
2932
+ const revokePermission = hooks.useMutation(
2933
+ "delete",
2934
+ "/roles/{id}/permissions/{permissionId}",
2169
2935
  {
2170
- key: "actions",
2171
- header: "Actions",
2172
- cell: (_permission) => /* @__PURE__ */ jsx15(Button8, { variant: "outline", size: "sm", children: "Edit" })
2936
+ onSuccess: () => {
2937
+ qc.invalidateQueries({ queryKey: ["get", "/roles"] });
2938
+ qc.invalidateQueries({ queryKey: ["get", "/roles/{id}"] });
2939
+ qc.invalidateQueries({
2940
+ queryKey: ["get", "/roles/{id}/permissions"]
2941
+ });
2942
+ toast9.success("Permission removed");
2943
+ },
2944
+ onError: () => {
2945
+ toast9.error("Failed to remove permission");
2946
+ }
2173
2947
  }
2174
- ];
2175
- if (error) {
2176
- return /* @__PURE__ */ jsx15("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx15("p", { className: "text-destructive", children: "Error loading permissions" }) });
2948
+ );
2949
+ const permissions = data?.permissions ?? [];
2950
+ const { total, pageCount } = useEntityPagination({
2951
+ items: permissions,
2952
+ total: data?.total,
2953
+ pageSize: params.pageSize
2954
+ });
2955
+ const isLoading = isPending || isFetching;
2956
+ const currentView = params.view || "table";
2957
+ if (!roleId) {
2958
+ return null;
2177
2959
  }
2178
- return /* @__PURE__ */ jsxs13("div", { className: "w-full p-6 space-y-4", children: [
2179
- /* @__PURE__ */ jsxs13("div", { className: "flex justify-between items-center", children: [
2180
- /* @__PURE__ */ jsxs13("div", { children: [
2181
- /* @__PURE__ */ jsx15("h1", { className: "text-3xl font-bold", children: "Permissions" }),
2182
- /* @__PURE__ */ jsx15("p", { className: "text-muted-foreground", children: "Manage system permissions" })
2183
- ] }),
2184
- /* @__PURE__ */ jsx15(Button8, { children: "Create Permission" })
2185
- ] }),
2186
- /* @__PURE__ */ jsx15(
2187
- DataTable,
2960
+ let content;
2961
+ if (isLoading) {
2962
+ content = /* @__PURE__ */ jsx22(
2963
+ EntityLoadingState,
2188
2964
  {
2189
- data: data?.permissions || [],
2190
- columns,
2191
- isLoading,
2192
- emptyMessage: "No permissions found"
2965
+ view: currentView,
2966
+ rowCount: params.pageSize,
2967
+ columnCount: TABLE_COLUMN_COUNT,
2968
+ cardCount: params.pageSize
2193
2969
  }
2194
- ),
2195
- data && "permissions" in data && data.permissions && data.permissions.length >= limit && /* @__PURE__ */ jsxs13("div", { className: "flex justify-between items-center", children: [
2196
- /* @__PURE__ */ jsx15(
2197
- Button8,
2970
+ );
2971
+ } else if (total === 0) {
2972
+ content = /* @__PURE__ */ jsx22(
2973
+ EntityEmptyState2,
2974
+ {
2975
+ icon: IconKey2,
2976
+ entityName: "permission",
2977
+ title: "No permissions assigned",
2978
+ description: "Assign permissions from the selector to grant access to this role."
2979
+ }
2980
+ );
2981
+ } else if (currentView === "table") {
2982
+ content = /* @__PURE__ */ jsxs18("div", { className: "space-y-4", children: [
2983
+ /* @__PURE__ */ jsxs18(DisplayTable, { withTableBorder: true, children: [
2984
+ /* @__PURE__ */ jsx22(Thead, { children: /* @__PURE__ */ jsxs18(Tr, { children: [
2985
+ /* @__PURE__ */ jsx22(Th, { children: "Permission" }),
2986
+ /* @__PURE__ */ jsx22(Th, { children: "Application" }),
2987
+ /* @__PURE__ */ jsx22(Th, { children: "Feature" }),
2988
+ /* @__PURE__ */ jsx22(Th, { className: "w-[60px]" })
2989
+ ] }) }),
2990
+ /* @__PURE__ */ jsx22(Tbody, { children: permissions.map((permission) => /* @__PURE__ */ jsxs18(Tr, { children: [
2991
+ /* @__PURE__ */ jsx22(Td, { children: /* @__PURE__ */ jsxs18("div", { className: "space-y-1", children: [
2992
+ /* @__PURE__ */ jsx22("p", { className: "font-medium", children: permission.activity }),
2993
+ /* @__PURE__ */ jsx22("p", { className: "font-mono text-xs text-muted-foreground", children: permission.id })
2994
+ ] }) }),
2995
+ /* @__PURE__ */ jsx22(Td, { children: /* @__PURE__ */ jsx22(Badge3, { variant: "secondary", children: permission.application }) }),
2996
+ /* @__PURE__ */ jsx22(Td, { children: /* @__PURE__ */ jsx22(Badge3, { variant: "outline", children: permission.feature }) }),
2997
+ /* @__PURE__ */ jsx22(Td, { children: /* @__PURE__ */ jsx22(
2998
+ DeleteConfirmButton,
2999
+ {
3000
+ entityName: "permission",
3001
+ onConfirm: () => revokePermission.mutate({
3002
+ params: {
3003
+ path: { id: roleId, permissionId: permission.id }
3004
+ }
3005
+ }),
3006
+ triggerClassName: "size-8 text-destructive hover:text-destructive"
3007
+ }
3008
+ ) })
3009
+ ] }, permission.id)) })
3010
+ ] }),
3011
+ /* @__PURE__ */ jsx22(
3012
+ DataTablePagination,
2198
3013
  {
2199
- variant: "outline",
2200
- disabled: page === 1,
2201
- onClick: () => setPage(page - 1),
2202
- children: "Previous"
3014
+ pageIndex: params.page - 1,
3015
+ pageSize: params.pageSize,
3016
+ pageCount,
3017
+ totalRows: total,
3018
+ onPageChange: (page) => setParams({ page: page + 1 }),
3019
+ onPageSizeChange: (pageSize) => setParams({ pageSize, page: 1 })
2203
3020
  }
2204
- ),
2205
- /* @__PURE__ */ jsxs13("span", { className: "text-sm text-muted-foreground", children: [
2206
- "Page ",
2207
- page
2208
- ] }),
2209
- /* @__PURE__ */ jsx15(Button8, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
2210
- ] })
3021
+ )
3022
+ ] });
3023
+ } else {
3024
+ content = /* @__PURE__ */ jsxs18("div", { className: "space-y-4", children: [
3025
+ /* @__PURE__ */ jsx22("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3", children: permissions.map((permission) => /* @__PURE__ */ jsx22(
3026
+ "div",
3027
+ {
3028
+ className: "rounded-xl border border-border/60 bg-card p-4 shadow-sm",
3029
+ children: /* @__PURE__ */ jsxs18("div", { className: "flex items-start justify-between gap-3", children: [
3030
+ /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
3031
+ /* @__PURE__ */ jsx22("p", { className: "font-semibold", children: permission.activity }),
3032
+ /* @__PURE__ */ jsxs18("div", { className: "flex flex-wrap gap-2", children: [
3033
+ /* @__PURE__ */ jsx22(Badge3, { variant: "secondary", children: permission.application }),
3034
+ /* @__PURE__ */ jsx22(Badge3, { variant: "outline", children: permission.feature })
3035
+ ] }),
3036
+ /* @__PURE__ */ jsx22("p", { className: "font-mono text-xs text-muted-foreground", children: permission.id })
3037
+ ] }),
3038
+ /* @__PURE__ */ jsx22(
3039
+ Button9,
3040
+ {
3041
+ type: "button",
3042
+ variant: "ghost",
3043
+ size: "icon",
3044
+ onClick: () => revokePermission.mutate({
3045
+ params: {
3046
+ path: { id: roleId, permissionId: permission.id }
3047
+ }
3048
+ }),
3049
+ disabled: revokePermission.isPending,
3050
+ children: /* @__PURE__ */ jsx22(IconTrash, { className: "h-4 w-4" })
3051
+ }
3052
+ )
3053
+ ] })
3054
+ },
3055
+ permission.id
3056
+ )) }),
3057
+ /* @__PURE__ */ jsx22(
3058
+ DataTablePagination,
3059
+ {
3060
+ pageIndex: params.page - 1,
3061
+ pageSize: params.pageSize,
3062
+ pageCount,
3063
+ totalRows: total,
3064
+ onPageChange: (page) => setParams({ page: page + 1 }),
3065
+ onPageSizeChange: (pageSize) => setParams({ pageSize, page: 1 })
3066
+ }
3067
+ )
3068
+ ] });
3069
+ }
3070
+ return /* @__PURE__ */ jsxs18(PageBody, { className: "px-0 pb-6", children: [
3071
+ /* @__PURE__ */ jsx22(
3072
+ EntityHeader,
3073
+ {
3074
+ icon: /* @__PURE__ */ jsx22(IconKey2, { className: "h-5 w-5" }),
3075
+ title: "Role permissions",
3076
+ actions: /* @__PURE__ */ jsx22(
3077
+ PermissionSelector,
3078
+ {
3079
+ trigger: /* @__PURE__ */ jsxs18(Button9, { size: "sm", loading: assignPermissions.isPending, children: [
3080
+ /* @__PURE__ */ jsx22(IconPlus, { className: "h-4 w-4" }),
3081
+ "Add permissions"
3082
+ ] }),
3083
+ onSelect: (selectedPermissions) => {
3084
+ if (!selectedPermissions.length) {
3085
+ return;
3086
+ }
3087
+ assignPermissions.mutate({
3088
+ params: { path: { id: roleId } },
3089
+ body: {
3090
+ permissionIds: selectedPermissions.map(
3091
+ (permission) => permission.id
3092
+ )
3093
+ }
3094
+ });
3095
+ },
3096
+ excludeIds: permissions.map((permission) => permission.id)
3097
+ }
3098
+ ),
3099
+ search: /* @__PURE__ */ jsx22(
3100
+ EntitySearch,
3101
+ {
3102
+ paramKey: "search",
3103
+ placeholder: "Search assigned permissions..."
3104
+ }
3105
+ ),
3106
+ filter: /* @__PURE__ */ jsx22(
3107
+ EntityFilter,
3108
+ {
3109
+ options: [
3110
+ { label: "All", value: "" },
3111
+ { label: "Application", value: "application" },
3112
+ { label: "Feature", value: "feature" },
3113
+ { label: "Activity", value: "activity" }
3114
+ ],
3115
+ placeholder: "Search field"
3116
+ }
3117
+ ),
3118
+ sort: /* @__PURE__ */ jsx22(
3119
+ EntitySort,
3120
+ {
3121
+ defaultSort: "application",
3122
+ defaultOrder: "asc",
3123
+ options: [
3124
+ { label: "ID", value: "id" },
3125
+ { label: "Application", value: "application" },
3126
+ { label: "Feature", value: "feature" },
3127
+ { label: "Activity", value: "activity" }
3128
+ ]
3129
+ }
3130
+ ),
3131
+ view: /* @__PURE__ */ jsx22(EntityViewToggle, { views: ["table", "card"] })
3132
+ }
3133
+ ),
3134
+ content
2211
3135
  ] });
2212
3136
  }
2213
3137
 
2214
3138
  // src/components/iam/roles.tsx
2215
- import { Badge as Badge2, Button as Button9 } from "@mesob/ui/components";
2216
- import { useLocale as useLocale2 } from "next-intl";
2217
- import { useState as useState10 } from "react";
2218
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
2219
- function getTranslation2(value, locale) {
3139
+ import { Badge as Badge4, Button as Button10 } from "@mesob/ui/components";
3140
+ import { useLocale } from "next-intl";
3141
+ import { useState as useState11 } from "react";
3142
+ import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
3143
+ function getTranslation(value, locale) {
2220
3144
  if (!value) {
2221
3145
  return "";
2222
3146
  }
@@ -2230,8 +3154,8 @@ function getTranslation2(value, locale) {
2230
3154
  }
2231
3155
  function Roles() {
2232
3156
  const { hooks } = useApi();
2233
- const locale = useLocale2();
2234
- const [page, setPage] = useState10(1);
3157
+ const locale = useLocale();
3158
+ const [page, setPage] = useState11(1);
2235
3159
  const limit = 20;
2236
3160
  const { data, isLoading, error } = hooks.useQuery("get", "/roles", {
2237
3161
  params: {
@@ -2245,42 +3169,45 @@ function Roles() {
2245
3169
  {
2246
3170
  key: "name",
2247
3171
  header: "Role",
2248
- cell: (role) => /* @__PURE__ */ jsxs14("div", { children: [
2249
- /* @__PURE__ */ jsx16("p", { className: "font-medium", children: getTranslation2(role.name, locale) }),
2250
- /* @__PURE__ */ jsx16(Badge2, { variant: "outline", className: "mt-1", children: role.code })
3172
+ cell: (role) => /* @__PURE__ */ jsxs19("div", { children: [
3173
+ /* @__PURE__ */ jsx23("p", { className: "font-medium", children: getTranslation(role.name, locale) }),
3174
+ /* @__PURE__ */ jsx23(Badge4, { variant: "outline", className: "mt-1", children: role.code })
2251
3175
  ] })
2252
3176
  },
2253
3177
  {
2254
- key: "description",
2255
- header: "Description",
2256
- cell: (role) => /* @__PURE__ */ jsx16("p", { className: "text-sm text-muted-foreground", children: getTranslation2(role.description, locale) })
3178
+ key: "access",
3179
+ header: "Access",
3180
+ cell: (role) => /* @__PURE__ */ jsxs19("div", { className: "flex flex-wrap gap-2", children: [
3181
+ role.isSystem ? /* @__PURE__ */ jsx23(Badge4, { children: "System" }) : null,
3182
+ /* @__PURE__ */ jsxs19(Badge4, { variant: "secondary", children: [
3183
+ role.permissionCount ?? 0,
3184
+ " permissions"
3185
+ ] })
3186
+ ] })
2257
3187
  },
2258
3188
  {
2259
3189
  key: "createdAt",
2260
3190
  header: "Created",
2261
- cell: (role) => /* @__PURE__ */ jsx16("p", { className: "text-sm", children: new Date(role.createdAt).toLocaleDateString() })
3191
+ cell: (role) => /* @__PURE__ */ jsx23("p", { className: "text-sm", children: new Date(role.createdAt).toLocaleDateString() })
2262
3192
  },
2263
3193
  {
2264
3194
  key: "actions",
2265
3195
  header: "Actions",
2266
- cell: (_role) => /* @__PURE__ */ jsxs14("div", { className: "flex gap-2", children: [
2267
- /* @__PURE__ */ jsx16(Button9, { variant: "outline", size: "sm", children: "Permissions" }),
2268
- /* @__PURE__ */ jsx16(Button9, { variant: "outline", size: "sm", children: "Edit" })
2269
- ] })
3196
+ cell: (_role) => /* @__PURE__ */ jsx23("div", { className: "flex gap-2", children: /* @__PURE__ */ jsx23(Button10, { variant: "outline", size: "sm", children: "Edit" }) })
2270
3197
  }
2271
3198
  ];
2272
3199
  if (error) {
2273
- return /* @__PURE__ */ jsx16("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx16("p", { className: "text-destructive", children: "Error loading roles" }) });
3200
+ return /* @__PURE__ */ jsx23("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx23("p", { className: "text-destructive", children: "Error loading roles" }) });
2274
3201
  }
2275
- return /* @__PURE__ */ jsxs14("div", { className: "w-full p-6 space-y-4", children: [
2276
- /* @__PURE__ */ jsxs14("div", { className: "flex justify-between items-center", children: [
2277
- /* @__PURE__ */ jsxs14("div", { children: [
2278
- /* @__PURE__ */ jsx16("h1", { className: "text-3xl font-bold", children: "Roles" }),
2279
- /* @__PURE__ */ jsx16("p", { className: "text-muted-foreground", children: "Manage user roles" })
3202
+ return /* @__PURE__ */ jsxs19("div", { className: "w-full p-6 space-y-4", children: [
3203
+ /* @__PURE__ */ jsxs19("div", { className: "flex justify-between items-center", children: [
3204
+ /* @__PURE__ */ jsxs19("div", { children: [
3205
+ /* @__PURE__ */ jsx23("h1", { className: "text-3xl font-bold", children: "Roles" }),
3206
+ /* @__PURE__ */ jsx23("p", { className: "text-muted-foreground", children: "Manage roles and assigned permissions" })
2280
3207
  ] }),
2281
- /* @__PURE__ */ jsx16(Button9, { children: "Create Role" })
3208
+ /* @__PURE__ */ jsx23(Button10, { children: "Create Role" })
2282
3209
  ] }),
2283
- /* @__PURE__ */ jsx16(
3210
+ /* @__PURE__ */ jsx23(
2284
3211
  DataTable,
2285
3212
  {
2286
3213
  data: data?.roles || [],
@@ -2289,32 +3216,39 @@ function Roles() {
2289
3216
  emptyMessage: "No roles found"
2290
3217
  }
2291
3218
  ),
2292
- data && "roles" in data && data.roles && data.roles.length >= limit && /* @__PURE__ */ jsxs14("div", { className: "flex justify-between items-center", children: [
2293
- /* @__PURE__ */ jsx16(
2294
- Button9,
3219
+ data && "roles" in data && data.roles && data.roles.length >= limit && /* @__PURE__ */ jsxs19("div", { className: "flex justify-between items-center", children: [
3220
+ /* @__PURE__ */ jsx23(
3221
+ Button10,
2295
3222
  {
2296
3223
  variant: "outline",
2297
3224
  disabled: page === 1,
2298
- onClick: () => setPage(page - 1),
3225
+ onClick: () => setPage((prev) => prev - 1),
2299
3226
  children: "Previous"
2300
3227
  }
2301
3228
  ),
2302
- /* @__PURE__ */ jsxs14("span", { className: "text-sm text-muted-foreground", children: [
3229
+ /* @__PURE__ */ jsxs19("span", { className: "text-sm text-muted-foreground", children: [
2303
3230
  "Page ",
2304
3231
  page
2305
3232
  ] }),
2306
- /* @__PURE__ */ jsx16(Button9, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
3233
+ /* @__PURE__ */ jsx23(
3234
+ Button10,
3235
+ {
3236
+ variant: "outline",
3237
+ onClick: () => setPage((prev) => prev + 1),
3238
+ children: "Next"
3239
+ }
3240
+ )
2307
3241
  ] })
2308
3242
  ] });
2309
3243
  }
2310
3244
 
2311
3245
  // src/components/iam/sessions.tsx
2312
- import { Button as Button10 } from "@mesob/ui/components";
2313
- import { useState as useState11 } from "react";
2314
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
3246
+ import { Button as Button11 } from "@mesob/ui/components";
3247
+ import { useState as useState12 } from "react";
3248
+ import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
2315
3249
  function Sessions() {
2316
3250
  const { hooks } = useApi();
2317
- const [selectedSessionId] = useState11(null);
3251
+ const [selectedSessionId] = useState12(null);
2318
3252
  const { data, isLoading, error, refetch } = hooks.useQuery(
2319
3253
  "get",
2320
3254
  "/sessions"
@@ -2340,31 +3274,31 @@ function Sessions() {
2340
3274
  {
2341
3275
  key: "createdAt",
2342
3276
  header: "Created",
2343
- cell: (session) => /* @__PURE__ */ jsxs15("div", { children: [
2344
- /* @__PURE__ */ jsx17("p", { className: "text-sm font-medium", children: new Date(session.createdAt).toLocaleDateString() }),
2345
- /* @__PURE__ */ jsx17("p", { className: "text-xs text-muted-foreground", children: new Date(session.createdAt).toLocaleTimeString() })
3277
+ cell: (session) => /* @__PURE__ */ jsxs20("div", { children: [
3278
+ /* @__PURE__ */ jsx24("p", { className: "text-sm font-medium", children: new Date(session.createdAt).toLocaleDateString() }),
3279
+ /* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: new Date(session.createdAt).toLocaleTimeString() })
2346
3280
  ] })
2347
3281
  },
2348
3282
  {
2349
3283
  key: "expiresAt",
2350
3284
  header: "Expires",
2351
- cell: (session) => /* @__PURE__ */ jsx17("p", { className: "text-sm", children: new Date(session.expiresAt).toLocaleDateString() })
3285
+ cell: (session) => /* @__PURE__ */ jsx24("p", { className: "text-sm", children: new Date(session.expiresAt).toLocaleDateString() })
2352
3286
  },
2353
3287
  {
2354
3288
  key: "userAgent",
2355
3289
  header: "Device",
2356
- cell: (session) => /* @__PURE__ */ jsx17("p", { className: "text-sm truncate max-w-xs", children: session.userAgent || "Unknown" })
3290
+ cell: (session) => /* @__PURE__ */ jsx24("p", { className: "text-sm truncate max-w-xs", children: session.userAgent || "Unknown" })
2357
3291
  },
2358
3292
  {
2359
3293
  key: "ip",
2360
3294
  header: "IP Address",
2361
- cell: (session) => /* @__PURE__ */ jsx17("p", { className: "text-sm font-mono", children: session.ip || "Unknown" })
3295
+ cell: (session) => /* @__PURE__ */ jsx24("p", { className: "text-sm font-mono", children: session.ip || "Unknown" })
2362
3296
  },
2363
3297
  {
2364
3298
  key: "actions",
2365
3299
  header: "Actions",
2366
- cell: (session) => /* @__PURE__ */ jsx17(
2367
- Button10,
3300
+ cell: (session) => /* @__PURE__ */ jsx24(
3301
+ Button11,
2368
3302
  {
2369
3303
  variant: "destructive",
2370
3304
  size: "sm",
@@ -2376,14 +3310,14 @@ function Sessions() {
2376
3310
  }
2377
3311
  ];
2378
3312
  if (error) {
2379
- return /* @__PURE__ */ jsx17("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx17("p", { className: "text-destructive", children: "Error loading sessions" }) });
3313
+ return /* @__PURE__ */ jsx24("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx24("p", { className: "text-destructive", children: "Error loading sessions" }) });
2380
3314
  }
2381
- return /* @__PURE__ */ jsxs15("div", { className: "w-full p-6 space-y-4", children: [
2382
- /* @__PURE__ */ jsxs15("div", { children: [
2383
- /* @__PURE__ */ jsx17("h1", { className: "text-3xl font-bold", children: "Sessions" }),
2384
- /* @__PURE__ */ jsx17("p", { className: "text-muted-foreground", children: "View and manage active sessions" })
3315
+ return /* @__PURE__ */ jsxs20("div", { className: "w-full p-6 space-y-4", children: [
3316
+ /* @__PURE__ */ jsxs20("div", { children: [
3317
+ /* @__PURE__ */ jsx24("h1", { className: "text-3xl font-bold", children: "Sessions" }),
3318
+ /* @__PURE__ */ jsx24("p", { className: "text-muted-foreground", children: "View and manage active sessions" })
2385
3319
  ] }),
2386
- /* @__PURE__ */ jsx17(
3320
+ /* @__PURE__ */ jsx24(
2387
3321
  DataTable,
2388
3322
  {
2389
3323
  data: data?.sessions || [],
@@ -2396,12 +3330,12 @@ function Sessions() {
2396
3330
  }
2397
3331
 
2398
3332
  // src/components/iam/tenants.tsx
2399
- import { Badge as Badge3, Button as Button11 } from "@mesob/ui/components";
2400
- import { useState as useState12 } from "react";
2401
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
3333
+ import { Badge as Badge5, Button as Button12 } from "@mesob/ui/components";
3334
+ import { useState as useState13 } from "react";
3335
+ import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
2402
3336
  function Tenants() {
2403
3337
  const { hooks } = useApi();
2404
- const [page, setPage] = useState12(1);
3338
+ const [page, setPage] = useState13(1);
2405
3339
  const limit = 20;
2406
3340
  const { data, isLoading, error } = hooks.useQuery("get", "/tenants", {
2407
3341
  params: {
@@ -2415,9 +3349,9 @@ function Tenants() {
2415
3349
  {
2416
3350
  key: "name",
2417
3351
  header: "Tenant",
2418
- cell: (tenant) => /* @__PURE__ */ jsxs16("div", { children: [
2419
- /* @__PURE__ */ jsx18("p", { className: "font-medium", children: tenant.name }),
2420
- /* @__PURE__ */ jsxs16("p", { className: "text-sm text-muted-foreground", children: [
3352
+ cell: (tenant) => /* @__PURE__ */ jsxs21("div", { children: [
3353
+ /* @__PURE__ */ jsx25("p", { className: "font-medium", children: tenant.name }),
3354
+ /* @__PURE__ */ jsxs21("p", { className: "text-sm text-muted-foreground", children: [
2421
3355
  "/",
2422
3356
  tenant.slug
2423
3357
  ] })
@@ -2426,34 +3360,34 @@ function Tenants() {
2426
3360
  {
2427
3361
  key: "status",
2428
3362
  header: "Status",
2429
- cell: (tenant) => /* @__PURE__ */ jsx18(Badge3, { variant: tenant.status === "active" ? "default" : "secondary", children: tenant.status })
3363
+ cell: (tenant) => /* @__PURE__ */ jsx25(Badge5, { variant: tenant.status === "active" ? "default" : "secondary", children: tenant.status })
2430
3364
  },
2431
3365
  {
2432
3366
  key: "createdAt",
2433
3367
  header: "Created",
2434
- cell: (tenant) => /* @__PURE__ */ jsx18("p", { className: "text-sm", children: new Date(tenant.createdAt).toLocaleDateString() })
3368
+ cell: (tenant) => /* @__PURE__ */ jsx25("p", { className: "text-sm", children: new Date(tenant.createdAt).toLocaleDateString() })
2435
3369
  },
2436
3370
  {
2437
3371
  key: "actions",
2438
3372
  header: "Actions",
2439
- cell: (_tenant) => /* @__PURE__ */ jsxs16("div", { className: "flex gap-2", children: [
2440
- /* @__PURE__ */ jsx18(Button11, { variant: "outline", size: "sm", children: "Domains" }),
2441
- /* @__PURE__ */ jsx18(Button11, { variant: "outline", size: "sm", children: "Edit" })
3373
+ cell: (_tenant) => /* @__PURE__ */ jsxs21("div", { className: "flex gap-2", children: [
3374
+ /* @__PURE__ */ jsx25(Button12, { variant: "outline", size: "sm", children: "Domains" }),
3375
+ /* @__PURE__ */ jsx25(Button12, { variant: "outline", size: "sm", children: "Edit" })
2442
3376
  ] })
2443
3377
  }
2444
3378
  ];
2445
3379
  if (error) {
2446
- return /* @__PURE__ */ jsx18("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx18("p", { className: "text-destructive", children: "Error loading tenants" }) });
3380
+ return /* @__PURE__ */ jsx25("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx25("p", { className: "text-destructive", children: "Error loading tenants" }) });
2447
3381
  }
2448
- return /* @__PURE__ */ jsxs16("div", { className: "w-full p-6 space-y-4", children: [
2449
- /* @__PURE__ */ jsxs16("div", { className: "flex justify-between items-center", children: [
2450
- /* @__PURE__ */ jsxs16("div", { children: [
2451
- /* @__PURE__ */ jsx18("h1", { className: "text-3xl font-bold", children: "Tenants" }),
2452
- /* @__PURE__ */ jsx18("p", { className: "text-muted-foreground", children: "Manage tenant organizations" })
3382
+ return /* @__PURE__ */ jsxs21("div", { className: "w-full p-6 space-y-4", children: [
3383
+ /* @__PURE__ */ jsxs21("div", { className: "flex justify-between items-center", children: [
3384
+ /* @__PURE__ */ jsxs21("div", { children: [
3385
+ /* @__PURE__ */ jsx25("h1", { className: "text-3xl font-bold", children: "Tenants" }),
3386
+ /* @__PURE__ */ jsx25("p", { className: "text-muted-foreground", children: "Manage tenant organizations" })
2453
3387
  ] }),
2454
- /* @__PURE__ */ jsx18(Button11, { children: "Create Tenant" })
3388
+ /* @__PURE__ */ jsx25(Button12, { children: "Create Tenant" })
2455
3389
  ] }),
2456
- /* @__PURE__ */ jsx18(
3390
+ /* @__PURE__ */ jsx25(
2457
3391
  DataTable,
2458
3392
  {
2459
3393
  data: data?.tenants || [],
@@ -2462,32 +3396,39 @@ function Tenants() {
2462
3396
  emptyMessage: "No tenants found"
2463
3397
  }
2464
3398
  ),
2465
- data && "tenants" in data && data.tenants && data.tenants.length >= limit && /* @__PURE__ */ jsxs16("div", { className: "flex justify-between items-center", children: [
2466
- /* @__PURE__ */ jsx18(
2467
- Button11,
3399
+ data && "tenants" in data && data.tenants && data.tenants.length >= limit && /* @__PURE__ */ jsxs21("div", { className: "flex justify-between items-center", children: [
3400
+ /* @__PURE__ */ jsx25(
3401
+ Button12,
2468
3402
  {
2469
3403
  variant: "outline",
2470
3404
  disabled: page === 1,
2471
- onClick: () => setPage(page - 1),
3405
+ onClick: () => setPage((prev) => prev - 1),
2472
3406
  children: "Previous"
2473
3407
  }
2474
3408
  ),
2475
- /* @__PURE__ */ jsxs16("span", { className: "text-sm text-muted-foreground", children: [
3409
+ /* @__PURE__ */ jsxs21("span", { className: "text-sm text-muted-foreground", children: [
2476
3410
  "Page ",
2477
3411
  page
2478
3412
  ] }),
2479
- /* @__PURE__ */ jsx18(Button11, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
3413
+ /* @__PURE__ */ jsx25(
3414
+ Button12,
3415
+ {
3416
+ variant: "outline",
3417
+ onClick: () => setPage((prev) => prev + 1),
3418
+ children: "Next"
3419
+ }
3420
+ )
2480
3421
  ] })
2481
3422
  ] });
2482
3423
  }
2483
3424
 
2484
3425
  // src/components/iam/users.tsx
2485
- import { Badge as Badge4, Button as Button12 } from "@mesob/ui/components";
2486
- import { useState as useState13 } from "react";
2487
- import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
3426
+ import { Badge as Badge6, Button as Button13 } from "@mesob/ui/components";
3427
+ import { useState as useState14 } from "react";
3428
+ import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
2488
3429
  function Users() {
2489
3430
  const { hooks } = useApi();
2490
- const [page, setPage] = useState13(1);
3431
+ const [page, setPage] = useState14(1);
2491
3432
  const limit = 20;
2492
3433
  const { data, isLoading, error } = hooks.useQuery("get", "/users", {
2493
3434
  params: {
@@ -2501,54 +3442,48 @@ function Users() {
2501
3442
  {
2502
3443
  key: "fullName",
2503
3444
  header: "Name",
2504
- cell: (user) => /* @__PURE__ */ jsxs17("div", { children: [
2505
- /* @__PURE__ */ jsx19("p", { className: "font-medium", children: user.fullName }),
2506
- /* @__PURE__ */ jsxs17("p", { className: "text-sm text-muted-foreground", children: [
2507
- "@",
2508
- user.handle
2509
- ] })
2510
- ] })
3445
+ cell: (user) => /* @__PURE__ */ jsx26("div", { children: /* @__PURE__ */ jsx26("p", { className: "font-medium", children: user.fullName }) })
2511
3446
  },
2512
3447
  {
2513
3448
  key: "contact",
2514
3449
  header: "Contact",
2515
- cell: (user) => /* @__PURE__ */ jsxs17("div", { className: "space-y-1", children: [
2516
- user.email && /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
2517
- /* @__PURE__ */ jsx19("p", { className: "text-sm", children: user.email }),
2518
- user.emailVerified && /* @__PURE__ */ jsx19(Badge4, { variant: "outline", className: "text-xs", children: "Verified" })
3450
+ cell: (user) => /* @__PURE__ */ jsxs22("div", { className: "space-y-1", children: [
3451
+ user.email && /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-2", children: [
3452
+ /* @__PURE__ */ jsx26("p", { className: "text-sm", children: user.email }),
3453
+ user.emailVerified && /* @__PURE__ */ jsx26(Badge6, { variant: "outline", className: "text-xs", children: "Verified" })
2519
3454
  ] }),
2520
- user.phone && /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
2521
- /* @__PURE__ */ jsx19("p", { className: "text-sm", children: user.phone }),
2522
- user.phoneVerified && /* @__PURE__ */ jsx19(Badge4, { variant: "outline", className: "text-xs", children: "Verified" })
3455
+ user.phone && /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-2", children: [
3456
+ /* @__PURE__ */ jsx26("p", { className: "text-sm", children: user.phone }),
3457
+ user.phoneVerified && /* @__PURE__ */ jsx26(Badge6, { variant: "outline", className: "text-xs", children: "Verified" })
2523
3458
  ] })
2524
3459
  ] })
2525
3460
  },
2526
3461
  {
2527
3462
  key: "lastSignIn",
2528
3463
  header: "Last Sign In",
2529
- cell: (user) => /* @__PURE__ */ jsx19("p", { className: "text-sm", children: user.lastSignInAt ? new Date(user.lastSignInAt).toLocaleDateString() : "Never" })
3464
+ cell: (user) => /* @__PURE__ */ jsx26("p", { className: "text-sm", children: user.lastSignInAt ? new Date(user.lastSignInAt).toLocaleDateString() : "Never" })
2530
3465
  },
2531
3466
  {
2532
3467
  key: "actions",
2533
3468
  header: "Actions",
2534
- cell: (_user) => /* @__PURE__ */ jsxs17("div", { className: "flex gap-2", children: [
2535
- /* @__PURE__ */ jsx19(Button12, { variant: "outline", size: "sm", children: "View" }),
2536
- /* @__PURE__ */ jsx19(Button12, { variant: "outline", size: "sm", children: "Edit" })
3469
+ cell: (_user) => /* @__PURE__ */ jsxs22("div", { className: "flex gap-2", children: [
3470
+ /* @__PURE__ */ jsx26(Button13, { variant: "outline", size: "sm", children: "View" }),
3471
+ /* @__PURE__ */ jsx26(Button13, { variant: "outline", size: "sm", children: "Edit" })
2537
3472
  ] })
2538
3473
  }
2539
3474
  ];
2540
3475
  if (error) {
2541
- return /* @__PURE__ */ jsx19("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx19("p", { className: "text-destructive", children: "Error loading users" }) });
3476
+ return /* @__PURE__ */ jsx26("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx26("p", { className: "text-destructive", children: "Error loading users" }) });
2542
3477
  }
2543
- return /* @__PURE__ */ jsxs17("div", { className: "w-full p-6 space-y-4", children: [
2544
- /* @__PURE__ */ jsxs17("div", { className: "flex justify-between items-center", children: [
2545
- /* @__PURE__ */ jsxs17("div", { children: [
2546
- /* @__PURE__ */ jsx19("h1", { className: "text-3xl font-bold", children: "Users" }),
2547
- /* @__PURE__ */ jsx19("p", { className: "text-muted-foreground", children: "Manage user accounts" })
3478
+ return /* @__PURE__ */ jsxs22("div", { className: "w-full p-6 space-y-4", children: [
3479
+ /* @__PURE__ */ jsxs22("div", { className: "flex justify-between items-center", children: [
3480
+ /* @__PURE__ */ jsxs22("div", { children: [
3481
+ /* @__PURE__ */ jsx26("h1", { className: "text-3xl font-bold", children: "Users" }),
3482
+ /* @__PURE__ */ jsx26("p", { className: "text-muted-foreground", children: "Manage user accounts" })
2548
3483
  ] }),
2549
- /* @__PURE__ */ jsx19(Button12, { children: "Create User" })
3484
+ /* @__PURE__ */ jsx26(Button13, { children: "Create User" })
2550
3485
  ] }),
2551
- /* @__PURE__ */ jsx19(
3486
+ /* @__PURE__ */ jsx26(
2552
3487
  DataTable,
2553
3488
  {
2554
3489
  data: data?.users || [],
@@ -2557,76 +3492,179 @@ function Users() {
2557
3492
  emptyMessage: "No users found"
2558
3493
  }
2559
3494
  ),
2560
- data && "users" in data && data.users && data.users.length >= limit && /* @__PURE__ */ jsxs17("div", { className: "flex justify-between items-center", children: [
2561
- /* @__PURE__ */ jsx19(
2562
- Button12,
3495
+ data && "users" in data && data.users && data.users.length >= limit && /* @__PURE__ */ jsxs22("div", { className: "flex justify-between items-center", children: [
3496
+ /* @__PURE__ */ jsx26(
3497
+ Button13,
2563
3498
  {
2564
3499
  variant: "outline",
2565
3500
  disabled: page === 1,
2566
- onClick: () => setPage(page - 1),
3501
+ onClick: () => setPage((prev) => prev - 1),
2567
3502
  children: "Previous"
2568
3503
  }
2569
3504
  ),
2570
- /* @__PURE__ */ jsxs17("span", { className: "text-sm text-muted-foreground", children: [
3505
+ /* @__PURE__ */ jsxs22("span", { className: "text-sm text-muted-foreground", children: [
2571
3506
  "Page ",
2572
3507
  page
2573
3508
  ] }),
2574
- /* @__PURE__ */ jsx19(Button12, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
3509
+ /* @__PURE__ */ jsx26(
3510
+ Button13,
3511
+ {
3512
+ variant: "outline",
3513
+ onClick: () => setPage((prev) => prev + 1),
3514
+ children: "Next"
3515
+ }
3516
+ )
2575
3517
  ] })
2576
3518
  ] });
2577
3519
  }
2578
3520
 
2579
3521
  // src/components/profile/account.tsx
2580
- import { Separator } from "@mesob/ui/components";
2581
- import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
3522
+ import { Badge as Badge8, Card as Card2, CardContent, Separator } from "@mesob/ui/components";
3523
+
3524
+ // src/components/profile/change-profile.tsx
3525
+ import {
3526
+ Avatar,
3527
+ AvatarFallback,
3528
+ AvatarImage,
3529
+ Badge as Badge7,
3530
+ Button as Button14
3531
+ } from "@mesob/ui/components";
3532
+ import { useState as useState15 } from "react";
3533
+ import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
3534
+ var ChangeProfile = ({ user }) => {
3535
+ const [isEditing, setIsEditing] = useState15(false);
3536
+ const initials = user.fullName?.split(" ").map((part) => part[0]).join("").toUpperCase().slice(0, 2) || "U";
3537
+ return /* @__PURE__ */ jsxs23("div", { className: "w-full rounded-[1.5rem] border border-border/60 bg-background/80 p-5 shadow-sm backdrop-blur", children: [
3538
+ /* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-4 md:flex-row md:items-center md:justify-between", children: [
3539
+ /* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-4", children: [
3540
+ /* @__PURE__ */ jsxs23(Avatar, { className: "h-14 w-14 ring-4 ring-primary/10", children: [
3541
+ /* @__PURE__ */ jsx27(AvatarImage, { src: user.image || "", alt: user.fullName || "" }),
3542
+ /* @__PURE__ */ jsx27(AvatarFallback, { children: initials })
3543
+ ] }),
3544
+ /* @__PURE__ */ jsxs23("div", { className: "space-y-1", children: [
3545
+ /* @__PURE__ */ jsx27("div", { className: "text-base font-semibold", children: user.fullName }),
3546
+ /* @__PURE__ */ jsxs23("div", { className: "flex flex-wrap gap-2 text-xs text-muted-foreground", children: [
3547
+ /* @__PURE__ */ jsx27(Badge7, { variant: "outline", children: user.emailVerified ? "Email verified" : "Email unverified" }),
3548
+ /* @__PURE__ */ jsx27(Badge7, { variant: "outline", children: user.phoneVerified ? "Phone verified" : "Phone unverified" })
3549
+ ] })
3550
+ ] })
3551
+ ] }),
3552
+ /* @__PURE__ */ jsx27(
3553
+ Button14,
3554
+ {
3555
+ variant: "secondary",
3556
+ className: "rounded-full px-5 text-primary hover:text-primary/80",
3557
+ onClick: () => setIsEditing((v) => !v),
3558
+ children: isEditing ? "Hide editor" : "Update profile"
3559
+ }
3560
+ )
3561
+ ] }),
3562
+ isEditing && /* @__PURE__ */ jsx27("div", { className: "mt-4 rounded-2xl border border-dashed border-border bg-muted/30 px-4 py-3 text-sm text-muted-foreground", children: "Profile editing is not wired yet. Contact and password flows below are live." })
3563
+ ] });
3564
+ };
3565
+
3566
+ // src/components/profile/account.tsx
3567
+ import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
2582
3568
  function Account() {
2583
3569
  const { user, isAuthenticated } = useSession();
2584
3570
  if (!(isAuthenticated && user)) {
2585
- return /* @__PURE__ */ jsx20("div", { children: "Sign in required" });
3571
+ return /* @__PURE__ */ jsx28("div", { className: "rounded-[1.75rem] border border-dashed border-border bg-muted/30 p-8 text-sm text-muted-foreground", children: "Sign in required." });
2586
3572
  }
2587
- return /* @__PURE__ */ jsxs18("div", { className: "p-6 max-w-4xl", children: [
2588
- /* @__PURE__ */ jsxs18("div", { className: "mb-6", children: [
2589
- /* @__PURE__ */ jsx20("h2", { className: "text-lg font-semibold mb-4", children: "Profile details" }),
2590
- /* @__PURE__ */ jsx20(Separator, {})
2591
- ] }),
2592
- /* @__PURE__ */ jsxs18("div", { className: "space-y-6 transition-all duration-300 ease-in-out", children: [
2593
- /* @__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" }) }) }),
2594
- /* @__PURE__ */ jsx20(Separator, {}),
2595
- /* @__PURE__ */ jsxs18("div", { className: "flex flex-col md:flex-row gap-4 md:gap-12 py-2", children: [
2596
- /* @__PURE__ */ jsx20("div", { className: "w-full md:w-48 shrink-0", children: /* @__PURE__ */ jsx20("span", { className: "font-medium text-sm", children: "Email addresses" }) }),
2597
- /* @__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" }) }) })
2598
- ] }),
2599
- /* @__PURE__ */ jsx20(Separator, {}),
2600
- /* @__PURE__ */ jsxs18("div", { className: "flex flex-col md:flex-row gap-4 md:gap-12 py-2", children: [
2601
- /* @__PURE__ */ jsx20("div", { className: "w-full md:w-48 shrink-0", children: /* @__PURE__ */ jsx20("span", { className: "font-medium text-sm", children: "Phone numbers" }) }),
2602
- /* @__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" }) })
3573
+ const contactItems = [
3574
+ {
3575
+ label: "Email",
3576
+ value: user.email ?? "No email address",
3577
+ status: user.emailVerified ? "Verified" : "Needs verification"
3578
+ },
3579
+ {
3580
+ label: "Phone",
3581
+ value: user.phone ?? "No phone number",
3582
+ status: user.phoneVerified ? "Verified" : "Needs verification"
3583
+ }
3584
+ ];
3585
+ return /* @__PURE__ */ jsxs24("div", { className: "mx-auto flex w-full max-w-6xl flex-col gap-6", children: [
3586
+ /* @__PURE__ */ jsxs24("div", { className: "relative overflow-hidden rounded-[2rem] border border-border/60 bg-gradient-to-br from-background via-background to-primary/5 p-6 shadow-sm", children: [
3587
+ /* @__PURE__ */ jsx28("div", { className: "absolute inset-y-0 right-0 w-1/3 bg-[radial-gradient(circle_at_top,_hsl(var(--primary)/0.16),_transparent_60%)]" }),
3588
+ /* @__PURE__ */ jsxs24("div", { className: "relative flex flex-col gap-5", children: [
3589
+ /* @__PURE__ */ jsxs24("div", { className: "flex flex-wrap items-center gap-2", children: [
3590
+ /* @__PURE__ */ jsx28(Badge8, { variant: "outline", children: "Profile console" }),
3591
+ /* @__PURE__ */ jsx28(Badge8, { variant: "secondary", children: "Live session data" })
3592
+ ] }),
3593
+ /* @__PURE__ */ jsxs24("div", { className: "max-w-2xl space-y-2", children: [
3594
+ /* @__PURE__ */ jsx28("h2", { className: "text-2xl font-semibold tracking-tight", children: "Account details, contact state, and verification status." }),
3595
+ /* @__PURE__ */ jsx28("p", { className: "text-sm text-muted-foreground", children: "Keep the identity surface minimal here. Contact updates and sensitive changes stay in security." })
3596
+ ] }),
3597
+ /* @__PURE__ */ jsx28(ChangeProfile, { user })
2603
3598
  ] })
3599
+ ] }),
3600
+ /* @__PURE__ */ jsxs24("div", { className: "grid gap-4 lg:grid-cols-[1.5fr_0.9fr]", children: [
3601
+ /* @__PURE__ */ jsx28(Card2, { className: "rounded-[1.75rem] border-border/60 shadow-sm", children: /* @__PURE__ */ jsxs24(CardContent, { className: "space-y-5 p-6", children: [
3602
+ /* @__PURE__ */ jsxs24("div", { className: "space-y-1", children: [
3603
+ /* @__PURE__ */ jsx28("div", { className: "text-sm font-medium text-muted-foreground", children: "Contact channels" }),
3604
+ /* @__PURE__ */ jsx28("div", { className: "text-lg font-semibold", children: "Primary profile data" })
3605
+ ] }),
3606
+ /* @__PURE__ */ jsx28(Separator, {}),
3607
+ /* @__PURE__ */ jsx28("div", { className: "space-y-4", children: contactItems.map((item) => /* @__PURE__ */ jsxs24(
3608
+ "div",
3609
+ {
3610
+ className: "flex flex-col gap-3 rounded-2xl border border-border/60 bg-muted/20 p-4 md:flex-row md:items-center md:justify-between",
3611
+ children: [
3612
+ /* @__PURE__ */ jsxs24("div", { className: "space-y-1", children: [
3613
+ /* @__PURE__ */ jsx28("div", { className: "text-sm font-medium", children: item.label }),
3614
+ /* @__PURE__ */ jsx28("div", { className: "text-sm text-muted-foreground", children: item.value })
3615
+ ] }),
3616
+ /* @__PURE__ */ jsx28(Badge8, { variant: "outline", children: item.status })
3617
+ ]
3618
+ },
3619
+ item.label
3620
+ )) })
3621
+ ] }) }),
3622
+ /* @__PURE__ */ jsx28(Card2, { className: "rounded-[1.75rem] border-border/60 shadow-sm", children: /* @__PURE__ */ jsxs24(CardContent, { className: "space-y-5 p-6", children: [
3623
+ /* @__PURE__ */ jsxs24("div", { className: "space-y-1", children: [
3624
+ /* @__PURE__ */ jsx28("div", { className: "text-sm font-medium text-muted-foreground", children: "Snapshot" }),
3625
+ /* @__PURE__ */ jsx28("div", { className: "text-lg font-semibold", children: "Session-facing identity" })
3626
+ ] }),
3627
+ /* @__PURE__ */ jsx28(Separator, {}),
3628
+ /* @__PURE__ */ jsxs24("div", { className: "grid gap-3", children: [
3629
+ /* @__PURE__ */ jsxs24("div", { className: "rounded-2xl bg-primary/[0.06] p-4", children: [
3630
+ /* @__PURE__ */ jsx28("div", { className: "text-xs uppercase tracking-[0.18em] text-muted-foreground", children: "Full name" }),
3631
+ /* @__PURE__ */ jsx28("div", { className: "mt-2 text-base font-semibold", children: user.fullName })
3632
+ ] }),
3633
+ /* @__PURE__ */ jsxs24("div", { className: "rounded-2xl bg-muted/25 p-4", children: [
3634
+ /* @__PURE__ */ jsx28("div", { className: "text-xs uppercase tracking-[0.18em] text-muted-foreground", children: "Last sign in" }),
3635
+ /* @__PURE__ */ jsx28("div", { className: "mt-2 text-base font-semibold", children: user.lastSignInAt ? new Date(user.lastSignInAt).toLocaleString() : "No activity recorded" })
3636
+ ] })
3637
+ ] })
3638
+ ] }) })
2604
3639
  ] })
2605
3640
  ] });
2606
3641
  }
2607
3642
 
3643
+ // src/components/profile/security.tsx
3644
+ import { Badge as Badge9, Card as Card3, CardContent as CardContent2, Separator as Separator2 } from "@mesob/ui/components";
3645
+
2608
3646
  // src/components/profile/change-email-form.tsx
2609
3647
  import {
2610
- Button as Button14,
3648
+ Button as Button16,
2611
3649
  Collapsible,
2612
3650
  CollapsibleContent,
2613
3651
  CollapsibleTrigger
2614
3652
  } from "@mesob/ui/components";
2615
3653
  import { IconChevronDown } from "@tabler/icons-react";
2616
- import { useState as useState16 } from "react";
3654
+ import { useState as useState18 } from "react";
2617
3655
 
2618
3656
  // src/components/profile/request-change-email-form.tsx
2619
- import { zodResolver as zodResolver6 } from "@hookform/resolvers/zod";
2620
- import { Button as Button13, Input as Input5, Label, Spinner as Spinner5 } from "@mesob/ui/components";
2621
- import { IconEye as IconEye4, IconEyeOff as IconEyeOff4 } from "@tabler/icons-react";
2622
- import { useEffect as useEffect8, useState as useState14 } from "react";
2623
- import { useForm as useForm6 } from "react-hook-form";
2624
- import { toast as toast7 } from "sonner";
2625
- import { z as z6 } from "zod";
2626
- import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
2627
- var emailPasswordSchema = z6.object({
2628
- email: z6.string().email("Invalid email address"),
2629
- password: z6.string().min(8, "Password must be at least 8 characters").max(128, "Password too long")
3657
+ import { zodResolver as zodResolver8 } from "@hookform/resolvers/zod";
3658
+ import { Button as Button15, Input as Input7, Label, Spinner as Spinner2 } from "@mesob/ui/components";
3659
+ import { IconEye as IconEye5, IconEyeOff as IconEyeOff5 } from "@tabler/icons-react";
3660
+ import { useEffect as useEffect10, useState as useState16 } from "react";
3661
+ import { useForm as useForm8 } from "react-hook-form";
3662
+ import { toast as toast10 } from "sonner";
3663
+ import { z as z8 } from "zod";
3664
+ import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
3665
+ var emailPasswordSchema = z8.object({
3666
+ email: z8.string().email("Invalid email address"),
3667
+ password: z8.string().min(8, "Password must be at least 8 characters").max(128, "Password too long")
2630
3668
  });
2631
3669
  function isAuthError2(error) {
2632
3670
  return typeof error === "object" && error !== null && ("code" in error || "message" in error || "name" in error);
@@ -2681,9 +3719,9 @@ function RequestChangeEmailForm({
2681
3719
  }) {
2682
3720
  const { user } = useSession();
2683
3721
  const { hooks } = useApi();
2684
- const [isSubmitting, setIsSubmitting] = useState14(false);
2685
- const [isChecking, setIsChecking] = useState14(true);
2686
- const [showPassword, setShowPassword] = useState14(false);
3722
+ const [isSubmitting, setIsSubmitting] = useState16(false);
3723
+ const [isChecking, setIsChecking] = useState16(true);
3724
+ const [showPassword, setShowPassword] = useState16(false);
2687
3725
  const getPendingAccountChangeQuery = hooks.useQuery(
2688
3726
  "get",
2689
3727
  "/account-change/pending",
@@ -2696,8 +3734,8 @@ function RequestChangeEmailForm({
2696
3734
  "post",
2697
3735
  "/email/verification/request"
2698
3736
  );
2699
- const emailPasswordForm = useForm6({
2700
- resolver: zodResolver6(emailPasswordSchema),
3737
+ const emailPasswordForm = useForm8({
3738
+ resolver: zodResolver8(emailPasswordSchema),
2701
3739
  defaultValues: {
2702
3740
  email: "",
2703
3741
  password: ""
@@ -2710,7 +3748,7 @@ function RequestChangeEmailForm({
2710
3748
  setValue,
2711
3749
  formState: { errors }
2712
3750
  } = emailPasswordForm;
2713
- useEffect8(() => {
3751
+ useEffect10(() => {
2714
3752
  let active = true;
2715
3753
  const run = async () => {
2716
3754
  try {
@@ -2734,7 +3772,7 @@ function RequestChangeEmailForm({
2734
3772
  }
2735
3773
  setValue("email", accountChange.newEmail, { shouldValidate: true });
2736
3774
  if (verificationId) {
2737
- toast7.message("Resuming verification\u2026");
3775
+ toast10.message("Resuming verification\u2026");
2738
3776
  onSuccess(verificationId, accountChange.newEmail);
2739
3777
  return;
2740
3778
  }
@@ -2750,7 +3788,7 @@ function RequestChangeEmailForm({
2750
3788
  }, [getPendingAccountChangeQuery.refetch, getValues, onSuccess, setValue]);
2751
3789
  const onEmailPasswordSubmit = async (data) => {
2752
3790
  if (!user) {
2753
- toast7.error("User not found");
3791
+ toast10.error("User not found");
2754
3792
  return;
2755
3793
  }
2756
3794
  try {
@@ -2763,10 +3801,10 @@ function RequestChangeEmailForm({
2763
3801
  });
2764
3802
  if (checkResult.data?.exists) {
2765
3803
  if (user?.email?.toLowerCase() === data.email.toLowerCase()) {
2766
- toast7.error("This is already your current email address.");
3804
+ toast10.error("This is already your current email address.");
2767
3805
  return;
2768
3806
  }
2769
- toast7.error(
3807
+ toast10.error(
2770
3808
  "This email is already taken. Please use a different email."
2771
3809
  );
2772
3810
  return;
@@ -2774,34 +3812,34 @@ function RequestChangeEmailForm({
2774
3812
  const verification = await requestEmailVerificationMutation.mutateAsync({
2775
3813
  body: { email: data.email }
2776
3814
  });
2777
- toast7.success("Verification code sent to your email");
3815
+ toast10.success("Verification code sent to your email");
2778
3816
  onSuccess(verification.data?.verificationId ?? "", data.email);
2779
3817
  } catch (error) {
2780
3818
  const errorMessage = getErrorMessage(error);
2781
3819
  if (isAuthError2(error)) {
2782
3820
  const errorCode = getErrorCode(error);
2783
3821
  if (errorCode === "INVALID_PASSWORD" || errorCode === "USER_NOT_FOUND") {
2784
- toast7.error("Incorrect password. Please try again.");
3822
+ toast10.error("Incorrect password. Please try again.");
2785
3823
  return;
2786
3824
  }
2787
3825
  }
2788
- toast7.error(errorMessage);
3826
+ toast10.error(errorMessage);
2789
3827
  } finally {
2790
3828
  setIsSubmitting(false);
2791
3829
  }
2792
3830
  };
2793
3831
  const isLoading = isSubmitting || isChecking;
2794
- return /* @__PURE__ */ jsxs19(
3832
+ return /* @__PURE__ */ jsxs25(
2795
3833
  "form",
2796
3834
  {
2797
3835
  onSubmit: handleSubmit(onEmailPasswordSubmit),
2798
3836
  className: "p-4 space-y-4 border-t",
2799
3837
  children: [
2800
- /* @__PURE__ */ jsxs19("div", { className: "space-y-4 w-full md:w-1/2", children: [
2801
- /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
2802
- /* @__PURE__ */ jsx21(Label, { htmlFor: "email", children: "New Email Address" }),
2803
- /* @__PURE__ */ jsx21(
2804
- Input5,
3838
+ /* @__PURE__ */ jsxs25("div", { className: "space-y-4 w-full md:w-1/2", children: [
3839
+ /* @__PURE__ */ jsxs25("div", { className: "space-y-2", children: [
3840
+ /* @__PURE__ */ jsx29(Label, { htmlFor: "email", children: "New Email Address" }),
3841
+ /* @__PURE__ */ jsx29(
3842
+ Input7,
2805
3843
  {
2806
3844
  id: "email",
2807
3845
  type: "email",
@@ -2810,13 +3848,13 @@ function RequestChangeEmailForm({
2810
3848
  disabled: isLoading
2811
3849
  }
2812
3850
  ),
2813
- errors.email && /* @__PURE__ */ jsx21("p", { className: "text-sm text-destructive", children: errors.email.message })
3851
+ errors.email && /* @__PURE__ */ jsx29("p", { className: "text-sm text-destructive", children: errors.email.message })
2814
3852
  ] }),
2815
- /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
2816
- /* @__PURE__ */ jsx21(Label, { htmlFor: "password", children: "Password" }),
2817
- /* @__PURE__ */ jsxs19("div", { className: "relative", children: [
2818
- /* @__PURE__ */ jsx21(
2819
- Input5,
3853
+ /* @__PURE__ */ jsxs25("div", { className: "space-y-2", children: [
3854
+ /* @__PURE__ */ jsx29(Label, { htmlFor: "password", children: "Password" }),
3855
+ /* @__PURE__ */ jsxs25("div", { className: "relative", children: [
3856
+ /* @__PURE__ */ jsx29(
3857
+ Input7,
2820
3858
  {
2821
3859
  id: "password",
2822
3860
  type: showPassword ? "text" : "password",
@@ -2826,23 +3864,23 @@ function RequestChangeEmailForm({
2826
3864
  disabled: isLoading
2827
3865
  }
2828
3866
  ),
2829
- /* @__PURE__ */ jsx21(
3867
+ /* @__PURE__ */ jsx29(
2830
3868
  "button",
2831
3869
  {
2832
3870
  type: "button",
2833
3871
  onClick: () => setShowPassword(!showPassword),
2834
3872
  className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
2835
3873
  disabled: isLoading,
2836
- children: showPassword ? /* @__PURE__ */ jsx21(IconEyeOff4, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx21(IconEye4, { className: "h-4 w-4" })
3874
+ children: showPassword ? /* @__PURE__ */ jsx29(IconEyeOff5, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx29(IconEye5, { className: "h-4 w-4" })
2837
3875
  }
2838
3876
  )
2839
3877
  ] }),
2840
- errors.password && /* @__PURE__ */ jsx21("p", { className: "text-sm text-destructive", children: errors.password.message })
3878
+ errors.password && /* @__PURE__ */ jsx29("p", { className: "text-sm text-destructive", children: errors.password.message })
2841
3879
  ] })
2842
3880
  ] }),
2843
- /* @__PURE__ */ jsxs19("div", { className: "flex justify-end gap-2", children: [
2844
- /* @__PURE__ */ jsx21(
2845
- Button13,
3881
+ /* @__PURE__ */ jsxs25("div", { className: "flex justify-end gap-2", children: [
3882
+ /* @__PURE__ */ jsx29(
3883
+ Button15,
2846
3884
  {
2847
3885
  type: "button",
2848
3886
  variant: "outline",
@@ -2851,8 +3889,8 @@ function RequestChangeEmailForm({
2851
3889
  children: "Cancel"
2852
3890
  }
2853
3891
  ),
2854
- /* @__PURE__ */ jsxs19(Button13, { type: "submit", disabled: isLoading, children: [
2855
- isLoading && /* @__PURE__ */ jsx21(Spinner5, { className: "mr-2 h-4 w-4" }),
3892
+ /* @__PURE__ */ jsxs25(Button15, { type: "submit", disabled: isLoading, children: [
3893
+ isLoading && /* @__PURE__ */ jsx29(Spinner2, { className: "mr-2 h-4 w-4" }),
2856
3894
  isChecking ? "Checking\u2026" : buttonText
2857
3895
  ] })
2858
3896
  ] })
@@ -2862,8 +3900,8 @@ function RequestChangeEmailForm({
2862
3900
  }
2863
3901
 
2864
3902
  // src/components/profile/verify-change-email-form.tsx
2865
- import { useState as useState15 } from "react";
2866
- import { toast as toast8 } from "sonner";
3903
+ import { useState as useState17 } from "react";
3904
+ import { toast as toast11 } from "sonner";
2867
3905
 
2868
3906
  // src/components/profile/otp-verification-modal.tsx
2869
3907
  import {
@@ -2873,7 +3911,7 @@ import {
2873
3911
  DialogHeader,
2874
3912
  DialogTitle
2875
3913
  } from "@mesob/ui/components";
2876
- import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
3914
+ import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
2877
3915
  function OtpVerificationModal({
2878
3916
  open,
2879
3917
  title,
@@ -2884,7 +3922,7 @@ function OtpVerificationModal({
2884
3922
  onResend,
2885
3923
  onCancel
2886
3924
  }) {
2887
- return /* @__PURE__ */ jsx22(
3925
+ return /* @__PURE__ */ jsx30(
2888
3926
  Dialog,
2889
3927
  {
2890
3928
  open,
@@ -2893,12 +3931,12 @@ function OtpVerificationModal({
2893
3931
  onCancel?.();
2894
3932
  }
2895
3933
  },
2896
- children: /* @__PURE__ */ jsxs20(DialogContent, { children: [
2897
- /* @__PURE__ */ jsxs20(DialogHeader, { children: [
2898
- /* @__PURE__ */ jsx22(DialogTitle, { children: title }),
2899
- description && /* @__PURE__ */ jsx22(DialogDescription, { children: description })
3934
+ children: /* @__PURE__ */ jsxs26(DialogContent, { children: [
3935
+ /* @__PURE__ */ jsxs26(DialogHeader, { children: [
3936
+ /* @__PURE__ */ jsx30(DialogTitle, { children: title }),
3937
+ description && /* @__PURE__ */ jsx30(DialogDescription, { children: description })
2900
3938
  ] }),
2901
- /* @__PURE__ */ jsx22(
3939
+ /* @__PURE__ */ jsx30(
2902
3940
  VerificationForm,
2903
3941
  {
2904
3942
  verificationId,
@@ -2913,7 +3951,7 @@ function OtpVerificationModal({
2913
3951
  }
2914
3952
 
2915
3953
  // src/components/profile/verify-change-email-form.tsx
2916
- import { jsx as jsx23 } from "react/jsx-runtime";
3954
+ import { jsx as jsx31 } from "react/jsx-runtime";
2917
3955
  function isAuthError3(error) {
2918
3956
  return typeof error === "object" && error !== null && ("code" in error || "message" in error || "name" in error);
2919
3957
  }
@@ -2968,8 +4006,8 @@ function VerifyChangeEmailForm({
2968
4006
  }) {
2969
4007
  const { refresh } = useSession();
2970
4008
  const { hooks } = useApi();
2971
- const [isSubmitting, setIsSubmitting] = useState15(false);
2972
- const [currentVerificationId, setCurrentVerificationId] = useState15(verificationId);
4009
+ const [isSubmitting, setIsSubmitting] = useState17(false);
4010
+ const [currentVerificationId, setCurrentVerificationId] = useState17(verificationId);
2973
4011
  const verifyEmailMutation = hooks.useMutation(
2974
4012
  "post",
2975
4013
  "/email/verification/confirm"
@@ -2981,7 +4019,7 @@ function VerifyChangeEmailForm({
2981
4019
  );
2982
4020
  const onOtpSubmit = async (code) => {
2983
4021
  if (!currentVerificationId) {
2984
- toast8.error("Verification not found. Please request a new code.");
4022
+ toast11.error("Verification not found. Please request a new code.");
2985
4023
  return;
2986
4024
  }
2987
4025
  try {
@@ -2995,21 +4033,21 @@ function VerifyChangeEmailForm({
2995
4033
  await updateEmailMutation.mutateAsync({
2996
4034
  body: { email }
2997
4035
  });
2998
- toast8.success("Email updated successfully");
4036
+ toast11.success("Email updated successfully");
2999
4037
  await refresh();
3000
4038
  onSuccess();
3001
4039
  } catch (error) {
3002
4040
  const errorMessage = getErrorMessage2(error);
3003
- toast8.error(errorMessage);
4041
+ toast11.error(errorMessage);
3004
4042
  } finally {
3005
4043
  setIsSubmitting(false);
3006
4044
  }
3007
4045
  };
3008
4046
  if (!currentVerificationId) {
3009
- toast8.error("Verification not found. Please request a new code.");
4047
+ toast11.error("Verification not found. Please request a new code.");
3010
4048
  return null;
3011
4049
  }
3012
- return /* @__PURE__ */ jsx23(
4050
+ return /* @__PURE__ */ jsx31(
3013
4051
  OtpVerificationModal,
3014
4052
  {
3015
4053
  open: true,
@@ -3025,9 +4063,9 @@ function VerifyChangeEmailForm({
3025
4063
  body: { email }
3026
4064
  });
3027
4065
  setCurrentVerificationId(next.data?.verificationId ?? null);
3028
- toast8.success("Verification code resent");
4066
+ toast11.success("Verification code resent");
3029
4067
  } catch (error) {
3030
- toast8.error(getErrorMessage2(error));
4068
+ toast11.error(getErrorMessage2(error));
3031
4069
  } finally {
3032
4070
  setIsSubmitting(false);
3033
4071
  }
@@ -3038,13 +4076,13 @@ function VerifyChangeEmailForm({
3038
4076
  }
3039
4077
 
3040
4078
  // src/components/profile/change-email-form.tsx
3041
- import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
4079
+ import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
3042
4080
  function ChangeEmailForm() {
3043
4081
  const { user } = useSession();
3044
- const [isOpen, setIsOpen] = useState16(false);
3045
- const [showOtp, setShowOtp] = useState16(false);
3046
- const [verificationId, setVerificationId] = useState16(null);
3047
- const [newEmail, setNewEmail] = useState16("");
4082
+ const [isOpen, setIsOpen] = useState18(false);
4083
+ const [showOtp, setShowOtp] = useState18(false);
4084
+ const [verificationId, setVerificationId] = useState18(null);
4085
+ const [newEmail, setNewEmail] = useState18("");
3048
4086
  const resetForms = () => {
3049
4087
  setShowOtp(false);
3050
4088
  setVerificationId(null);
@@ -3065,23 +4103,23 @@ function ChangeEmailForm() {
3065
4103
  };
3066
4104
  const title = user?.email ? "Change Email" : "Add Email";
3067
4105
  const description = user?.email ? "Update your email address" : "Add an email address to your account";
3068
- return /* @__PURE__ */ jsx24(Collapsible, { open: isOpen, onOpenChange: setIsOpen, children: /* @__PURE__ */ jsxs21("div", { className: "border rounded-lg", children: [
3069
- /* @__PURE__ */ jsxs21(
4106
+ return /* @__PURE__ */ jsx32(Collapsible, { open: isOpen, onOpenChange: setIsOpen, children: /* @__PURE__ */ jsxs27("div", { className: "border rounded-lg", children: [
4107
+ /* @__PURE__ */ jsxs27(
3070
4108
  CollapsibleTrigger,
3071
4109
  {
3072
- render: /* @__PURE__ */ jsx24(
3073
- Button14,
4110
+ render: /* @__PURE__ */ jsx32(
4111
+ Button16,
3074
4112
  {
3075
4113
  variant: "ghost",
3076
4114
  className: "w-full justify-between p-4 h-auto"
3077
4115
  }
3078
4116
  ),
3079
4117
  children: [
3080
- /* @__PURE__ */ jsxs21("div", { className: "flex flex-col items-start", children: [
3081
- /* @__PURE__ */ jsx24("span", { className: "font-medium", children: title }),
3082
- /* @__PURE__ */ jsx24("span", { className: "text-sm text-muted-foreground", children: description })
4118
+ /* @__PURE__ */ jsxs27("div", { className: "flex flex-col items-start", children: [
4119
+ /* @__PURE__ */ jsx32("span", { className: "font-medium", children: title }),
4120
+ /* @__PURE__ */ jsx32("span", { className: "text-sm text-muted-foreground", children: description })
3083
4121
  ] }),
3084
- /* @__PURE__ */ jsx24(
4122
+ /* @__PURE__ */ jsx32(
3085
4123
  IconChevronDown,
3086
4124
  {
3087
4125
  className: `h-4 w-4 transition-transform ${isOpen ? "rotate-180" : ""}`
@@ -3090,7 +4128,7 @@ function ChangeEmailForm() {
3090
4128
  ]
3091
4129
  }
3092
4130
  ),
3093
- /* @__PURE__ */ jsx24(CollapsibleContent, { children: showOtp ? /* @__PURE__ */ jsx24(
4131
+ /* @__PURE__ */ jsx32(CollapsibleContent, { children: showOtp ? /* @__PURE__ */ jsx32(
3094
4132
  VerifyChangeEmailForm,
3095
4133
  {
3096
4134
  email: newEmail,
@@ -3098,7 +4136,7 @@ function ChangeEmailForm() {
3098
4136
  onSuccess: handleVerifySuccess,
3099
4137
  onCancel: handleCancel
3100
4138
  }
3101
- ) : /* @__PURE__ */ jsx24(
4139
+ ) : /* @__PURE__ */ jsx32(
3102
4140
  RequestChangeEmailForm,
3103
4141
  {
3104
4142
  onSuccess: handleRequestSuccess,
@@ -3110,26 +4148,26 @@ function ChangeEmailForm() {
3110
4148
  }
3111
4149
 
3112
4150
  // src/components/profile/change-password-form.tsx
3113
- import { zodResolver as zodResolver7 } from "@hookform/resolvers/zod";
4151
+ import { zodResolver as zodResolver9 } from "@hookform/resolvers/zod";
3114
4152
  import {
3115
- Button as Button15,
4153
+ Button as Button17,
3116
4154
  Collapsible as Collapsible2,
3117
4155
  CollapsibleContent as CollapsibleContent2,
3118
4156
  CollapsibleTrigger as CollapsibleTrigger2,
3119
- Input as Input6,
4157
+ Input as Input8,
3120
4158
  Label as Label2,
3121
- Spinner as Spinner6
4159
+ Spinner as Spinner3
3122
4160
  } from "@mesob/ui/components";
3123
- import { IconChevronDown as IconChevronDown2, IconEye as IconEye5, IconEyeOff as IconEyeOff5 } from "@tabler/icons-react";
3124
- import { useState as useState17 } from "react";
3125
- import { useForm as useForm7 } from "react-hook-form";
3126
- import { toast as toast9 } from "sonner";
3127
- import { z as z7 } from "zod";
3128
- import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
3129
- var changePasswordSchema = z7.object({
3130
- currentPassword: z7.string().min(8, "Password must be at least 8 characters"),
3131
- newPassword: z7.string().min(8, "Password must be at least 8 characters"),
3132
- confirmPassword: z7.string().min(8, "Password must be at least 8 characters")
4161
+ import { IconChevronDown as IconChevronDown2, IconEye as IconEye6, IconEyeOff as IconEyeOff6 } from "@tabler/icons-react";
4162
+ import { useState as useState19 } from "react";
4163
+ import { useForm as useForm9 } from "react-hook-form";
4164
+ import { toast as toast12 } from "sonner";
4165
+ import { z as z9 } from "zod";
4166
+ import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
4167
+ var changePasswordSchema = z9.object({
4168
+ currentPassword: z9.string().min(8, "Password must be at least 8 characters"),
4169
+ newPassword: z9.string().min(8, "Password must be at least 8 characters"),
4170
+ confirmPassword: z9.string().min(8, "Password must be at least 8 characters")
3133
4171
  }).refine((data) => data.newPassword === data.confirmPassword, {
3134
4172
  message: "Passwords don't match",
3135
4173
  path: ["confirmPassword"]
@@ -3183,13 +4221,13 @@ function getPasswordChangeErrorMessage(error) {
3183
4221
  }
3184
4222
  function ChangePasswordForm() {
3185
4223
  const { user: _user } = useSession();
3186
- const [isOpen, setIsOpen] = useState17(false);
3187
- const [isSubmitting, setIsSubmitting] = useState17(false);
3188
- const [showPassword, setShowPassword] = useState17(false);
3189
- const [showNewPassword, setShowNewPassword] = useState17(false);
3190
- const [showConfirmPassword, setShowConfirmPassword] = useState17(false);
3191
- const form = useForm7({
3192
- resolver: zodResolver7(changePasswordSchema),
4224
+ const [isOpen, setIsOpen] = useState19(false);
4225
+ const [isSubmitting, setIsSubmitting] = useState19(false);
4226
+ const [showPassword, setShowPassword] = useState19(false);
4227
+ const [showNewPassword, setShowNewPassword] = useState19(false);
4228
+ const [showConfirmPassword, setShowConfirmPassword] = useState19(false);
4229
+ const form = useForm9({
4230
+ resolver: zodResolver9(changePasswordSchema),
3193
4231
  defaultValues: {
3194
4232
  currentPassword: "",
3195
4233
  newPassword: "",
@@ -3200,32 +4238,32 @@ function ChangePasswordForm() {
3200
4238
  const onSubmit = (_data) => {
3201
4239
  try {
3202
4240
  setIsSubmitting(true);
3203
- toast9.error("Password change unavailable");
4241
+ toast12.error("Password change unavailable");
3204
4242
  setIsOpen(false);
3205
4243
  } catch (error) {
3206
4244
  const errorMessage = getPasswordChangeErrorMessage(error);
3207
- toast9.error(errorMessage);
4245
+ toast12.error(errorMessage);
3208
4246
  } finally {
3209
4247
  setIsSubmitting(false);
3210
4248
  }
3211
4249
  };
3212
- return /* @__PURE__ */ jsx25(Collapsible2, { open: isOpen, onOpenChange: setIsOpen, children: /* @__PURE__ */ jsxs22("div", { className: "border rounded-lg", children: [
3213
- /* @__PURE__ */ jsxs22(
4250
+ return /* @__PURE__ */ jsx33(Collapsible2, { open: isOpen, onOpenChange: setIsOpen, children: /* @__PURE__ */ jsxs28("div", { className: "border rounded-lg", children: [
4251
+ /* @__PURE__ */ jsxs28(
3214
4252
  CollapsibleTrigger2,
3215
4253
  {
3216
- render: /* @__PURE__ */ jsx25(
3217
- Button15,
4254
+ render: /* @__PURE__ */ jsx33(
4255
+ Button17,
3218
4256
  {
3219
4257
  variant: "ghost",
3220
4258
  className: "w-full justify-between p-4 h-auto"
3221
4259
  }
3222
4260
  ),
3223
4261
  children: [
3224
- /* @__PURE__ */ jsxs22("div", { className: "flex flex-col items-start", children: [
3225
- /* @__PURE__ */ jsx25("span", { className: "font-medium", children: "Change Password" }),
3226
- /* @__PURE__ */ jsx25("span", { className: "text-sm text-muted-foreground", children: "Update your account password" })
4262
+ /* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-start", children: [
4263
+ /* @__PURE__ */ jsx33("span", { className: "font-medium", children: "Change Password" }),
4264
+ /* @__PURE__ */ jsx33("span", { className: "text-sm text-muted-foreground", children: "Update your account password" })
3227
4265
  ] }),
3228
- /* @__PURE__ */ jsx25(
4266
+ /* @__PURE__ */ jsx33(
3229
4267
  IconChevronDown2,
3230
4268
  {
3231
4269
  className: `h-4 w-4 transition-transform ${isOpen ? "rotate-180" : ""}`
@@ -3234,17 +4272,17 @@ function ChangePasswordForm() {
3234
4272
  ]
3235
4273
  }
3236
4274
  ),
3237
- /* @__PURE__ */ jsx25(CollapsibleContent2, { children: /* @__PURE__ */ jsxs22(
4275
+ /* @__PURE__ */ jsx33(CollapsibleContent2, { children: /* @__PURE__ */ jsxs28(
3238
4276
  "form",
3239
4277
  {
3240
4278
  onSubmit: handleSubmit(onSubmit),
3241
4279
  className: "p-4 space-y-4 border-t",
3242
4280
  children: [
3243
- /* @__PURE__ */ jsxs22("div", { className: "space-y-2 w-full md:w-1/2", children: [
3244
- /* @__PURE__ */ jsx25(Label2, { htmlFor: "currentPassword", children: "Old Password" }),
3245
- /* @__PURE__ */ jsxs22("div", { className: "relative", children: [
3246
- /* @__PURE__ */ jsx25(
3247
- Input6,
4281
+ /* @__PURE__ */ jsxs28("div", { className: "space-y-2 w-full md:w-1/2", children: [
4282
+ /* @__PURE__ */ jsx33(Label2, { htmlFor: "currentPassword", children: "Old Password" }),
4283
+ /* @__PURE__ */ jsxs28("div", { className: "relative", children: [
4284
+ /* @__PURE__ */ jsx33(
4285
+ Input8,
3248
4286
  {
3249
4287
  id: "currentPassword",
3250
4288
  type: showPassword ? "text" : "password",
@@ -3253,23 +4291,23 @@ function ChangePasswordForm() {
3253
4291
  ...register("currentPassword")
3254
4292
  }
3255
4293
  ),
3256
- /* @__PURE__ */ jsx25(
4294
+ /* @__PURE__ */ jsx33(
3257
4295
  "button",
3258
4296
  {
3259
4297
  type: "button",
3260
4298
  onClick: () => setShowPassword(!showPassword),
3261
4299
  className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
3262
- children: showPassword ? /* @__PURE__ */ jsx25(IconEyeOff5, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx25(IconEye5, { className: "h-4 w-4" })
4300
+ children: showPassword ? /* @__PURE__ */ jsx33(IconEyeOff6, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx33(IconEye6, { className: "h-4 w-4" })
3263
4301
  }
3264
4302
  )
3265
4303
  ] }),
3266
- formState.errors.currentPassword && /* @__PURE__ */ jsx25("p", { className: "text-sm text-destructive", children: formState.errors.currentPassword.message })
4304
+ formState.errors.currentPassword && /* @__PURE__ */ jsx33("p", { className: "text-sm text-destructive", children: formState.errors.currentPassword.message })
3267
4305
  ] }),
3268
- /* @__PURE__ */ jsxs22("div", { className: "space-y-2 w-full md:w-1/2", children: [
3269
- /* @__PURE__ */ jsx25(Label2, { htmlFor: "newPassword", children: "New Password" }),
3270
- /* @__PURE__ */ jsxs22("div", { className: "relative", children: [
3271
- /* @__PURE__ */ jsx25(
3272
- Input6,
4306
+ /* @__PURE__ */ jsxs28("div", { className: "space-y-2 w-full md:w-1/2", children: [
4307
+ /* @__PURE__ */ jsx33(Label2, { htmlFor: "newPassword", children: "New Password" }),
4308
+ /* @__PURE__ */ jsxs28("div", { className: "relative", children: [
4309
+ /* @__PURE__ */ jsx33(
4310
+ Input8,
3273
4311
  {
3274
4312
  id: "newPassword",
3275
4313
  type: showNewPassword ? "text" : "password",
@@ -3278,23 +4316,23 @@ function ChangePasswordForm() {
3278
4316
  ...register("newPassword")
3279
4317
  }
3280
4318
  ),
3281
- /* @__PURE__ */ jsx25(
4319
+ /* @__PURE__ */ jsx33(
3282
4320
  "button",
3283
4321
  {
3284
4322
  type: "button",
3285
4323
  onClick: () => setShowNewPassword(!showNewPassword),
3286
4324
  className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
3287
- children: showNewPassword ? /* @__PURE__ */ jsx25(IconEyeOff5, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx25(IconEye5, { className: "h-4 w-4" })
4325
+ children: showNewPassword ? /* @__PURE__ */ jsx33(IconEyeOff6, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx33(IconEye6, { className: "h-4 w-4" })
3288
4326
  }
3289
4327
  )
3290
4328
  ] }),
3291
- formState.errors.newPassword && /* @__PURE__ */ jsx25("p", { className: "text-sm text-destructive", children: formState.errors.newPassword.message })
4329
+ formState.errors.newPassword && /* @__PURE__ */ jsx33("p", { className: "text-sm text-destructive", children: formState.errors.newPassword.message })
3292
4330
  ] }),
3293
- /* @__PURE__ */ jsxs22("div", { className: "space-y-2 w-full md:w-1/2", children: [
3294
- /* @__PURE__ */ jsx25(Label2, { htmlFor: "confirmPassword", children: "Confirm New Password" }),
3295
- /* @__PURE__ */ jsxs22("div", { className: "relative", children: [
3296
- /* @__PURE__ */ jsx25(
3297
- Input6,
4331
+ /* @__PURE__ */ jsxs28("div", { className: "space-y-2 w-full md:w-1/2", children: [
4332
+ /* @__PURE__ */ jsx33(Label2, { htmlFor: "confirmPassword", children: "Confirm New Password" }),
4333
+ /* @__PURE__ */ jsxs28("div", { className: "relative", children: [
4334
+ /* @__PURE__ */ jsx33(
4335
+ Input8,
3298
4336
  {
3299
4337
  id: "confirmPassword",
3300
4338
  type: showConfirmPassword ? "text" : "password",
@@ -3303,21 +4341,21 @@ function ChangePasswordForm() {
3303
4341
  ...register("confirmPassword")
3304
4342
  }
3305
4343
  ),
3306
- /* @__PURE__ */ jsx25(
4344
+ /* @__PURE__ */ jsx33(
3307
4345
  "button",
3308
4346
  {
3309
4347
  type: "button",
3310
4348
  onClick: () => setShowConfirmPassword(!showConfirmPassword),
3311
4349
  className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
3312
- children: showConfirmPassword ? /* @__PURE__ */ jsx25(IconEyeOff5, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx25(IconEye5, { className: "h-4 w-4" })
4350
+ children: showConfirmPassword ? /* @__PURE__ */ jsx33(IconEyeOff6, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx33(IconEye6, { className: "h-4 w-4" })
3313
4351
  }
3314
4352
  )
3315
4353
  ] }),
3316
- formState.errors.confirmPassword && /* @__PURE__ */ jsx25("p", { className: "text-sm text-destructive", children: formState.errors.confirmPassword.message })
4354
+ formState.errors.confirmPassword && /* @__PURE__ */ jsx33("p", { className: "text-sm text-destructive", children: formState.errors.confirmPassword.message })
3317
4355
  ] }),
3318
- /* @__PURE__ */ jsxs22("div", { className: "flex justify-end gap-2", children: [
3319
- /* @__PURE__ */ jsx25(
3320
- Button15,
4356
+ /* @__PURE__ */ jsxs28("div", { className: "flex justify-end gap-2", children: [
4357
+ /* @__PURE__ */ jsx33(
4358
+ Button17,
3321
4359
  {
3322
4360
  type: "button",
3323
4361
  variant: "outline",
@@ -3329,8 +4367,8 @@ function ChangePasswordForm() {
3329
4367
  children: "Cancel"
3330
4368
  }
3331
4369
  ),
3332
- /* @__PURE__ */ jsxs22(Button15, { type: "submit", disabled: isSubmitting, children: [
3333
- isSubmitting && /* @__PURE__ */ jsx25(Spinner6, { className: "mr-2 h-4 w-4" }),
4370
+ /* @__PURE__ */ jsxs28(Button17, { type: "submit", disabled: isSubmitting, children: [
4371
+ isSubmitting && /* @__PURE__ */ jsx33(Spinner3, { className: "mr-2 h-4 w-4" }),
3334
4372
  "Change Password"
3335
4373
  ] })
3336
4374
  ] })
@@ -3342,25 +4380,25 @@ function ChangePasswordForm() {
3342
4380
 
3343
4381
  // src/components/profile/change-phone-form.tsx
3344
4382
  import {
3345
- Button as Button17,
4383
+ Button as Button19,
3346
4384
  Collapsible as Collapsible3,
3347
4385
  CollapsibleContent as CollapsibleContent3,
3348
4386
  CollapsibleTrigger as CollapsibleTrigger3
3349
4387
  } from "@mesob/ui/components";
3350
4388
  import { IconChevronDown as IconChevronDown3 } from "@tabler/icons-react";
3351
- import { useState as useState20 } from "react";
4389
+ import { useState as useState22 } from "react";
3352
4390
 
3353
4391
  // src/components/profile/request-change-phone-form.tsx
3354
- import { zodResolver as zodResolver8 } from "@hookform/resolvers/zod";
3355
- import { Button as Button16, Input as Input7, Label as Label3, Spinner as Spinner7 } from "@mesob/ui/components";
3356
- import { IconEye as IconEye6, IconEyeOff as IconEyeOff6 } from "@tabler/icons-react";
3357
- import { useEffect as useEffect9, useState as useState18 } from "react";
3358
- import { useForm as useForm8 } from "react-hook-form";
3359
- import { toast as toast10 } from "sonner";
3360
- import { z as z8 } from "zod";
3361
- import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
3362
- var phonePasswordSchema = (phoneRegex) => z8.object({
3363
- phone: z8.string().trim().min(1, { message: "Phone number is required" }).refine(
4392
+ import { zodResolver as zodResolver10 } from "@hookform/resolvers/zod";
4393
+ import { Button as Button18, Input as Input9, Label as Label3, Spinner as Spinner4 } from "@mesob/ui/components";
4394
+ import { IconEye as IconEye7, IconEyeOff as IconEyeOff7 } from "@tabler/icons-react";
4395
+ import { useEffect as useEffect11, useState as useState20 } from "react";
4396
+ import { useForm as useForm10 } from "react-hook-form";
4397
+ import { toast as toast13 } from "sonner";
4398
+ import { z as z10 } from "zod";
4399
+ import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
4400
+ var phonePasswordSchema = (phoneRegex) => z10.object({
4401
+ phone: z10.string().trim().min(1, { message: "Phone number is required" }).refine(
3364
4402
  (val) => {
3365
4403
  const isPhone3 = phoneRegex.test(val);
3366
4404
  return isPhone3;
@@ -3369,7 +4407,7 @@ var phonePasswordSchema = (phoneRegex) => z8.object({
3369
4407
  message: "Invalid phone number"
3370
4408
  }
3371
4409
  ),
3372
- password: z8.string().min(8, "Password must be at least 8 characters").max(128, "Password too long")
4410
+ password: z10.string().min(8, "Password must be at least 8 characters").max(128, "Password too long")
3373
4411
  });
3374
4412
  function isAuthError5(error) {
3375
4413
  return typeof error === "object" && error !== null && ("code" in error || "message" in error || "name" in error);
@@ -3425,9 +4463,9 @@ function RequestChangePhoneForm({
3425
4463
  const { user } = useSession();
3426
4464
  const { hooks } = useApi();
3427
4465
  const { config } = useConfig();
3428
- const [isSubmitting, setIsSubmitting] = useState18(false);
3429
- const [isChecking, setIsChecking] = useState18(true);
3430
- const [showPassword, setShowPassword] = useState18(false);
4466
+ const [isSubmitting, setIsSubmitting] = useState20(false);
4467
+ const [isChecking, setIsChecking] = useState20(true);
4468
+ const [showPassword, setShowPassword] = useState20(false);
3431
4469
  const phoneRegex = typeof config.phoneRegex === "string" ? new RegExp(config.phoneRegex) : config.phoneRegex || /^(\+2519|\+2517|2519|2517|09|07)\d{8}$/;
3432
4470
  const getPendingAccountChangeQuery = hooks.useQuery(
3433
4471
  "get",
@@ -3441,8 +4479,8 @@ function RequestChangePhoneForm({
3441
4479
  "post",
3442
4480
  "/phone/verification/request"
3443
4481
  );
3444
- const phonePasswordForm = useForm8({
3445
- resolver: zodResolver8(phonePasswordSchema(phoneRegex)),
4482
+ const phonePasswordForm = useForm10({
4483
+ resolver: zodResolver10(phonePasswordSchema(phoneRegex)),
3446
4484
  defaultValues: {
3447
4485
  phone: "",
3448
4486
  password: ""
@@ -3455,7 +4493,7 @@ function RequestChangePhoneForm({
3455
4493
  setValue,
3456
4494
  formState: { errors }
3457
4495
  } = phonePasswordForm;
3458
- useEffect9(() => {
4496
+ useEffect11(() => {
3459
4497
  let active = true;
3460
4498
  const run = async () => {
3461
4499
  try {
@@ -3479,7 +4517,7 @@ function RequestChangePhoneForm({
3479
4517
  }
3480
4518
  setValue("phone", accountChange.newPhone, { shouldValidate: true });
3481
4519
  if (verificationId) {
3482
- toast10.message("Resuming verification\u2026");
4520
+ toast13.message("Resuming verification\u2026");
3483
4521
  onSuccess(verificationId, accountChange.newPhone);
3484
4522
  return;
3485
4523
  }
@@ -3495,7 +4533,7 @@ function RequestChangePhoneForm({
3495
4533
  }, [getPendingAccountChangeQuery.refetch, getValues, onSuccess, setValue]);
3496
4534
  const onPhonePasswordSubmit = async (data) => {
3497
4535
  if (!user) {
3498
- toast10.error("User not found");
4536
+ toast13.error("User not found");
3499
4537
  return;
3500
4538
  }
3501
4539
  try {
@@ -3509,10 +4547,10 @@ function RequestChangePhoneForm({
3509
4547
  });
3510
4548
  if (checkResult.data?.exists) {
3511
4549
  if (user?.phone?.replace(/\s/g, "") === normalizedPhone.replace(/\s/g, "")) {
3512
- toast10.error("This is already your current phone number.");
4550
+ toast13.error("This is already your current phone number.");
3513
4551
  return;
3514
4552
  }
3515
- toast10.error(
4553
+ toast13.error(
3516
4554
  "This phone number is already taken. Please use a different number."
3517
4555
  );
3518
4556
  return;
@@ -3523,34 +4561,34 @@ function RequestChangePhoneForm({
3523
4561
  context: "change-phone"
3524
4562
  }
3525
4563
  });
3526
- toast10.success("Verification code sent to your phone");
4564
+ toast13.success("Verification code sent to your phone");
3527
4565
  onSuccess(verification.data?.verificationId ?? "", normalizedPhone);
3528
4566
  } catch (error) {
3529
4567
  const errorMessage = getErrorMessage3(error);
3530
4568
  if (isAuthError5(error)) {
3531
4569
  const errorCode = getErrorCode4(error);
3532
4570
  if (errorCode === "INVALID_PASSWORD" || errorCode === "USER_NOT_FOUND") {
3533
- toast10.error("Incorrect password. Please try again.");
4571
+ toast13.error("Incorrect password. Please try again.");
3534
4572
  return;
3535
4573
  }
3536
4574
  }
3537
- toast10.error(errorMessage);
4575
+ toast13.error(errorMessage);
3538
4576
  } finally {
3539
4577
  setIsSubmitting(false);
3540
4578
  }
3541
4579
  };
3542
4580
  const isLoading = isSubmitting || isChecking;
3543
- return /* @__PURE__ */ jsxs23(
4581
+ return /* @__PURE__ */ jsxs29(
3544
4582
  "form",
3545
4583
  {
3546
4584
  onSubmit: handleSubmit(onPhonePasswordSubmit),
3547
4585
  className: "p-4 space-y-4 border-t",
3548
4586
  children: [
3549
- /* @__PURE__ */ jsxs23("div", { className: "space-y-4 w-full md:w-1/2", children: [
3550
- /* @__PURE__ */ jsxs23("div", { className: "space-y-2", children: [
3551
- /* @__PURE__ */ jsx26(Label3, { htmlFor: "phone", children: "Phone Number" }),
3552
- /* @__PURE__ */ jsx26(
3553
- Input7,
4587
+ /* @__PURE__ */ jsxs29("div", { className: "space-y-4 w-full md:w-1/2", children: [
4588
+ /* @__PURE__ */ jsxs29("div", { className: "space-y-2", children: [
4589
+ /* @__PURE__ */ jsx34(Label3, { htmlFor: "phone", children: "Phone Number" }),
4590
+ /* @__PURE__ */ jsx34(
4591
+ Input9,
3554
4592
  {
3555
4593
  id: "phone",
3556
4594
  type: "tel",
@@ -3559,13 +4597,13 @@ function RequestChangePhoneForm({
3559
4597
  disabled: isLoading
3560
4598
  }
3561
4599
  ),
3562
- errors.phone && /* @__PURE__ */ jsx26("p", { className: "text-sm text-destructive", children: errors.phone.message })
4600
+ errors.phone && /* @__PURE__ */ jsx34("p", { className: "text-sm text-destructive", children: errors.phone.message })
3563
4601
  ] }),
3564
- /* @__PURE__ */ jsxs23("div", { className: "space-y-2", children: [
3565
- /* @__PURE__ */ jsx26(Label3, { htmlFor: "password", children: "Password" }),
3566
- /* @__PURE__ */ jsxs23("div", { className: "relative", children: [
3567
- /* @__PURE__ */ jsx26(
3568
- Input7,
4602
+ /* @__PURE__ */ jsxs29("div", { className: "space-y-2", children: [
4603
+ /* @__PURE__ */ jsx34(Label3, { htmlFor: "password", children: "Password" }),
4604
+ /* @__PURE__ */ jsxs29("div", { className: "relative", children: [
4605
+ /* @__PURE__ */ jsx34(
4606
+ Input9,
3569
4607
  {
3570
4608
  id: "password",
3571
4609
  type: showPassword ? "text" : "password",
@@ -3575,22 +4613,22 @@ function RequestChangePhoneForm({
3575
4613
  disabled: isLoading
3576
4614
  }
3577
4615
  ),
3578
- /* @__PURE__ */ jsx26(
4616
+ /* @__PURE__ */ jsx34(
3579
4617
  "button",
3580
4618
  {
3581
4619
  type: "button",
3582
4620
  onClick: () => setShowPassword(!showPassword),
3583
4621
  className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
3584
- children: showPassword ? /* @__PURE__ */ jsx26(IconEyeOff6, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx26(IconEye6, { className: "h-4 w-4" })
4622
+ children: showPassword ? /* @__PURE__ */ jsx34(IconEyeOff7, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx34(IconEye7, { className: "h-4 w-4" })
3585
4623
  }
3586
4624
  )
3587
4625
  ] }),
3588
- errors.password && /* @__PURE__ */ jsx26("p", { className: "text-sm text-destructive", children: errors.password.message })
4626
+ errors.password && /* @__PURE__ */ jsx34("p", { className: "text-sm text-destructive", children: errors.password.message })
3589
4627
  ] })
3590
4628
  ] }),
3591
- /* @__PURE__ */ jsxs23("div", { className: "flex justify-end gap-2", children: [
3592
- /* @__PURE__ */ jsx26(
3593
- Button16,
4629
+ /* @__PURE__ */ jsxs29("div", { className: "flex justify-end gap-2", children: [
4630
+ /* @__PURE__ */ jsx34(
4631
+ Button18,
3594
4632
  {
3595
4633
  type: "button",
3596
4634
  variant: "outline",
@@ -3599,8 +4637,8 @@ function RequestChangePhoneForm({
3599
4637
  children: "Cancel"
3600
4638
  }
3601
4639
  ),
3602
- /* @__PURE__ */ jsxs23(Button16, { type: "submit", disabled: isLoading, children: [
3603
- isLoading && /* @__PURE__ */ jsx26(Spinner7, { className: "mr-2 h-4 w-4" }),
4640
+ /* @__PURE__ */ jsxs29(Button18, { type: "submit", disabled: isLoading, children: [
4641
+ isLoading && /* @__PURE__ */ jsx34(Spinner4, { className: "mr-2 h-4 w-4" }),
3604
4642
  isChecking ? "Checking\u2026" : buttonText
3605
4643
  ] })
3606
4644
  ] })
@@ -3610,9 +4648,9 @@ function RequestChangePhoneForm({
3610
4648
  }
3611
4649
 
3612
4650
  // src/components/profile/verify-change-phone-form.tsx
3613
- import { useState as useState19 } from "react";
3614
- import { toast as toast11 } from "sonner";
3615
- import { jsx as jsx27 } from "react/jsx-runtime";
4651
+ import { useState as useState21 } from "react";
4652
+ import { toast as toast14 } from "sonner";
4653
+ import { jsx as jsx35 } from "react/jsx-runtime";
3616
4654
  function isAuthError6(error) {
3617
4655
  return typeof error === "object" && error !== null && ("code" in error || "message" in error || "name" in error);
3618
4656
  }
@@ -3667,8 +4705,8 @@ function VerifyChangePhoneForm({
3667
4705
  }) {
3668
4706
  const { refresh } = useSession();
3669
4707
  const { hooks } = useApi();
3670
- const [isSubmitting, setIsSubmitting] = useState19(false);
3671
- const [currentVerificationId, setCurrentVerificationId] = useState19(verificationId);
4708
+ const [isSubmitting, setIsSubmitting] = useState21(false);
4709
+ const [currentVerificationId, setCurrentVerificationId] = useState21(verificationId);
3672
4710
  const verifyPhoneOtpMutation = hooks.useMutation(
3673
4711
  "post",
3674
4712
  "/phone/verification/confirm"
@@ -3680,7 +4718,7 @@ function VerifyChangePhoneForm({
3680
4718
  );
3681
4719
  const onOtpSubmit = async (code) => {
3682
4720
  if (!currentVerificationId) {
3683
- toast11.error("Verification not found. Please request a new code.");
4721
+ toast14.error("Verification not found. Please request a new code.");
3684
4722
  return;
3685
4723
  }
3686
4724
  try {
@@ -3695,21 +4733,21 @@ function VerifyChangePhoneForm({
3695
4733
  await updatePhoneMutation.mutateAsync({
3696
4734
  body: { phone }
3697
4735
  });
3698
- toast11.success("Phone number updated successfully");
4736
+ toast14.success("Phone number updated successfully");
3699
4737
  await refresh();
3700
4738
  onSuccess();
3701
4739
  } catch (error) {
3702
4740
  const errorMessage = getErrorMessage4(error);
3703
- toast11.error(errorMessage);
4741
+ toast14.error(errorMessage);
3704
4742
  } finally {
3705
4743
  setIsSubmitting(false);
3706
4744
  }
3707
4745
  };
3708
4746
  if (!currentVerificationId) {
3709
- toast11.error("Verification not found. Please request a new code.");
4747
+ toast14.error("Verification not found. Please request a new code.");
3710
4748
  return null;
3711
4749
  }
3712
- return /* @__PURE__ */ jsx27(
4750
+ return /* @__PURE__ */ jsx35(
3713
4751
  OtpVerificationModal,
3714
4752
  {
3715
4753
  open: true,
@@ -3728,9 +4766,9 @@ function VerifyChangePhoneForm({
3728
4766
  }
3729
4767
  });
3730
4768
  setCurrentVerificationId(next.data?.verificationId ?? null);
3731
- toast11.success("Verification code resent");
4769
+ toast14.success("Verification code resent");
3732
4770
  } catch (error) {
3733
- toast11.error(getErrorMessage4(error));
4771
+ toast14.error(getErrorMessage4(error));
3734
4772
  } finally {
3735
4773
  setIsSubmitting(false);
3736
4774
  }
@@ -3741,13 +4779,13 @@ function VerifyChangePhoneForm({
3741
4779
  }
3742
4780
 
3743
4781
  // src/components/profile/change-phone-form.tsx
3744
- import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
4782
+ import { jsx as jsx36, jsxs as jsxs30 } from "react/jsx-runtime";
3745
4783
  function ChangePhoneForm() {
3746
4784
  const { user } = useSession();
3747
- const [isOpen, setIsOpen] = useState20(false);
3748
- const [showOtp, setShowOtp] = useState20(false);
3749
- const [verificationId, setVerificationId] = useState20(null);
3750
- const [newPhone, setNewPhone] = useState20("");
4785
+ const [isOpen, setIsOpen] = useState22(false);
4786
+ const [showOtp, setShowOtp] = useState22(false);
4787
+ const [verificationId, setVerificationId] = useState22(null);
4788
+ const [newPhone, setNewPhone] = useState22("");
3751
4789
  const resetForms = () => {
3752
4790
  setShowOtp(false);
3753
4791
  setVerificationId(null);
@@ -3768,23 +4806,23 @@ function ChangePhoneForm() {
3768
4806
  };
3769
4807
  const title = user?.phone ? "Change Phone" : "Add Phone";
3770
4808
  const description = user?.phone ? "Update your phone number" : "Add a phone number to your account";
3771
- return /* @__PURE__ */ jsx28(Collapsible3, { open: isOpen, onOpenChange: setIsOpen, children: /* @__PURE__ */ jsxs24("div", { className: "border rounded-lg", children: [
3772
- /* @__PURE__ */ jsxs24(
4809
+ return /* @__PURE__ */ jsx36(Collapsible3, { open: isOpen, onOpenChange: setIsOpen, children: /* @__PURE__ */ jsxs30("div", { className: "border rounded-lg", children: [
4810
+ /* @__PURE__ */ jsxs30(
3773
4811
  CollapsibleTrigger3,
3774
4812
  {
3775
- render: /* @__PURE__ */ jsx28(
3776
- Button17,
4813
+ render: /* @__PURE__ */ jsx36(
4814
+ Button19,
3777
4815
  {
3778
4816
  variant: "ghost",
3779
4817
  className: "w-full justify-between p-4 h-auto"
3780
4818
  }
3781
4819
  ),
3782
4820
  children: [
3783
- /* @__PURE__ */ jsxs24("div", { className: "flex flex-col items-start", children: [
3784
- /* @__PURE__ */ jsx28("span", { className: "font-medium", children: title }),
3785
- /* @__PURE__ */ jsx28("span", { className: "text-sm text-muted-foreground", children: description })
4821
+ /* @__PURE__ */ jsxs30("div", { className: "flex flex-col items-start", children: [
4822
+ /* @__PURE__ */ jsx36("span", { className: "font-medium", children: title }),
4823
+ /* @__PURE__ */ jsx36("span", { className: "text-sm text-muted-foreground", children: description })
3786
4824
  ] }),
3787
- /* @__PURE__ */ jsx28(
4825
+ /* @__PURE__ */ jsx36(
3788
4826
  IconChevronDown3,
3789
4827
  {
3790
4828
  className: `h-4 w-4 transition-transform ${isOpen ? "rotate-180" : ""}`
@@ -3793,7 +4831,7 @@ function ChangePhoneForm() {
3793
4831
  ]
3794
4832
  }
3795
4833
  ),
3796
- /* @__PURE__ */ jsx28(CollapsibleContent3, { children: showOtp ? /* @__PURE__ */ jsx28(
4834
+ /* @__PURE__ */ jsx36(CollapsibleContent3, { children: showOtp ? /* @__PURE__ */ jsx36(
3797
4835
  VerifyChangePhoneForm,
3798
4836
  {
3799
4837
  phone: newPhone,
@@ -3801,7 +4839,7 @@ function ChangePhoneForm() {
3801
4839
  onSuccess: handleVerifySuccess,
3802
4840
  onCancel: handleCancel
3803
4841
  }
3804
- ) : /* @__PURE__ */ jsx28(
4842
+ ) : /* @__PURE__ */ jsx36(
3805
4843
  RequestChangePhoneForm,
3806
4844
  {
3807
4845
  onSuccess: handleRequestSuccess,
@@ -3813,70 +4851,101 @@ function ChangePhoneForm() {
3813
4851
  }
3814
4852
 
3815
4853
  // src/components/profile/security.tsx
3816
- import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
4854
+ import { jsx as jsx37, jsxs as jsxs31 } from "react/jsx-runtime";
3817
4855
  function Security() {
3818
- return /* @__PURE__ */ jsxs25("div", { className: "p-6 space-y-6", children: [
3819
- /* @__PURE__ */ jsxs25("div", { children: [
3820
- /* @__PURE__ */ jsx29("h1", { className: "text-2xl font-semibold", children: "Security" }),
3821
- /* @__PURE__ */ jsx29("p", { className: "text-muted-foreground", children: "Manage your security settings" })
4856
+ const { user } = useSession();
4857
+ return /* @__PURE__ */ jsxs31("div", { className: "mx-auto flex w-full max-w-6xl flex-col gap-6", children: [
4858
+ /* @__PURE__ */ jsxs31("div", { className: "relative overflow-hidden rounded-[2rem] border border-border/60 bg-gradient-to-br from-background via-background to-amber-500/5 p-6 shadow-sm", children: [
4859
+ /* @__PURE__ */ jsx37("div", { className: "absolute left-0 top-0 h-32 w-32 rounded-full bg-primary/10 blur-3xl" }),
4860
+ /* @__PURE__ */ jsxs31("div", { className: "relative flex flex-col gap-4", children: [
4861
+ /* @__PURE__ */ jsxs31("div", { className: "flex flex-wrap gap-2", children: [
4862
+ /* @__PURE__ */ jsx37(Badge9, { variant: "outline", children: "Security center" }),
4863
+ /* @__PURE__ */ jsx37(Badge9, { variant: "secondary", children: user?.emailVerified || user?.phoneVerified ? "Recovery methods available" : "Add a recovery method" })
4864
+ ] }),
4865
+ /* @__PURE__ */ jsxs31("div", { className: "space-y-2", children: [
4866
+ /* @__PURE__ */ jsx37("h1", { className: "text-2xl font-semibold tracking-tight", children: "Security" }),
4867
+ /* @__PURE__ */ jsx37("p", { className: "max-w-2xl text-sm text-muted-foreground", children: "Password, email, and phone updates all live here. Keep recovery channels current so account recovery stays predictable." })
4868
+ ] })
4869
+ ] })
3822
4870
  ] }),
3823
- /* @__PURE__ */ jsxs25("div", { className: "space-y-4", children: [
3824
- /* @__PURE__ */ jsx29(ChangePasswordForm, {}),
3825
- /* @__PURE__ */ jsx29(ChangeEmailForm, {}),
3826
- /* @__PURE__ */ jsx29(ChangePhoneForm, {})
4871
+ /* @__PURE__ */ jsxs31("div", { className: "grid gap-4 lg:grid-cols-[0.85fr_1.4fr]", children: [
4872
+ /* @__PURE__ */ jsx37(Card3, { className: "rounded-[1.75rem] border-border/60 shadow-sm", children: /* @__PURE__ */ jsxs31(CardContent2, { className: "space-y-5 p-6", children: [
4873
+ /* @__PURE__ */ jsxs31("div", { className: "space-y-1", children: [
4874
+ /* @__PURE__ */ jsx37("div", { className: "text-sm font-medium text-muted-foreground", children: "Verification state" }),
4875
+ /* @__PURE__ */ jsx37("div", { className: "text-lg font-semibold", children: "Recovery readiness" })
4876
+ ] }),
4877
+ /* @__PURE__ */ jsx37(Separator2, {}),
4878
+ /* @__PURE__ */ jsxs31("div", { className: "space-y-3", children: [
4879
+ /* @__PURE__ */ jsxs31("div", { className: "rounded-2xl border border-border/60 bg-muted/20 p-4", children: [
4880
+ /* @__PURE__ */ jsx37("div", { className: "text-sm font-medium", children: "Email" }),
4881
+ /* @__PURE__ */ jsx37("div", { className: "mt-1 text-sm text-muted-foreground", children: user?.email ?? "No email added" }),
4882
+ /* @__PURE__ */ jsx37("div", { className: "mt-3", children: /* @__PURE__ */ jsx37(Badge9, { variant: "outline", children: user?.emailVerified ? "Verified" : "Unverified" }) })
4883
+ ] }),
4884
+ /* @__PURE__ */ jsxs31("div", { className: "rounded-2xl border border-border/60 bg-muted/20 p-4", children: [
4885
+ /* @__PURE__ */ jsx37("div", { className: "text-sm font-medium", children: "Phone" }),
4886
+ /* @__PURE__ */ jsx37("div", { className: "mt-1 text-sm text-muted-foreground", children: user?.phone ?? "No phone added" }),
4887
+ /* @__PURE__ */ jsx37("div", { className: "mt-3", children: /* @__PURE__ */ jsx37(Badge9, { variant: "outline", children: user?.phoneVerified ? "Verified" : "Unverified" }) })
4888
+ ] })
4889
+ ] })
4890
+ ] }) }),
4891
+ /* @__PURE__ */ jsxs31("div", { className: "space-y-4", children: [
4892
+ /* @__PURE__ */ jsx37(ChangePasswordForm, {}),
4893
+ /* @__PURE__ */ jsx37(ChangeEmailForm, {}),
4894
+ /* @__PURE__ */ jsx37(ChangePhoneForm, {})
4895
+ ] })
3827
4896
  ] })
3828
4897
  ] });
3829
4898
  }
3830
4899
 
3831
4900
  // src/components/skeletons/auth-form-skeleton.tsx
3832
- import { Skeleton as Skeleton2 } from "@mesob/ui/components";
3833
- import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
4901
+ import { Skeleton as Skeleton3 } from "@mesob/ui/components";
4902
+ import { jsx as jsx38, jsxs as jsxs32 } from "react/jsx-runtime";
3834
4903
  function AuthFormSkeleton() {
3835
- return /* @__PURE__ */ jsxs26("div", { className: "w-full max-w-md space-y-6 p-6", children: [
3836
- /* @__PURE__ */ jsxs26("div", { className: "space-y-2 text-center", children: [
3837
- /* @__PURE__ */ jsx30(Skeleton2, { className: "h-8 w-48 mx-auto" }),
3838
- /* @__PURE__ */ jsx30(Skeleton2, { className: "h-4 w-64 mx-auto" })
4904
+ return /* @__PURE__ */ jsxs32("div", { className: "w-full max-w-md space-y-6 p-6", children: [
4905
+ /* @__PURE__ */ jsxs32("div", { className: "space-y-2 text-center", children: [
4906
+ /* @__PURE__ */ jsx38(Skeleton3, { className: "h-8 w-48 mx-auto" }),
4907
+ /* @__PURE__ */ jsx38(Skeleton3, { className: "h-4 w-64 mx-auto" })
3839
4908
  ] }),
3840
- /* @__PURE__ */ jsxs26("div", { className: "space-y-4", children: [
3841
- /* @__PURE__ */ jsxs26("div", { className: "space-y-2", children: [
3842
- /* @__PURE__ */ jsx30(Skeleton2, { className: "h-4 w-24" }),
3843
- /* @__PURE__ */ jsx30(Skeleton2, { className: "h-10 w-full" })
4909
+ /* @__PURE__ */ jsxs32("div", { className: "space-y-4", children: [
4910
+ /* @__PURE__ */ jsxs32("div", { className: "space-y-2", children: [
4911
+ /* @__PURE__ */ jsx38(Skeleton3, { className: "h-4 w-24" }),
4912
+ /* @__PURE__ */ jsx38(Skeleton3, { className: "h-10 w-full" })
3844
4913
  ] }),
3845
- /* @__PURE__ */ jsxs26("div", { className: "space-y-2", children: [
3846
- /* @__PURE__ */ jsx30(Skeleton2, { className: "h-4 w-24" }),
3847
- /* @__PURE__ */ jsx30(Skeleton2, { className: "h-10 w-full" })
4914
+ /* @__PURE__ */ jsxs32("div", { className: "space-y-2", children: [
4915
+ /* @__PURE__ */ jsx38(Skeleton3, { className: "h-4 w-24" }),
4916
+ /* @__PURE__ */ jsx38(Skeleton3, { className: "h-10 w-full" })
3848
4917
  ] }),
3849
- /* @__PURE__ */ jsx30(Skeleton2, { className: "h-10 w-full" })
4918
+ /* @__PURE__ */ jsx38(Skeleton3, { className: "h-10 w-full" })
3850
4919
  ] }),
3851
- /* @__PURE__ */ jsxs26("div", { className: "space-y-2", children: [
3852
- /* @__PURE__ */ jsx30(Skeleton2, { className: "h-px w-full" }),
3853
- /* @__PURE__ */ jsx30(Skeleton2, { className: "h-4 w-32 mx-auto" })
4920
+ /* @__PURE__ */ jsxs32("div", { className: "space-y-2", children: [
4921
+ /* @__PURE__ */ jsx38(Skeleton3, { className: "h-px w-full" }),
4922
+ /* @__PURE__ */ jsx38(Skeleton3, { className: "h-4 w-32 mx-auto" })
3854
4923
  ] })
3855
4924
  ] });
3856
4925
  }
3857
4926
 
3858
4927
  // src/components/skeletons/profile-skeleton.tsx
3859
- import { Skeleton as Skeleton3 } from "@mesob/ui/components";
3860
- import { jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
4928
+ import { Skeleton as Skeleton4 } from "@mesob/ui/components";
4929
+ import { jsx as jsx39, jsxs as jsxs33 } from "react/jsx-runtime";
3861
4930
  function ProfileSkeleton() {
3862
- return /* @__PURE__ */ jsxs27("div", { className: "w-full max-w-4xl space-y-8 p-6", children: [
3863
- /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-6", children: [
3864
- /* @__PURE__ */ jsx31(Skeleton3, { className: "h-24 w-24 rounded-full" }),
3865
- /* @__PURE__ */ jsxs27("div", { className: "space-y-2 flex-1", children: [
3866
- /* @__PURE__ */ jsx31(Skeleton3, { className: "h-8 w-48" }),
3867
- /* @__PURE__ */ jsx31(Skeleton3, { className: "h-4 w-64" })
4931
+ return /* @__PURE__ */ jsxs33("div", { className: "w-full max-w-4xl space-y-8 p-6", children: [
4932
+ /* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-6", children: [
4933
+ /* @__PURE__ */ jsx39(Skeleton4, { className: "h-24 w-24 rounded-full" }),
4934
+ /* @__PURE__ */ jsxs33("div", { className: "space-y-2 flex-1", children: [
4935
+ /* @__PURE__ */ jsx39(Skeleton4, { className: "h-8 w-48" }),
4936
+ /* @__PURE__ */ jsx39(Skeleton4, { className: "h-4 w-64" })
3868
4937
  ] })
3869
4938
  ] }),
3870
- /* @__PURE__ */ jsx31("div", { className: "space-y-6", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs27("div", { className: "space-y-4", children: [
3871
- /* @__PURE__ */ jsx31(Skeleton3, { className: "h-6 w-32" }),
3872
- /* @__PURE__ */ jsxs27("div", { className: "space-y-3", children: [
3873
- /* @__PURE__ */ jsxs27("div", { className: "flex justify-between items-center", children: [
3874
- /* @__PURE__ */ jsx31(Skeleton3, { className: "h-4 w-24" }),
3875
- /* @__PURE__ */ jsx31(Skeleton3, { className: "h-4 w-32" })
4939
+ /* @__PURE__ */ jsx39("div", { className: "space-y-6", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs33("div", { className: "space-y-4", children: [
4940
+ /* @__PURE__ */ jsx39(Skeleton4, { className: "h-6 w-32" }),
4941
+ /* @__PURE__ */ jsxs33("div", { className: "space-y-3", children: [
4942
+ /* @__PURE__ */ jsxs33("div", { className: "flex justify-between items-center", children: [
4943
+ /* @__PURE__ */ jsx39(Skeleton4, { className: "h-4 w-24" }),
4944
+ /* @__PURE__ */ jsx39(Skeleton4, { className: "h-4 w-32" })
3876
4945
  ] }),
3877
- /* @__PURE__ */ jsxs27("div", { className: "flex justify-between items-center", children: [
3878
- /* @__PURE__ */ jsx31(Skeleton3, { className: "h-4 w-24" }),
3879
- /* @__PURE__ */ jsx31(Skeleton3, { className: "h-4 w-40" })
4946
+ /* @__PURE__ */ jsxs33("div", { className: "flex justify-between items-center", children: [
4947
+ /* @__PURE__ */ jsx39(Skeleton4, { className: "h-4 w-24" }),
4948
+ /* @__PURE__ */ jsx39(Skeleton4, { className: "h-4 w-40" })
3880
4949
  ] })
3881
4950
  ] })
3882
4951
  ] }, i)) })
@@ -3894,15 +4963,22 @@ export {
3894
4963
  AuthErrorBoundary,
3895
4964
  AuthFormSkeleton,
3896
4965
  DataTable,
4966
+ Deny,
3897
4967
  ErrorBoundary,
3898
4968
  ForgotPassword,
4969
+ Grant,
3899
4970
  MesobAuthProvider,
4971
+ PermissionSelector,
3900
4972
  Permissions,
3901
4973
  ProfileSkeleton,
3902
4974
  ResetPasswordForm,
4975
+ RoleDetailLayout,
4976
+ RoleDetailPage,
4977
+ RolePermissionsPage,
3903
4978
  Roles,
3904
4979
  Security,
3905
4980
  Sessions,
4981
+ SetPassword,
3906
4982
  SignIn,
3907
4983
  SignUp,
3908
4984
  TableSkeleton,