@mesob/auth-react 0.4.0 → 0.4.2
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.
- package/dist/chunk-35TCGAW3.js +98 -0
- package/dist/chunk-35TCGAW3.js.map +1 -0
- package/dist/chunk-3BZC4VVD.js +36 -0
- package/dist/chunk-3BZC4VVD.js.map +1 -0
- package/dist/chunk-45UCLKH2.js +188 -0
- package/dist/chunk-45UCLKH2.js.map +1 -0
- package/dist/chunk-55BMNC4S.js +115 -0
- package/dist/chunk-55BMNC4S.js.map +1 -0
- package/dist/chunk-5F5FZMHE.js +94 -0
- package/dist/chunk-5F5FZMHE.js.map +1 -0
- package/dist/chunk-5M7I7WNH.js +31 -0
- package/dist/chunk-5M7I7WNH.js.map +1 -0
- package/dist/chunk-72YRO3A7.js +288 -0
- package/dist/chunk-72YRO3A7.js.map +1 -0
- package/dist/chunk-7KXTL6NT.js +48 -0
- package/dist/chunk-7KXTL6NT.js.map +1 -0
- package/dist/chunk-AIMD6R6U.js +466 -0
- package/dist/chunk-AIMD6R6U.js.map +1 -0
- package/dist/chunk-BGSHXIHI.js +953 -0
- package/dist/chunk-BGSHXIHI.js.map +1 -0
- package/dist/chunk-BZ42QPXE.js +271 -0
- package/dist/chunk-BZ42QPXE.js.map +1 -0
- package/dist/chunk-C26NPUPI.js +272 -0
- package/dist/chunk-C26NPUPI.js.map +1 -0
- package/dist/chunk-C2KFZ57H.js +194 -0
- package/dist/chunk-C2KFZ57H.js.map +1 -0
- package/dist/chunk-C5ZW7FD2.js +46 -0
- package/dist/chunk-C5ZW7FD2.js.map +1 -0
- package/dist/chunk-DPH2PHK3.js +32 -0
- package/dist/chunk-DPH2PHK3.js.map +1 -0
- package/dist/chunk-EQ4346FE.js +139 -0
- package/dist/chunk-EQ4346FE.js.map +1 -0
- package/dist/chunk-FAHN63DA.js +535 -0
- package/dist/chunk-FAHN63DA.js.map +1 -0
- package/dist/chunk-FFR5UHTS.js +99 -0
- package/dist/chunk-FFR5UHTS.js.map +1 -0
- package/dist/chunk-FHOLUOOZ.js +164 -0
- package/dist/chunk-FHOLUOOZ.js.map +1 -0
- package/dist/chunk-G2AW2H36.js +11 -0
- package/dist/chunk-G2AW2H36.js.map +1 -0
- package/dist/chunk-G7SCXCCM.js +89 -0
- package/dist/chunk-G7SCXCCM.js.map +1 -0
- package/dist/chunk-GP7GIUI3.js +64 -0
- package/dist/chunk-GP7GIUI3.js.map +1 -0
- package/dist/chunk-GRT6EBR6.js +93 -0
- package/dist/chunk-GRT6EBR6.js.map +1 -0
- package/dist/chunk-GXKBVCVS.js +102 -0
- package/dist/chunk-GXKBVCVS.js.map +1 -0
- package/dist/chunk-HB2RZTHS.js +338 -0
- package/dist/chunk-HB2RZTHS.js.map +1 -0
- package/dist/chunk-HOO2VLNM.js +305 -0
- package/dist/chunk-HOO2VLNM.js.map +1 -0
- package/dist/chunk-II5MLBSB.js +183 -0
- package/dist/chunk-II5MLBSB.js.map +1 -0
- package/dist/chunk-ISNNPMF7.js +95 -0
- package/dist/chunk-ISNNPMF7.js.map +1 -0
- package/dist/chunk-JB6XVST4.js +141 -0
- package/dist/chunk-JB6XVST4.js.map +1 -0
- package/dist/chunk-JUHBVG5Q.js +303 -0
- package/dist/chunk-JUHBVG5Q.js.map +1 -0
- package/dist/chunk-JZZJCBAE.js +118 -0
- package/dist/chunk-JZZJCBAE.js.map +1 -0
- package/dist/chunk-KWG4DSB5.js +55 -0
- package/dist/chunk-KWG4DSB5.js.map +1 -0
- package/dist/chunk-L4CGIO2I.js +265 -0
- package/dist/chunk-L4CGIO2I.js.map +1 -0
- package/dist/chunk-LNG736CV.js +19 -0
- package/dist/chunk-LNG736CV.js.map +1 -0
- package/dist/chunk-LSYKVFJA.js +98 -0
- package/dist/chunk-LSYKVFJA.js.map +1 -0
- package/dist/chunk-LZR4YUDV.js +107 -0
- package/dist/chunk-LZR4YUDV.js.map +1 -0
- package/dist/chunk-MELNS4QH.js +255 -0
- package/dist/chunk-MELNS4QH.js.map +1 -0
- package/dist/chunk-MS2JUZ3N.js +94 -0
- package/dist/chunk-MS2JUZ3N.js.map +1 -0
- package/dist/chunk-NEO72TMH.js +32 -0
- package/dist/chunk-NEO72TMH.js.map +1 -0
- package/dist/chunk-NJPNTAAT.js +68 -0
- package/dist/chunk-NJPNTAAT.js.map +1 -0
- package/dist/chunk-NPW7D2HZ.js +16 -0
- package/dist/chunk-NPW7D2HZ.js.map +1 -0
- package/dist/chunk-OAN4EXU4.js +310 -0
- package/dist/chunk-OAN4EXU4.js.map +1 -0
- package/dist/chunk-OFLSINVU.js +138 -0
- package/dist/chunk-OFLSINVU.js.map +1 -0
- package/dist/chunk-OHIIMUQC.js +286 -0
- package/dist/chunk-OHIIMUQC.js.map +1 -0
- package/dist/chunk-OQGJX37L.js +239 -0
- package/dist/chunk-OQGJX37L.js.map +1 -0
- package/dist/chunk-OYHH7HQG.js +65 -0
- package/dist/chunk-OYHH7HQG.js.map +1 -0
- package/dist/chunk-PSRIZMWJ.js +486 -0
- package/dist/chunk-PSRIZMWJ.js.map +1 -0
- package/dist/chunk-QNCE2B5O.js +23 -0
- package/dist/chunk-QNCE2B5O.js.map +1 -0
- package/dist/chunk-RLPZFLAS.js +23 -0
- package/dist/chunk-RLPZFLAS.js.map +1 -0
- package/dist/chunk-RT5C7IAE.js +38 -0
- package/dist/chunk-RT5C7IAE.js.map +1 -0
- package/dist/chunk-S3CXCCKL.js +272 -0
- package/dist/chunk-S3CXCCKL.js.map +1 -0
- package/dist/chunk-SOCZK4CV.js +69 -0
- package/dist/chunk-SOCZK4CV.js.map +1 -0
- package/dist/chunk-T6P7UHVP.js +34 -0
- package/dist/chunk-T6P7UHVP.js.map +1 -0
- package/dist/chunk-TFVBER3Y.js +52 -0
- package/dist/chunk-TFVBER3Y.js.map +1 -0
- package/dist/chunk-UXOZ2TME.js +104 -0
- package/dist/chunk-UXOZ2TME.js.map +1 -0
- package/dist/chunk-V2W3WPCZ.js +22 -0
- package/dist/chunk-V2W3WPCZ.js.map +1 -0
- package/dist/chunk-YZ264S2L.js +286 -0
- package/dist/chunk-YZ264S2L.js.map +1 -0
- package/dist/chunk-ZESFGO3K.js +28 -0
- package/dist/chunk-ZESFGO3K.js.map +1 -0
- package/dist/chunk-ZG6WFZHX.js +143 -0
- package/dist/chunk-ZG6WFZHX.js.map +1 -0
- package/dist/components/auth/auth-card.d.ts +3 -6
- package/dist/components/auth/auth-card.js +3 -7
- package/dist/components/auth/auth-card.js.map +1 -1
- package/dist/components/auth/auth-layout.d.ts +3 -6
- package/dist/components/auth/auth-layout.js +3 -28
- package/dist/components/auth/auth-layout.js.map +1 -1
- package/dist/components/auth/countdown.d.ts +2 -5
- package/dist/components/auth/countdown.js +5 -130
- package/dist/components/auth/countdown.js.map +1 -1
- package/dist/components/auth/forgot-password.d.ts +1 -5
- package/dist/components/auth/forgot-password.js +6 -365
- package/dist/components/auth/forgot-password.js.map +1 -1
- package/dist/components/auth/reset-password-form.d.ts +2 -5
- package/dist/components/auth/reset-password-form.js +6 -487
- package/dist/components/auth/reset-password-form.js.map +1 -1
- package/dist/components/auth/set-password.d.ts +2 -5
- package/dist/components/auth/set-password.js +7 -521
- package/dist/components/auth/set-password.js.map +1 -1
- package/dist/components/auth/sign-in.d.ts +2 -5
- package/dist/components/auth/sign-in.js +7 -561
- package/dist/components/auth/sign-in.js.map +1 -1
- package/dist/components/auth/sign-up.d.ts +2 -5
- package/dist/components/auth/sign-up.js +6 -511
- package/dist/components/auth/sign-up.js.map +1 -1
- package/dist/components/auth/verification-form.d.ts +13 -2
- package/dist/components/auth/verification-form.js +5 -217
- package/dist/components/auth/verification-form.js.map +1 -1
- package/dist/components/auth/verify-email.d.ts +2 -5
- package/dist/components/auth/verify-email.js +8 -527
- package/dist/components/auth/verify-email.js.map +1 -1
- package/dist/components/auth/verify-phone.d.ts +2 -5
- package/dist/components/auth/verify-phone.js +8 -532
- package/dist/components/auth/verify-phone.js.map +1 -1
- package/dist/components/authorization/deny.d.ts +3 -6
- package/dist/components/authorization/deny.js +4 -47
- package/dist/components/authorization/deny.js.map +1 -1
- package/dist/components/authorization/grant.d.ts +3 -6
- package/dist/components/authorization/grant.js +4 -52
- package/dist/components/authorization/grant.js.map +1 -1
- package/dist/components/error-boundary.d.ts +6 -10
- package/dist/components/error-boundary.js +4 -43
- package/dist/components/error-boundary.js.map +1 -1
- package/dist/components/iam/permission-selector.d.ts +3 -6
- package/dist/components/iam/permission-selector.js +3 -116
- package/dist/components/iam/permission-selector.js.map +1 -1
- package/dist/components/iam/permissions-page.d.ts +1 -0
- package/dist/components/iam/permissions-page.js +10 -0
- package/dist/components/iam/permissions-page.js.map +1 -0
- package/dist/components/iam/permissions.d.ts +1 -5
- package/dist/components/iam/permissions.js +5 -198
- package/dist/components/iam/permissions.js.map +1 -1
- package/dist/components/iam/role-detail-layout.d.ts +3 -6
- package/dist/components/iam/role-detail-layout.js +3 -131
- package/dist/components/iam/role-detail-layout.js.map +1 -1
- package/dist/components/iam/role-detail-page.d.ts +2 -5
- package/dist/components/iam/role-detail-page.js +3 -223
- package/dist/components/iam/role-detail-page.js.map +1 -1
- package/dist/components/iam/role-permissions-page.d.ts +2 -5
- package/dist/components/iam/role-permissions-page.js +4 -391
- package/dist/components/iam/role-permissions-page.js.map +1 -1
- package/dist/components/iam/roles-page.d.ts +1 -0
- package/dist/components/iam/roles-page.js +13 -0
- package/dist/components/iam/roles-page.js.map +1 -0
- package/dist/components/iam/roles.d.ts +1 -5
- package/dist/components/iam/roles.js +5 -218
- package/dist/components/iam/roles.js.map +1 -1
- package/dist/components/iam/sessions-page.d.ts +1 -0
- package/dist/components/iam/sessions-page.js +12 -0
- package/dist/components/iam/sessions-page.js.map +1 -0
- package/dist/components/iam/sessions.d.ts +1 -5
- package/dist/components/iam/sessions.js +5 -198
- package/dist/components/iam/sessions.js.map +1 -1
- package/dist/components/iam/tenants-page.d.ts +1 -0
- package/dist/components/iam/tenants-page.js +13 -0
- package/dist/components/iam/tenants-page.js.map +1 -0
- package/dist/components/iam/tenants.d.ts +1 -5
- package/dist/components/iam/tenants.js +5 -204
- package/dist/components/iam/tenants.js.map +1 -1
- package/dist/components/iam/users-page.d.ts +1 -0
- package/dist/components/iam/users-page.js +13 -0
- package/dist/components/iam/users-page.js.map +1 -0
- package/dist/components/iam/users.d.ts +1 -5
- package/dist/components/iam/users.js +5 -207
- package/dist/components/iam/users.js.map +1 -1
- package/dist/components/profile/account.d.ts +1 -5
- package/dist/components/profile/account.js +4 -151
- package/dist/components/profile/account.js.map +1 -1
- package/dist/components/profile/change-email-form.d.ts +1 -5
- package/dist/components/profile/change-email-form.js +9 -735
- package/dist/components/profile/change-email-form.js.map +1 -1
- package/dist/components/profile/change-password-form.d.ts +1 -5
- package/dist/components/profile/change-password-form.js +3 -262
- package/dist/components/profile/change-password-form.js.map +1 -1
- package/dist/components/profile/change-phone-form.d.ts +1 -5
- package/dist/components/profile/change-phone-form.js +10 -772
- package/dist/components/profile/change-phone-form.js.map +1 -1
- package/dist/components/profile/change-profile.d.ts +3 -7
- package/dist/components/profile/change-profile.js +2 -40
- package/dist/components/profile/change-profile.js.map +1 -1
- package/dist/components/profile/otp-verification-modal.d.ts +2 -5
- package/dist/components/profile/otp-verification-modal.js +6 -266
- package/dist/components/profile/otp-verification-modal.js.map +1 -1
- package/dist/components/profile/profile-layout.d.ts +4 -0
- package/dist/components/profile/profile-layout.js +10 -0
- package/dist/components/profile/profile-layout.js.map +1 -0
- package/dist/components/profile/request-change-email-form.d.ts +2 -5
- package/dist/components/profile/request-change-email-form.js +4 -285
- package/dist/components/profile/request-change-email-form.js.map +1 -1
- package/dist/components/profile/request-change-phone-form.d.ts +2 -5
- package/dist/components/profile/request-change-phone-form.js +5 -323
- package/dist/components/profile/request-change-phone-form.js.map +1 -1
- package/dist/components/profile/security.d.ts +1 -5
- package/dist/components/profile/security.js +15 -1508
- package/dist/components/profile/security.js.map +1 -1
- package/dist/components/profile/verify-change-email-form.d.ts +2 -5
- package/dist/components/profile/verify-change-email-form.js +7 -407
- package/dist/components/profile/verify-change-email-form.js.map +1 -1
- package/dist/components/profile/verify-change-phone-form.d.ts +2 -5
- package/dist/components/profile/verify-change-phone-form.js +7 -411
- package/dist/components/profile/verify-change-phone-form.js.map +1 -1
- package/dist/components/shared/data-table.d.ts +5 -8
- package/dist/components/shared/data-table.js +3 -79
- package/dist/components/shared/data-table.js.map +1 -1
- package/dist/components/skeletons/auth-form-skeleton.d.ts +1 -5
- package/dist/components/skeletons/auth-form-skeleton.js +3 -27
- package/dist/components/skeletons/auth-form-skeleton.js.map +1 -1
- package/dist/components/skeletons/profile-skeleton.d.ts +1 -5
- package/dist/components/skeletons/profile-skeleton.js +3 -28
- package/dist/components/skeletons/profile-skeleton.js.map +1 -1
- package/dist/components/skeletons/table-skeleton.d.ts +2 -5
- package/dist/components/skeletons/table-skeleton.js +3 -34
- package/dist/components/skeletons/table-skeleton.js.map +1 -1
- package/dist/constants/auth.error.codes.d.ts +5 -0
- package/dist/hooks/use-session-cookie-name.d.ts +1 -0
- package/dist/hooks/use-translator.d.ts +1 -0
- package/dist/index.d.ts +50 -92
- package/dist/index.js +147 -4936
- package/dist/index.js.map +1 -1
- package/dist/lib/query-options.d.ts +10 -0
- package/dist/lib/translations.d.ts +3 -0
- package/dist/pages/auth/forgot-password.d.ts +3 -7
- package/dist/pages/auth/forgot-password.js +8 -770
- package/dist/pages/auth/forgot-password.js.map +1 -1
- package/dist/pages/auth/layout.d.ts +3 -7
- package/dist/pages/auth/layout.js +13 -536
- package/dist/pages/auth/layout.js.map +1 -1
- package/dist/pages/auth/reset-password.d.ts +4 -7
- package/dist/pages/auth/reset-password.js +8 -888
- package/dist/pages/auth/reset-password.js.map +1 -1
- package/dist/pages/auth/set-password.d.ts +4 -7
- package/dist/pages/auth/set-password.js +9 -927
- package/dist/pages/auth/set-password.js.map +1 -1
- package/dist/pages/auth/sign-in.d.ts +4 -7
- package/dist/pages/auth/sign-in.js +9 -967
- package/dist/pages/auth/sign-in.js.map +1 -1
- package/dist/pages/auth/sign-up.d.ts +4 -7
- package/dist/pages/auth/sign-up.js +8 -915
- package/dist/pages/auth/sign-up.js.map +1 -1
- package/dist/pages/auth/verify-email.d.ts +4 -7
- package/dist/pages/auth/verify-email.js +10 -922
- package/dist/pages/auth/verify-email.js.map +1 -1
- package/dist/pages/auth/verify-phone.d.ts +4 -7
- package/dist/pages/auth/verify-phone.js +10 -927
- package/dist/pages/auth/verify-phone.js.map +1 -1
- package/dist/pages/iam/permissions/_components/permission-card.d.ts +6 -0
- package/dist/pages/iam/permissions/_components/permissions-data.d.ts +7 -0
- package/dist/pages/iam/permissions/_components/permissions-list.d.ts +14 -0
- package/dist/pages/iam/permissions.d.ts +1 -5
- package/dist/pages/iam/permissions.js +4 -302
- package/dist/pages/iam/permissions.js.map +1 -1
- package/dist/pages/iam/role-detail-layout.d.ts +3 -6
- package/dist/pages/iam/role-detail-layout.js +5 -132
- package/dist/pages/iam/role-detail-layout.js.map +1 -1
- package/dist/pages/iam/role-detail.d.ts +4 -7
- package/dist/pages/iam/role-detail.js +5 -224
- package/dist/pages/iam/role-detail.js.map +1 -1
- package/dist/pages/iam/role-permissions.d.ts +4 -7
- package/dist/pages/iam/role-permissions.js +6 -392
- package/dist/pages/iam/role-permissions.js.map +1 -1
- package/dist/pages/iam/role-users.d.ts +4 -7
- package/dist/pages/iam/role-users.js +9 -808
- package/dist/pages/iam/role-users.js.map +1 -1
- package/dist/pages/iam/roles/_components/role-card.d.ts +7 -0
- package/dist/pages/iam/roles/_components/role-form.d.ts +9 -0
- package/dist/pages/iam/roles/_components/role-selector.d.ts +11 -0
- package/dist/pages/iam/roles/_components/roles-data.d.ts +16 -0
- package/dist/pages/iam/roles/_components/roles-list.d.ts +15 -0
- package/dist/pages/iam/roles/users/_components/role-users-page.d.ts +5 -0
- package/dist/pages/iam/roles.d.ts +1 -5
- package/dist/pages/iam/roles.js +7 -678
- package/dist/pages/iam/roles.js.map +1 -1
- package/dist/pages/iam/sessions/_components/session-card.d.ts +6 -0
- package/dist/pages/iam/sessions/_components/sessions-data.d.ts +7 -0
- package/dist/pages/iam/sessions/_components/sessions-list.d.ts +14 -0
- package/dist/pages/iam/sessions.d.ts +1 -5
- package/dist/pages/iam/sessions.js +6 -309
- package/dist/pages/iam/sessions.js.map +1 -1
- package/dist/pages/iam/shared/navigation.d.ts +8 -0
- package/dist/pages/iam/shared/page-helpers.d.ts +12 -0
- package/dist/pages/iam/tenant-detail.d.ts +2 -5
- package/dist/pages/iam/tenant-detail.js +6 -174
- package/dist/pages/iam/tenant-detail.js.map +1 -1
- package/dist/pages/iam/tenants/_components/tenant-card.d.ts +6 -0
- package/dist/pages/iam/tenants/_components/tenant-form.d.ts +9 -0
- package/dist/pages/iam/tenants/_components/tenant-selector.d.ts +13 -0
- package/dist/pages/iam/tenants/_components/tenants-data.d.ts +12 -0
- package/dist/pages/iam/tenants/_components/tenants-list.d.ts +15 -0
- package/dist/pages/iam/tenants/tenant-detail-page-content.d.ts +5 -0
- package/dist/pages/iam/tenants.d.ts +1 -5
- package/dist/pages/iam/tenants.js +7 -604
- package/dist/pages/iam/tenants.js.map +1 -1
- package/dist/pages/iam/user-activity.d.ts +2 -5
- package/dist/pages/iam/user-activity.js +9 -838
- package/dist/pages/iam/user-activity.js.map +1 -1
- package/dist/pages/iam/user-detail-layout.d.ts +3 -6
- package/dist/pages/iam/user-detail-layout.js +5 -93
- package/dist/pages/iam/user-detail-layout.js.map +1 -1
- package/dist/pages/iam/user-detail.d.ts +2 -5
- package/dist/pages/iam/user-detail.js +5 -92
- package/dist/pages/iam/user-detail.js.map +1 -1
- package/dist/pages/iam/users/_components/bulk-invite-user-form.d.ts +6 -0
- package/dist/pages/iam/users/_components/invite-user-form.d.ts +6 -0
- package/dist/pages/iam/users/_components/invite-user-shared.d.ts +25 -0
- package/dist/pages/iam/users/_components/user-card.d.ts +6 -0
- package/dist/pages/iam/users/_components/user-detail-layout-content.d.ts +6 -0
- package/dist/pages/iam/users/_components/user-detail-page-content.d.ts +5 -0
- package/dist/pages/iam/users/_components/user-form.d.ts +9 -0
- package/dist/pages/iam/users/_components/user-selector.d.ts +12 -0
- package/dist/pages/iam/users/_components/users-data.d.ts +22 -0
- package/dist/pages/iam/users/_components/users-list.d.ts +15 -0
- package/dist/pages/iam/users/activity/_components/role-section.d.ts +3 -0
- package/dist/pages/iam/users/activity/user-activity-page-content.d.ts +5 -0
- package/dist/pages/iam/users.d.ts +1 -5
- package/dist/pages/iam/users.js +7 -1269
- package/dist/pages/iam/users.js.map +1 -1
- package/dist/pages/profile/_components/profile-sidebar.d.ts +1 -0
- package/dist/pages/profile/account.d.ts +1 -5
- package/dist/pages/profile/account.js +9 -158
- package/dist/pages/profile/account.js.map +1 -1
- package/dist/pages/profile/layout.d.ts +1 -8
- package/dist/pages/profile/layout.js +5 -128
- package/dist/pages/profile/layout.js.map +1 -1
- package/dist/pages/profile/security.d.ts +1 -5
- package/dist/pages/profile/security.js +20 -1515
- package/dist/pages/profile/security.js.map +1 -1
- package/dist/provider.d.ts +53 -0
- package/dist/{types-g9QcNRxT.d.ts → types.d.ts} +33 -12
- package/dist/utils/cookie.d.ts +2 -0
- package/dist/utils/custom-fetch.d.ts +2 -0
- package/dist/utils/handle-error.d.ts +7 -0
- package/dist/utils/normalize-phone.d.ts +1 -0
- package/package.json +4 -4
- package/dist/verification-form-ipSRTtQB.d.ts +0 -22
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/pages/iam/users/activity/user-activity-page-content.tsx","../../../src/pages/iam/users/activity/_components/role-section.tsx","../../../src/pages/iam/roles/_components/role-selector.tsx","../../../src/provider.tsx","../../../src/utils/cookie.ts","../../../src/pages/iam/shared/navigation.tsx","../../../src/lib/query-options.ts","../../../src/pages/iam/shared/page-helpers.tsx","../../../src/pages/iam/roles/_components/role-card.tsx","../../../src/pages/iam/roles/_components/roles-data.ts","../../../src/pages/iam/roles/_components/roles-list.tsx","../../../src/pages/iam/roles/_components/role-form.tsx","../../../src/pages/iam/user-activity.tsx"],"sourcesContent":["'use client';\n\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Section,\n} from '@mesob/ui/components';\nimport { IconCalendar } from '@tabler/icons-react';\nimport { RoleSection } from './_components/role-section';\n\ntype UserActivityPageContentProps = {\n userId: string;\n};\n\nexport function UserActivityPageContent({\n userId,\n}: UserActivityPageContentProps) {\n if (!userId) {\n return null;\n }\n\n return (\n <div className=\"space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle>Activity</CardTitle>\n </CardHeader>\n <CardContent className=\"flex items-center gap-2 text-muted-foreground text-sm\">\n <IconCalendar className=\"h-4 w-4\" />\n Activity (placeholder)\n </CardContent>\n </Card>\n <RoleSection userId={userId} />\n <Section title=\"Permissions\">test</Section>\n <Section title=\"Groups\">test</Section>\n </div>\n );\n}\n","'use client';\n\nimport {\n Button,\n EntityEmptyState,\n EntityLoadingState,\n EntitySection,\n useEntitySectionState,\n} from '@mesob/ui/components';\nimport { IconPlus, IconShield } from '@tabler/icons-react';\nimport { useMemo, useState } from 'react';\nimport { RoleSelector } from '../../../roles/_components/role-selector';\nimport type { Role } from '../../../roles/_components/roles-data';\nimport { str } from '../../../roles/_components/roles-data';\nimport { RolesList } from '../../../roles/_components/roles-list';\nimport {\n authApi$,\n defaultEntityQueryOptions,\n} from '../../../shared/page-helpers';\n\nconst LIMIT = 100;\nconst TABLE_COLUMN_COUNT = 4;\n\nfunction filterAndSort(\n roles: Role[],\n search: string,\n sort: string,\n order: 'asc' | 'desc',\n) {\n let out = roles;\n if (search.trim()) {\n const q = search.trim().toLowerCase();\n out = out.filter(\n (r) =>\n str(r.name).toLowerCase().includes(q) ||\n r.code.toLowerCase().includes(q),\n );\n }\n const mult = order === 'asc' ? 1 : -1;\n const by = sort === 'code' ? 'code' : 'createdAt';\n out = [...out].sort((a, b) =>\n by === 'code'\n ? mult * a.code.localeCompare(b.code)\n : mult *\n (new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()),\n );\n return out;\n}\n\nexport function RoleSection({ userId }: { userId: string }) {\n const [open, setOpen] = useState(false);\n const sectionState = useEntitySectionState({\n defaultSort: 'createdAt',\n defaultOrder: 'desc',\n defaultPageSize: 10,\n filterOptions: [\n { label: 'All', value: '' },\n { label: 'By Code', value: 'code' },\n ],\n sortOptions: [\n { label: 'Created', value: 'createdAt' },\n { label: 'Updated', value: 'updatedAt' },\n { label: 'Code', value: 'code' },\n ],\n views: ['table', 'card'],\n });\n\n const { data, isPending, isFetching } = authApi$.useQuery(\n 'get',\n '/roles',\n { params: { query: { limit: LIMIT } } },\n { ...defaultEntityQueryOptions, enabled: open },\n );\n const isLoading = isPending || isFetching;\n const roles = data?.roles ?? [];\n\n const filtered = useMemo(\n () =>\n filterAndSort(\n roles,\n sectionState.search,\n sectionState.sort,\n sectionState.order,\n ),\n [roles, sectionState.search, sectionState.sort, sectionState.order],\n );\n const pageCount = Math.ceil(filtered.length / sectionState.pageSize) || 1;\n const pageIndex = Math.min(sectionState.page - 1, Math.max(0, pageCount - 1));\n const paginated = useMemo(\n () =>\n filtered.slice(\n pageIndex * sectionState.pageSize,\n pageIndex * sectionState.pageSize + sectionState.pageSize,\n ),\n [filtered, pageIndex, sectionState.pageSize],\n );\n\n return (\n <EntitySection\n title=\"Role\"\n state={sectionState}\n onOpenChange={setOpen}\n actions={\n <RoleSelector\n trigger={\n <Button variant=\"outline\" size=\"sm\">\n <IconPlus className=\"h-4 w-4\" />\n Add role\n </Button>\n }\n multiple\n onSelect={(roles) => {\n // TODO: assign roles to user; logging for now\n // biome-ignore lint/suspicious/noConsole: intentional for now\n console.log('Selected roles:', userId, roles);\n }}\n />\n }\n config={{\n searchPlaceholder: 'Search roles...',\n filterOptions: sectionState.filterOptions,\n sortOptions: sectionState.sortOptions,\n views: sectionState.views,\n }}\n >\n {(state) => (\n <>\n {isLoading && (\n <EntityLoadingState\n view={state.view as 'table' | 'card'}\n rowCount={state.pageSize}\n columnCount={TABLE_COLUMN_COUNT}\n cardCount={state.pageSize}\n />\n )}\n {!isLoading && filtered.length === 0 && (\n <EntityEmptyState\n icon={IconShield}\n entityName=\"role\"\n title=\"No roles\"\n description={\n roles.length === 0 ? 'No roles in tenant.' : 'No matches.'\n }\n />\n )}\n {!isLoading && filtered.length > 0 && (\n <RolesList\n data={paginated}\n view={state.view as 'table' | 'card'}\n pageIndex={pageIndex}\n pageSize={state.pageSize}\n pageCount={pageCount}\n totalRows={filtered.length}\n onPageChange={(p) => state.setPage(p + 1)}\n onPageSizeChange={(size) => {\n state.setPageSize(size);\n state.setPage(1);\n }}\n />\n )}\n </>\n )}\n </EntitySection>\n );\n}\n","'use client';\n\nimport {\n EntitySelector,\n type EntitySelectorColumn,\n type EntitySelectorConfig,\n useEntitySectionState,\n} from '@mesob/ui/components';\nimport { cn } from '@mesob/ui/lib/utils';\nimport { IconCalendar, IconShield } from '@tabler/icons-react';\nimport type { ReactNode } from 'react';\nimport type { paths } from '../../../../data/openapi';\nimport { authApi$, defaultEntityQueryOptions } from '../../shared/page-helpers';\nimport { RoleCard } from './role-card';\nimport type { Role } from './roles-data';\nimport { str } from './roles-data';\n\nfunction SelectableRoleCard({\n role,\n selected,\n onToggle,\n}: {\n role: Role;\n selected: boolean;\n onToggle: () => void;\n}) {\n return (\n // biome-ignore lint/a11y/useSemanticElements: div to avoid nested buttons from RoleCard\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onToggle}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n onToggle();\n }\n }}\n className={cn(\n 'cursor-pointer rounded-lg transition-shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n selected && 'ring-primary ring-2',\n )}\n >\n <RoleCard role={role} mode=\"static\" />\n </div>\n );\n}\n\nconst roleColumns: EntitySelectorColumn<Role>[] = [\n {\n key: 'role',\n header: 'Role',\n cell: (role) => (\n <>\n <p className=\"font-medium\">{str(role.name) || role.code}</p>\n <p className=\"text-sm text-muted-foreground\">{role.code}</p>\n </>\n ),\n },\n {\n key: 'description',\n header: 'Description',\n cell: (role) => (\n <span className=\"text-muted-foreground line-clamp-1 max-w-[200px]\">\n {str(role.description) || '—'}\n </span>\n ),\n },\n {\n key: 'created',\n header: 'Created',\n cell: (role) => (\n <div className=\"flex items-center gap-1 text-muted-foreground\">\n <IconCalendar className=\"h-4 w-4\" />\n {new Date(role.createdAt).toLocaleDateString()}\n </div>\n ),\n },\n];\n\ntype RoleSelectorProps = {\n trigger: ReactNode;\n multiple?: boolean;\n onSelect: (roles: Role[]) => void;\n modalSize?: 'sm' | 'md' | 'lg' | 'xl' | 'full';\n contentClassName?: string;\n};\n\nexport function RoleSelector({\n trigger,\n multiple = true,\n onSelect,\n modalSize = 'xl',\n contentClassName,\n}: RoleSelectorProps) {\n const state = useEntitySectionState({\n defaultSort: 'createdAt',\n defaultOrder: 'desc',\n defaultPageSize: 10,\n searchParamName: 'search',\n });\n const rolesQuery = state.queryConfig as {\n params: {\n query: NonNullable<paths['/roles']['get']['parameters']['query']>;\n };\n };\n\n const { data, isPending, isFetching } = authApi$.useQuery(\n 'get',\n '/roles',\n rolesQuery,\n defaultEntityQueryOptions,\n );\n\n const roles = data?.roles ?? [];\n\n const config: EntitySelectorConfig<Role> = {\n title: 'Select role(s)',\n modalSize,\n contentClassName,\n multiple,\n entityName: 'role',\n entityIcon: IconShield,\n columns: roleColumns,\n columnCount: 3,\n getItemLabel: (role) => str(role.name) || role.code,\n searchPlaceholder: 'Search roles...',\n wrapHeaderInCard: false,\n filterOptions: [\n { label: 'All', value: '' },\n { label: 'By Code', value: 'code' },\n ],\n sortOptions: [\n { label: 'Created', value: 'createdAt' },\n { label: 'Updated', value: 'updatedAt' },\n { label: 'Code', value: 'code' },\n ],\n showViewToggle: false,\n renderCard: (role, selected, onToggle) => (\n <SelectableRoleCard role={role} selected={selected} onToggle={onToggle} />\n ),\n };\n\n return (\n <EntitySelector<Role>\n trigger={trigger}\n config={config}\n onSelect={onSelect}\n items={roles}\n total={data?.total}\n isLoading={isPending || isFetching}\n state={state}\n />\n );\n}\n","'use client';\n\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { deepmerge } from 'deepmerge-ts';\nimport createFetchClient from 'openapi-fetch';\nimport createClient from 'openapi-react-query';\nimport type { ReactNode } from 'react';\nimport { createContext, useContext, useMemo, useState } from 'react';\nimport type { paths } from './data/openapi';\nimport { createTranslator } from './lib/translations';\nimport {\n type AuthClientConfig,\n type AuthResponse,\n defaultAuthClientConfig,\n type Session,\n type User,\n} from './types';\nimport { getSessionCookieName } from './utils/cookie';\nimport { createCustomFetch } from './utils/custom-fetch';\n\n// biome-ignore lint/suspicious/noExplicitAny: OpenAPI hooks type\ntype OpenApiHooks = any;\n\n// --- Utility: Check if running on server ---\nfunction isServer(): boolean {\n return typeof document === 'undefined';\n}\n\n/**\n * @deprecated Cookie is httpOnly and cannot be read client-side.\n * Use `useSession().isAuthenticated` instead.\n * This function always returns false on client.\n */\nexport function hasAuthCookie(_cookieName: string): boolean {\n // Cookie is httpOnly, can't check client-side\n // Always return false - use useSession() for auth status\n return false;\n}\n\n// --- Types ---\nexport type AuthStatus = 'loading' | 'authenticated' | 'unauthenticated';\n\ntype AuthState = {\n user: User | null;\n session: Session | null;\n status: AuthStatus;\n error: Error | null;\n};\n\ntype SessionContextValue = AuthState & {\n isLoading: boolean;\n isAuthenticated: boolean;\n refresh: () => Promise<void>;\n signOut: () => Promise<void>;\n};\n\ntype ApiContextValue = {\n hooks: OpenApiHooks;\n setAuth: (auth: AuthResponse) => void;\n clearAuth: () => void;\n refresh: () => Promise<void>;\n};\n\ntype ConfigContextValue = {\n config: AuthClientConfig;\n cookieName: string;\n t: (key: string, params?: Record<string, string | number>) => string;\n};\n\nconst SessionContext = createContext<SessionContextValue | null>(null);\nconst ApiContext = createContext<ApiContextValue | null>(null);\nconst ConfigContext = createContext<ConfigContextValue | null>(null);\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n refetchOnWindowFocus: false,\n },\n },\n});\n\n// --- Hooks ---\n\n/**\n * Get session state including user, session, and auth status.\n * - `status`: 'loading' | 'authenticated' | 'unauthenticated'\n * - `isLoading`: true while fetching session\n * - `isAuthenticated`: true if user and session exist\n */\nexport function useSession(): SessionContextValue {\n const context = useContext(SessionContext);\n if (!context) {\n throw new Error('useSession must be used within MesobAuthProvider');\n }\n return context;\n}\n\nexport function useApi(): ApiContextValue {\n const context = useContext(ApiContext);\n if (!context) {\n throw new Error('useApi must be used within MesobAuthProvider');\n }\n return context;\n}\n\nexport function useConfig(): ConfigContextValue {\n const context = useContext(ConfigContext);\n if (!context) {\n throw new Error('useConfig must be used within MesobAuthProvider');\n }\n return context;\n}\n\n/**\n * @deprecated Cookie is httpOnly, can't be checked client-side.\n * Use `useSession().isAuthenticated` instead.\n */\nexport function useHasAuthCookie(): boolean {\n const { status } = useSession();\n return status === 'authenticated' || status === 'loading';\n}\n\n// --- Provider ---\n\ntype MesobAuthProviderProps = {\n config: AuthClientConfig;\n children: ReactNode;\n};\n\nexport function MesobAuthProvider({\n config,\n children,\n}: MesobAuthProviderProps) {\n const mergedConfig = useMemo(\n () =>\n deepmerge(\n { ...defaultAuthClientConfig } as Partial<AuthClientConfig>,\n config,\n ) as AuthClientConfig,\n [config],\n );\n\n const api = useMemo(\n () =>\n createFetchClient<paths>({\n baseUrl: mergedConfig.baseURL,\n fetch: createCustomFetch(mergedConfig),\n }),\n [mergedConfig],\n );\n\n const hooks = useMemo(() => createClient(api), [api]);\n const cookieName = useMemo(\n () => getSessionCookieName(mergedConfig),\n [mergedConfig],\n );\n\n return (\n <QueryClientProvider client={queryClient}>\n <AuthStateProvider\n config={mergedConfig}\n hooks={hooks}\n cookieName={cookieName}\n >\n {children}\n </AuthStateProvider>\n </QueryClientProvider>\n );\n}\n\ntype AuthStateProviderProps = {\n config: AuthClientConfig;\n hooks: OpenApiHooks;\n cookieName: string;\n children: ReactNode;\n};\n\nfunction AuthStateProvider({\n config,\n hooks,\n cookieName,\n children,\n}: AuthStateProviderProps) {\n // Manual override for sign-out / sign-in\n const [override, setOverride] = useState<AuthState | null>(null);\n\n // Always fetch session - cookie is httpOnly, can't check client-side\n // Server will read the cookie and return user/session if valid\n const {\n data: sessionData,\n isLoading,\n isFetched,\n error: sessionError,\n refetch,\n } = hooks.useQuery(\n 'get',\n '/session',\n {},\n {\n enabled: !(override || isServer()),\n refetchOnMount: false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n retry: false,\n gcTime: 0,\n staleTime: 0,\n },\n );\n\n // Derive state directly - no useEffect\n const user = override?.user ?? sessionData?.user ?? null;\n const session = override?.session ?? sessionData?.session ?? null;\n const error = override?.error ?? (sessionError as Error | null);\n\n // Check error status code\n const errorStatus = (() => {\n if (!sessionError) {\n return null;\n }\n const err = sessionError as { status?: number };\n return err.status ?? null;\n })();\n\n // Check if error is a network/connection error\n const isNetworkError = (() => {\n if (!sessionError) {\n return false;\n }\n const error = sessionError as Error & { cause?: unknown; data?: unknown };\n const errorMessage =\n error.message || String(error) || JSON.stringify(error);\n // Network errors: TypeError, DOMException, or fetch failures\n if (\n error instanceof TypeError ||\n error instanceof DOMException ||\n error.name === 'TypeError' ||\n errorMessage.includes('Failed to fetch') ||\n errorMessage.includes('ERR_CONNECTION_REFUSED') ||\n errorMessage.includes('NetworkError') ||\n errorMessage.includes('Network request failed') ||\n errorMessage.includes('fetch failed')\n ) {\n return true;\n }\n // Check error cause\n if (error.cause) {\n const causeStr = String(error.cause);\n if (\n causeStr.includes('Failed to fetch') ||\n causeStr.includes('ERR_CONNECTION_REFUSED') ||\n causeStr.includes('NetworkError')\n ) {\n return true;\n }\n }\n return false;\n })();\n\n // Compute status\n // biome-ignore lint: Status determination requires multiple checks\n const status: AuthStatus = (() => {\n if (override) {\n return override.status;\n }\n if (isServer()) {\n return 'loading';\n }\n if (user && session) {\n return 'authenticated';\n }\n // Check for network errors or auth errors first - allow auth page to show\n if (isNetworkError || errorStatus === 401) {\n return 'unauthenticated';\n }\n // If we have an error but it's not a network error, still check loading state\n if (sessionError && !isNetworkError && errorStatus !== 401) {\n if (errorStatus && errorStatus >= 500) {\n return 'authenticated';\n }\n // Other errors mean unauthenticated\n if (isFetched) {\n return 'unauthenticated';\n }\n }\n if (isLoading || !isFetched) {\n return 'loading';\n }\n if (isFetched && !user && !session) {\n return 'unauthenticated';\n }\n return 'unauthenticated';\n })();\n\n const signOutMutation = hooks.useMutation('post', '/sign-out');\n const t = createTranslator(config.messages || {});\n\n const setAuth = (auth: AuthResponse) => {\n setOverride({\n user: auth.user,\n session: auth.session,\n status: 'authenticated',\n error: null,\n });\n };\n\n const clearAuth = () => {\n setOverride({\n user: null,\n session: null,\n status: 'unauthenticated',\n error: null,\n });\n };\n\n const refresh = async () => {\n setOverride(null);\n await refetch();\n };\n\n const signOut = async () => {\n try {\n await signOutMutation.mutateAsync({});\n } finally {\n clearAuth();\n }\n };\n\n return (\n <ConfigContext.Provider value={{ config, cookieName, t }}>\n <ApiContext.Provider value={{ hooks, setAuth, clearAuth, refresh }}>\n <SessionContext.Provider\n value={{\n user,\n session,\n status,\n error,\n isLoading: status === 'loading',\n isAuthenticated: status === 'authenticated',\n refresh,\n signOut,\n }}\n >\n {children}\n </SessionContext.Provider>\n </ApiContext.Provider>\n </ConfigContext.Provider>\n );\n}\n","import type { AuthClientConfig } from '../types';\n\nconst isProduction =\n typeof process !== 'undefined' && process.env.NODE_ENV === 'production';\n\nexport const getSessionCookieName = (config: AuthClientConfig): string => {\n const prefix = config.cookiePrefix || '';\n const baseName = 'session_token';\n if (prefix) {\n return `${prefix}_${baseName}`;\n }\n return isProduction ? '__Host-session_token' : baseName;\n};\n","'use client';\n\nimport { useMesob } from '@mesob/ui/providers';\nimport type { ReactNode } from 'react';\nimport { useConfig } from '../../../provider';\n\ntype AppLinkProps = React.ComponentProps<'a'> & {\n href: string;\n children: ReactNode;\n};\n\nexport function AppLink({ href, children, ...props }: AppLinkProps) {\n const mesob = useMesob();\n const Link = mesob?.linkComponent ?? mesob?.navigation?.Link;\n const locale = mesob?.locale;\n\n if (Link) {\n return (\n <Link href={href} {...(locale ? ({ locale } as object) : {})} {...props}>\n {children}\n </Link>\n );\n }\n\n return (\n <a href={href} {...props}>\n {children}\n </a>\n );\n}\n\nexport function useNavigate() {\n const { config } = useConfig();\n\n return (href: string) => {\n if (config.navigation?.onNavigate) {\n config.navigation.onNavigate(href);\n return;\n }\n\n if (typeof window !== 'undefined') {\n window.location.href = href;\n }\n };\n}\n","import { keepPreviousData } from '@tanstack/react-query';\n\nexport const defaultEntityQueryOptions = {\n refetchOnMount: false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n staleTime: 60 * 1000,\n gcTime: 5 * 60 * 1000,\n placeholderData: keepPreviousData,\n retry: 1,\n};\n","'use client';\n\nimport type { ComponentProps } from 'react';\nimport { useApi } from '../../../provider';\nimport { AppLink, useNavigate } from './navigation';\n\nexport { defaultEntityQueryOptions } from '../../../lib/query-options';\n\ntype HookArgs = [string, string, ...unknown[]];\n\nexport const authApi$ = {\n useQuery(...args: HookArgs) {\n const { hooks } = useApi();\n\n return hooks.useQuery(...args);\n },\n useMutation(...args: HookArgs) {\n const { hooks } = useApi();\n\n return hooks.useMutation(...args);\n },\n};\n\nexport function Link(props: ComponentProps<typeof AppLink>) {\n return <AppLink {...props} />;\n}\n\nexport function useRouter() {\n const navigate = useNavigate();\n\n return {\n push: navigate,\n };\n}\n","'use client';\n\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n} from '@mesob/ui/components';\nimport { IconDots, IconExternalLink } from '@tabler/icons-react';\nimport { useRouter } from '../../shared/page-helpers';\nimport type { Role } from './roles-data';\nimport { str } from './roles-data';\n\ntype RoleCardProps = {\n role: Role;\n mode?: 'navigate' | 'static';\n};\n\nexport function RoleCard({ role, mode = 'navigate' }: RoleCardProps) {\n const router = useRouter();\n const canNavigate = mode === 'navigate';\n\n return (\n <Card className=\"group transition-shadow hover:shadow-md\">\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-start justify-between\">\n <button\n type=\"button\"\n onClick={() => {\n if (canNavigate) {\n router.push(`/iam/roles/${role.id}`);\n }\n }}\n className=\"text-left font-semibold hover:text-primary hover:underline\"\n >\n {str(role.name) || role.code}\n </button>\n {canNavigate ? (\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 opacity-0 transition-opacity group-hover:opacity-100\"\n />\n }\n >\n <IconDots className=\"h-4 w-4\" />\n </DropdownMenuTrigger>\n <DropdownMenuPortal>\n <DropdownMenuContent>\n <DropdownMenuItem\n onClick={() => router.push(`/iam/roles/${role.id}`)}\n >\n <IconExternalLink className=\"mr-2 h-4 w-4\" />\n Open\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenuPortal>\n </DropdownMenu>\n ) : null}\n </div>\n <Badge variant=\"outline\" className=\"text-xs\">\n {role.code}\n </Badge>\n </CardHeader>\n <CardContent>\n <div className=\"mb-3 flex flex-wrap gap-2\">\n {role.isSystem ? <Badge>System</Badge> : null}\n <Badge variant=\"secondary\">\n {role.permissionCount ?? role.permissionIds?.length ?? 0}{' '}\n permissions\n </Badge>\n <Badge variant=\"outline\">{role.userCount ?? 0} users</Badge>\n </div>\n {str(role.description) && (\n <p className=\"line-clamp-2 text-sm text-muted-foreground\">\n {str(role.description)}\n </p>\n )}\n <p className=\"mt-2 text-xs text-muted-foreground\">\n Created {new Date(role.createdAt).toLocaleDateString()}\n </p>\n </CardContent>\n </Card>\n );\n}\n","export type Role = {\n id: string;\n tenantId: string;\n createdAt: string;\n updatedAt: string;\n name?: unknown;\n description?: unknown;\n code: string;\n isSystem?: boolean;\n isEditable?: boolean;\n isDeletable?: boolean;\n permissionIds?: string[];\n permissionCount?: number;\n userCount?: number;\n};\n\nexport function str(v: unknown): string {\n if (v == null) {\n return '';\n }\n if (typeof v === 'string') {\n return v;\n }\n if (typeof v === 'object' && v !== null && 'en' in v) {\n const o = v as { en?: string; am?: string };\n return (o.en ?? o.am ?? '') as string;\n }\n return String(v);\n}\n","'use client';\n\nimport {\n Badge,\n DataTableAction,\n DataTablePagination,\n DisplayTable,\n EntityEmptyState,\n EntityLoadingState,\n Tbody,\n Td,\n Th,\n Thead,\n Tr,\n} from '@mesob/ui/components';\nimport { IconCalendar, IconShield } from '@tabler/icons-react';\nimport { useState } from 'react';\nimport { Link } from '../../shared/page-helpers';\nimport { RoleCard } from './role-card';\nimport { RoleForm } from './role-form';\nimport type { Role } from './roles-data';\nimport { str } from './roles-data';\n\nconst TABLE_COLUMN_COUNT = 5;\n\ntype RolesListProps = {\n data: Role[];\n isLoading?: boolean;\n view: 'table' | 'card';\n pageIndex: number;\n pageSize: number;\n pageCount: number;\n totalRows: number;\n onPageChange: (page: number) => void;\n onPageSizeChange: (size: number) => void;\n onCreateNew?: () => void;\n};\n\nexport function RolesList({\n data,\n isLoading,\n view,\n pageIndex,\n pageSize,\n pageCount,\n totalRows,\n onPageChange,\n onPageSizeChange,\n onCreateNew,\n}: RolesListProps) {\n const [drawerRole, setDrawerRole] = useState<Role | null>(null);\n\n if (isLoading) {\n return (\n <EntityLoadingState\n view={view}\n rowCount={pageSize}\n columnCount={TABLE_COLUMN_COUNT}\n cardCount={pageSize}\n />\n );\n }\n if (totalRows === 0) {\n return (\n <EntityEmptyState\n icon={IconShield}\n entityName=\"role\"\n title=\"No roles yet\"\n description=\"Create your first role to get started.\"\n onAction={onCreateNew}\n />\n );\n }\n if (view === 'table') {\n return (\n <div className=\"space-y-4\">\n {drawerRole ? (\n <RoleForm\n mode=\"edit\"\n roleId={drawerRole.id}\n open\n onClose={() => setDrawerRole(null)}\n onSuccess={() => setDrawerRole(null)}\n />\n ) : null}\n <DisplayTable withTableBorder>\n <Thead>\n <Tr>\n <Th>Role</Th>\n <Th>Description</Th>\n <Th>Access</Th>\n <Th>Created</Th>\n <Th className=\"w-[50px]\" />\n </Tr>\n </Thead>\n <Tbody>\n {data.map((role) => (\n <Tr key={role.id} className=\"group\">\n <Td>\n <Link\n href={`/iam/roles/${role.id}`}\n className=\"block text-left font-medium hover:text-primary hover:underline cursor-pointer\"\n >\n <p>{str(role.name) || role.code}</p>\n <Badge variant=\"outline\" className=\"mt-1 text-xs\">\n {role.code}\n </Badge>\n </Link>\n </Td>\n <Td>\n <span className=\"text-muted-foreground line-clamp-1 max-w-[200px]\">\n {str(role.description) || '—'}\n </span>\n </Td>\n <Td>\n <div className=\"flex flex-wrap gap-2\">\n {role.isSystem ? <Badge>System</Badge> : null}\n <Badge variant=\"secondary\">\n {role.permissionCount ?? role.permissionIds?.length ?? 0}{' '}\n permissions\n </Badge>\n </div>\n </Td>\n <Td>\n <div className=\"flex items-center gap-1 text-muted-foreground\">\n <IconCalendar className=\"h-4 w-4\" />\n {new Date(role.createdAt).toLocaleDateString()}\n </div>\n </Td>\n <Td>\n <DataTableAction onClick={() => setDrawerRole(role)} />\n </Td>\n </Tr>\n ))}\n </Tbody>\n </DisplayTable>\n <DataTablePagination\n pageIndex={pageIndex}\n pageSize={pageSize}\n pageCount={pageCount}\n totalRows={totalRows}\n onPageChange={onPageChange}\n onPageSizeChange={onPageSizeChange}\n />\n </div>\n );\n }\n return (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n {data.map((r) => (\n <RoleCard key={r.id} role={r} />\n ))}\n </div>\n <DataTablePagination\n pageIndex={pageIndex}\n pageSize={pageSize}\n pageCount={pageCount}\n totalRows={totalRows}\n onPageChange={onPageChange}\n onPageSizeChange={onPageSizeChange}\n />\n </div>\n );\n}\n","'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n EntityDrawer,\n EntityFormActions,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n LocaleInputText,\n LocaleInputTextarea,\n Skeleton,\n} from '@mesob/ui/components';\nimport { useLocaleConfig, useLocaleSchemas } from '@mesob/ui/providers';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useEffect, useMemo } from 'react';\nimport type { Resolver } from 'react-hook-form';\nimport { useForm, useWatch } from 'react-hook-form';\nimport { z } from 'zod';\nimport { authApi$ } from '../../shared/page-helpers';\n\ntype RoleFormData = {\n name: Record<string, string>;\n code: string;\n description: Record<string, string>;\n permissionIds: string[];\n};\n\ntype RoleFormProps = {\n mode: 'new' | 'edit';\n roleId?: string;\n open: boolean;\n onClose: () => void;\n onSuccess?: () => void;\n};\n\nexport function RoleForm({\n mode,\n roleId,\n open,\n onClose,\n onSuccess,\n}: RoleFormProps) {\n const qc = useQueryClient();\n const { localeInputDefault, requiredSchema, optionalSchema } =\n useLocaleSchemas();\n const { defaultLanguage } = useLocaleConfig();\n const schema = useMemo(\n () =>\n z.object({\n name: requiredSchema,\n code: z.string().min(1, 'Code is required'),\n description: optionalSchema,\n permissionIds: z.array(z.string()),\n }),\n [requiredSchema, optionalSchema],\n );\n const defaults: RoleFormData = useMemo(\n () => ({\n name: { ...localeInputDefault },\n code: '',\n description: { ...localeInputDefault },\n permissionIds: [],\n }),\n [localeInputDefault],\n );\n\n const { data, isLoading } = authApi$.useQuery(\n 'get',\n '/roles/{id}',\n { params: { path: { id: roleId ?? '' } } },\n { enabled: mode === 'edit' && !!roleId },\n );\n const create = authApi$.useMutation('post', '/roles', {\n onSuccess: () => qc.invalidateQueries({ queryKey: ['get', '/roles'] }),\n });\n const update = authApi$.useMutation('put', '/roles/{id}', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/roles'] });\n if (roleId) {\n qc.invalidateQueries({ queryKey: ['get', '/roles/{id}'] });\n }\n },\n });\n const del = authApi$.useMutation('delete', '/roles/{id}', {\n onSuccess: () => qc.invalidateQueries({ queryKey: ['get', '/roles'] }),\n });\n\n const form = useForm<RoleFormData>({\n resolver: zodResolver(schema) as Resolver<RoleFormData>,\n defaultValues: defaults,\n });\n\n const { reset, formState, control, register, setValue } = form;\n const nameVal = useWatch({ control, name: 'name' });\n const codeVal = useWatch({ control, name: 'code' });\n\n useEffect(() => {\n const nameDefault =\n typeof nameVal === 'object' &&\n nameVal !== null &&\n defaultLanguage in nameVal\n ? ((nameVal as Record<string, string>)[defaultLanguage] ?? '')\n : '';\n if (\n mode === 'new' &&\n typeof nameDefault === 'string' &&\n nameDefault.trim().length > 0 &&\n !codeVal\n ) {\n const code = nameDefault\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '');\n if (code) {\n setValue('code', code);\n }\n }\n }, [mode, nameVal, setValue, codeVal, defaultLanguage]);\n\n useEffect(() => {\n if (!open) {\n return;\n }\n if (mode === 'edit' && data?.role && !isLoading) {\n const r = data.role;\n reset({\n name: (r.name ?? {}) as RoleFormData['name'],\n code: r.code,\n description: (r.description ?? {}) as RoleFormData['description'],\n permissionIds: r.permissionIds ?? [],\n });\n } else {\n reset({ ...defaults, permissionIds: [] });\n }\n }, [mode, data, open, isLoading, reset, defaults]);\n\n const onSubmit = form.handleSubmit(async (d) => {\n const body = {\n name: d.name,\n code: d.code,\n description: d.description ?? undefined,\n permissionIds: d.permissionIds,\n };\n if (mode === 'new') {\n await create.mutateAsync({ body });\n } else if (roleId) {\n await update.mutateAsync({\n params: { path: { id: roleId } },\n body,\n });\n }\n onSuccess?.();\n onClose();\n });\n\n const onDelete = async () => {\n if (!roleId) {\n return;\n }\n await del.mutateAsync({ params: { path: { id: roleId } } });\n onSuccess?.();\n onClose();\n };\n\n const editable = mode === 'new' || data?.role?.isEditable !== false;\n\n return (\n <EntityDrawer\n title={mode === 'new' ? 'New role' : 'Edit role'}\n open={open}\n onClose={onClose}\n isDirty={formState.isDirty}\n size=\"md\"\n form={\n isLoading ? (\n <FormSkeleton />\n ) : (\n <Form {...form}>\n <form onSubmit={onSubmit} className=\"space-y-4\">\n <LocaleInputText\n label=\"Name\"\n field=\"name\"\n required\n register={register}\n errors={formState.errors}\n placeholder=\"e.g. Administrator\"\n disabled={!editable}\n />\n <FormField\n control={control}\n name=\"code\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n Code <span className=\"text-destructive\">*</span>\n </FormLabel>\n <FormControl>\n <Input\n placeholder=\"e.g. admin\"\n disabled={!editable}\n {...field}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <LocaleInputTextarea\n label=\"Description\"\n field=\"description\"\n register={register}\n errors={formState.errors}\n placeholder=\"Description\"\n rows={3}\n disabled={!editable}\n />\n </form>\n </Form>\n )\n }\n actions={\n <EntityFormActions\n mode={mode}\n onSubmit={onSubmit}\n onReset={mode === 'new' ? () => reset(defaults) : undefined}\n onDelete={mode === 'edit' ? onDelete : undefined}\n isSubmitting={create.isPending || update.isPending}\n isDeleting={del.isPending}\n disabled={isLoading || !editable}\n itemName=\"role\"\n />\n }\n />\n );\n}\n\nfunction FormSkeleton() {\n return (\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-16\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-14\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-20 w-full\" />\n </div>\n </div>\n );\n}\n","import { UserActivityPageContent } from './users/activity/user-activity-page-content';\n\ntype UserActivityPageProps = {\n params: Promise<{ id: string }>;\n};\n\nexport default async function UserActivityPage({\n params,\n}: UserActivityPageProps) {\n const { id } = await params;\n\n return <UserActivityPageContent userId={id} />;\n}\n"],"mappings":"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","names":["Card","CardContent","CardHeader","IconCalendar","Button","EntityEmptyState","EntityLoadingState","useEntitySectionState","IconShield","useMemo","useState","jsx","Link","jsx","jsx","jsx","jsxs","Badge","IconCalendar","IconShield","useState","useMemo","jsx","jsxs","useMemo","jsx","jsxs","useState","IconShield","Badge","IconCalendar","Fragment","jsx","jsxs","TABLE_COLUMN_COUNT","useState","useEntitySectionState","useMemo","Button","roles","EntityLoadingState","EntityEmptyState","IconShield","jsx","jsxs","Card","CardHeader","CardContent","IconCalendar","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/pages/iam/user-activity.tsx"],"sourcesContent":["import { UserActivityPageContent } from './users/activity/user-activity-page-content';\n\ntype UserActivityPageProps = {\n params: Promise<{ id: string }>;\n};\n\nexport default async function UserActivityPage({\n params,\n}: UserActivityPageProps) {\n const { id } = await params;\n\n return <UserActivityPageContent userId={id} />;\n}\n"],"mappings":";;;;;;;;;;AAWS;AALT,eAAO,iBAAwC;AAAA,EAC7C;AACF,GAA0B;AACxB,QAAM,EAAE,GAAG,IAAI,MAAM;AAErB,SAAO,oBAAC,2BAAwB,QAAQ,IAAI;AAC9C;","names":[]}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ReactNode } from 'react';
|
|
3
|
-
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
4
2
|
type UserDetailLayoutPageProps = {
|
|
5
3
|
children: ReactNode;
|
|
6
4
|
params: Promise<{
|
|
7
5
|
id: string;
|
|
8
6
|
}>;
|
|
9
7
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export { UserDetailLayoutPage as default };
|
|
8
|
+
export default function UserDetailLayoutPage({ children, params, }: UserDetailLayoutPageProps): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
9
|
+
export {};
|
|
@@ -1,104 +1,16 @@
|
|
|
1
|
-
// src/pages/iam/users/_components/user-detail-layout-content.tsx
|
|
2
|
-
import { toTitleCase } from "@mesob/common";
|
|
3
1
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
useBreadcrumbs
|
|
8
|
-
} from "@mesob/ui/components";
|
|
9
|
-
import { IconUser } from "@tabler/icons-react";
|
|
10
|
-
import { useMemo as useMemo2 } from "react";
|
|
11
|
-
|
|
12
|
-
// src/provider.tsx
|
|
13
|
-
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
14
|
-
import { deepmerge } from "deepmerge-ts";
|
|
15
|
-
import createFetchClient from "openapi-fetch";
|
|
16
|
-
import createClient from "openapi-react-query";
|
|
17
|
-
import { createContext, useContext, useMemo, useState } from "react";
|
|
18
|
-
|
|
19
|
-
// src/utils/cookie.ts
|
|
20
|
-
var isProduction = typeof process !== "undefined" && process.env.NODE_ENV === "production";
|
|
21
|
-
|
|
22
|
-
// src/provider.tsx
|
|
23
|
-
import { jsx } from "react/jsx-runtime";
|
|
24
|
-
var SessionContext = createContext(null);
|
|
25
|
-
var ApiContext = createContext(null);
|
|
26
|
-
var ConfigContext = createContext(null);
|
|
27
|
-
var queryClient = new QueryClient({
|
|
28
|
-
defaultOptions: {
|
|
29
|
-
queries: {
|
|
30
|
-
refetchOnWindowFocus: false
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
function useApi() {
|
|
35
|
-
const context = useContext(ApiContext);
|
|
36
|
-
if (!context) {
|
|
37
|
-
throw new Error("useApi must be used within MesobAuthProvider");
|
|
38
|
-
}
|
|
39
|
-
return context;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// src/pages/iam/users/_components/user-detail-layout-content.tsx
|
|
43
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
44
|
-
function UserDetailLayoutContent({
|
|
45
|
-
userId,
|
|
46
|
-
children
|
|
47
|
-
}) {
|
|
48
|
-
const { hooks } = useApi();
|
|
49
|
-
const { data, isLoading } = hooks.useQuery(
|
|
50
|
-
"get",
|
|
51
|
-
"/users/{id}",
|
|
52
|
-
{ params: { path: { id: userId } } },
|
|
53
|
-
{ enabled: !!userId }
|
|
54
|
-
);
|
|
55
|
-
const user = data?.user;
|
|
56
|
-
const title = toTitleCase(user?.fullName || userId || "User");
|
|
57
|
-
useBreadcrumbs({
|
|
58
|
-
items: [
|
|
59
|
-
{ label: "Home", href: "/dashboard" },
|
|
60
|
-
{ label: "IAM", href: "/iam" },
|
|
61
|
-
{ label: "Users", href: "/iam/users" },
|
|
62
|
-
{ label: title }
|
|
63
|
-
]
|
|
64
|
-
});
|
|
65
|
-
const tabs = useMemo2(
|
|
66
|
-
() => [
|
|
67
|
-
{ value: "detail", name: "Detail", href: `/iam/users/${userId}` },
|
|
68
|
-
{
|
|
69
|
-
value: "activity",
|
|
70
|
-
name: "Activity",
|
|
71
|
-
href: `/iam/users/${userId}/activity`
|
|
72
|
-
}
|
|
73
|
-
],
|
|
74
|
-
[userId]
|
|
75
|
-
);
|
|
76
|
-
if (!userId) {
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
return /* @__PURE__ */ jsxs(PageContainer, { children: [
|
|
80
|
-
/* @__PURE__ */ jsx2(
|
|
81
|
-
EntityDetailHeader,
|
|
82
|
-
{
|
|
83
|
-
title,
|
|
84
|
-
icon: /* @__PURE__ */ jsx2(IconUser, {}),
|
|
85
|
-
tabs,
|
|
86
|
-
loading: isLoading,
|
|
87
|
-
actions: /* @__PURE__ */ jsx2(Button, { children: "Test Button" })
|
|
88
|
-
}
|
|
89
|
-
),
|
|
90
|
-
children
|
|
91
|
-
] });
|
|
92
|
-
}
|
|
2
|
+
UserDetailLayoutContent
|
|
3
|
+
} from "../../chunk-SOCZK4CV.js";
|
|
4
|
+
import "../../chunk-72YRO3A7.js";
|
|
93
5
|
|
|
94
6
|
// src/pages/iam/user-detail-layout.tsx
|
|
95
|
-
import { jsx
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
96
8
|
async function UserDetailLayoutPage({
|
|
97
9
|
children,
|
|
98
10
|
params
|
|
99
11
|
}) {
|
|
100
12
|
const { id } = await params;
|
|
101
|
-
return /* @__PURE__ */
|
|
13
|
+
return /* @__PURE__ */ jsx(UserDetailLayoutContent, { userId: id, children });
|
|
102
14
|
}
|
|
103
15
|
export {
|
|
104
16
|
UserDetailLayoutPage as default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/pages/iam/users/_components/user-detail-layout-content.tsx","../../../src/provider.tsx","../../../src/utils/cookie.ts","../../../src/pages/iam/user-detail-layout.tsx"],"sourcesContent":["'use client';\n\nimport { toTitleCase } from '@mesob/common';\nimport {\n Button,\n EntityDetailHeader,\n PageContainer,\n type TabItem,\n useBreadcrumbs,\n} from '@mesob/ui/components';\nimport { IconUser } from '@tabler/icons-react';\nimport { useMemo } from 'react';\nimport { useApi } from '../../../../provider';\n\ntype UserDetailLayoutContentProps = {\n userId: string;\n children: React.ReactNode;\n};\n\nexport function UserDetailLayoutContent({\n userId,\n children,\n}: UserDetailLayoutContentProps) {\n const { hooks } = useApi();\n const { data, isLoading } = hooks.useQuery(\n 'get',\n '/users/{id}',\n { params: { path: { id: userId } } },\n { enabled: !!userId },\n );\n const user = data?.user;\n\n const title = toTitleCase(user?.fullName || userId || 'User');\n\n useBreadcrumbs({\n items: [\n { label: 'Home', href: '/dashboard' },\n { label: 'IAM', href: '/iam' },\n { label: 'Users', href: '/iam/users' },\n { label: title },\n ],\n });\n\n const tabs: TabItem[] = useMemo(\n () => [\n { value: 'detail', name: 'Detail', href: `/iam/users/${userId}` },\n {\n value: 'activity',\n name: 'Activity',\n href: `/iam/users/${userId}/activity`,\n },\n ],\n [userId],\n );\n\n if (!userId) {\n return null;\n }\n\n return (\n <PageContainer>\n <EntityDetailHeader\n title={title}\n icon={<IconUser />}\n tabs={tabs}\n loading={isLoading}\n actions={<Button>Test Button</Button>}\n />\n {children}\n </PageContainer>\n );\n}\n","'use client';\n\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { deepmerge } from 'deepmerge-ts';\nimport createFetchClient from 'openapi-fetch';\nimport createClient from 'openapi-react-query';\nimport type { ReactNode } from 'react';\nimport { createContext, useContext, useMemo, useState } from 'react';\nimport type { paths } from './data/openapi';\nimport { createTranslator } from './lib/translations';\nimport {\n type AuthClientConfig,\n type AuthResponse,\n defaultAuthClientConfig,\n type Session,\n type User,\n} from './types';\nimport { getSessionCookieName } from './utils/cookie';\nimport { createCustomFetch } from './utils/custom-fetch';\n\n// biome-ignore lint/suspicious/noExplicitAny: OpenAPI hooks type\ntype OpenApiHooks = any;\n\n// --- Utility: Check if running on server ---\nfunction isServer(): boolean {\n return typeof document === 'undefined';\n}\n\n/**\n * @deprecated Cookie is httpOnly and cannot be read client-side.\n * Use `useSession().isAuthenticated` instead.\n * This function always returns false on client.\n */\nexport function hasAuthCookie(_cookieName: string): boolean {\n // Cookie is httpOnly, can't check client-side\n // Always return false - use useSession() for auth status\n return false;\n}\n\n// --- Types ---\nexport type AuthStatus = 'loading' | 'authenticated' | 'unauthenticated';\n\ntype AuthState = {\n user: User | null;\n session: Session | null;\n status: AuthStatus;\n error: Error | null;\n};\n\ntype SessionContextValue = AuthState & {\n isLoading: boolean;\n isAuthenticated: boolean;\n refresh: () => Promise<void>;\n signOut: () => Promise<void>;\n};\n\ntype ApiContextValue = {\n hooks: OpenApiHooks;\n setAuth: (auth: AuthResponse) => void;\n clearAuth: () => void;\n refresh: () => Promise<void>;\n};\n\ntype ConfigContextValue = {\n config: AuthClientConfig;\n cookieName: string;\n t: (key: string, params?: Record<string, string | number>) => string;\n};\n\nconst SessionContext = createContext<SessionContextValue | null>(null);\nconst ApiContext = createContext<ApiContextValue | null>(null);\nconst ConfigContext = createContext<ConfigContextValue | null>(null);\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n refetchOnWindowFocus: false,\n },\n },\n});\n\n// --- Hooks ---\n\n/**\n * Get session state including user, session, and auth status.\n * - `status`: 'loading' | 'authenticated' | 'unauthenticated'\n * - `isLoading`: true while fetching session\n * - `isAuthenticated`: true if user and session exist\n */\nexport function useSession(): SessionContextValue {\n const context = useContext(SessionContext);\n if (!context) {\n throw new Error('useSession must be used within MesobAuthProvider');\n }\n return context;\n}\n\nexport function useApi(): ApiContextValue {\n const context = useContext(ApiContext);\n if (!context) {\n throw new Error('useApi must be used within MesobAuthProvider');\n }\n return context;\n}\n\nexport function useConfig(): ConfigContextValue {\n const context = useContext(ConfigContext);\n if (!context) {\n throw new Error('useConfig must be used within MesobAuthProvider');\n }\n return context;\n}\n\n/**\n * @deprecated Cookie is httpOnly, can't be checked client-side.\n * Use `useSession().isAuthenticated` instead.\n */\nexport function useHasAuthCookie(): boolean {\n const { status } = useSession();\n return status === 'authenticated' || status === 'loading';\n}\n\n// --- Provider ---\n\ntype MesobAuthProviderProps = {\n config: AuthClientConfig;\n children: ReactNode;\n};\n\nexport function MesobAuthProvider({\n config,\n children,\n}: MesobAuthProviderProps) {\n const mergedConfig = useMemo(\n () =>\n deepmerge(\n { ...defaultAuthClientConfig } as Partial<AuthClientConfig>,\n config,\n ) as AuthClientConfig,\n [config],\n );\n\n const api = useMemo(\n () =>\n createFetchClient<paths>({\n baseUrl: mergedConfig.baseURL,\n fetch: createCustomFetch(mergedConfig),\n }),\n [mergedConfig],\n );\n\n const hooks = useMemo(() => createClient(api), [api]);\n const cookieName = useMemo(\n () => getSessionCookieName(mergedConfig),\n [mergedConfig],\n );\n\n return (\n <QueryClientProvider client={queryClient}>\n <AuthStateProvider\n config={mergedConfig}\n hooks={hooks}\n cookieName={cookieName}\n >\n {children}\n </AuthStateProvider>\n </QueryClientProvider>\n );\n}\n\ntype AuthStateProviderProps = {\n config: AuthClientConfig;\n hooks: OpenApiHooks;\n cookieName: string;\n children: ReactNode;\n};\n\nfunction AuthStateProvider({\n config,\n hooks,\n cookieName,\n children,\n}: AuthStateProviderProps) {\n // Manual override for sign-out / sign-in\n const [override, setOverride] = useState<AuthState | null>(null);\n\n // Always fetch session - cookie is httpOnly, can't check client-side\n // Server will read the cookie and return user/session if valid\n const {\n data: sessionData,\n isLoading,\n isFetched,\n error: sessionError,\n refetch,\n } = hooks.useQuery(\n 'get',\n '/session',\n {},\n {\n enabled: !(override || isServer()),\n refetchOnMount: false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n retry: false,\n gcTime: 0,\n staleTime: 0,\n },\n );\n\n // Derive state directly - no useEffect\n const user = override?.user ?? sessionData?.user ?? null;\n const session = override?.session ?? sessionData?.session ?? null;\n const error = override?.error ?? (sessionError as Error | null);\n\n // Check error status code\n const errorStatus = (() => {\n if (!sessionError) {\n return null;\n }\n const err = sessionError as { status?: number };\n return err.status ?? null;\n })();\n\n // Check if error is a network/connection error\n const isNetworkError = (() => {\n if (!sessionError) {\n return false;\n }\n const error = sessionError as Error & { cause?: unknown; data?: unknown };\n const errorMessage =\n error.message || String(error) || JSON.stringify(error);\n // Network errors: TypeError, DOMException, or fetch failures\n if (\n error instanceof TypeError ||\n error instanceof DOMException ||\n error.name === 'TypeError' ||\n errorMessage.includes('Failed to fetch') ||\n errorMessage.includes('ERR_CONNECTION_REFUSED') ||\n errorMessage.includes('NetworkError') ||\n errorMessage.includes('Network request failed') ||\n errorMessage.includes('fetch failed')\n ) {\n return true;\n }\n // Check error cause\n if (error.cause) {\n const causeStr = String(error.cause);\n if (\n causeStr.includes('Failed to fetch') ||\n causeStr.includes('ERR_CONNECTION_REFUSED') ||\n causeStr.includes('NetworkError')\n ) {\n return true;\n }\n }\n return false;\n })();\n\n // Compute status\n // biome-ignore lint: Status determination requires multiple checks\n const status: AuthStatus = (() => {\n if (override) {\n return override.status;\n }\n if (isServer()) {\n return 'loading';\n }\n if (user && session) {\n return 'authenticated';\n }\n // Check for network errors or auth errors first - allow auth page to show\n if (isNetworkError || errorStatus === 401) {\n return 'unauthenticated';\n }\n // If we have an error but it's not a network error, still check loading state\n if (sessionError && !isNetworkError && errorStatus !== 401) {\n if (errorStatus && errorStatus >= 500) {\n return 'authenticated';\n }\n // Other errors mean unauthenticated\n if (isFetched) {\n return 'unauthenticated';\n }\n }\n if (isLoading || !isFetched) {\n return 'loading';\n }\n if (isFetched && !user && !session) {\n return 'unauthenticated';\n }\n return 'unauthenticated';\n })();\n\n const signOutMutation = hooks.useMutation('post', '/sign-out');\n const t = createTranslator(config.messages || {});\n\n const setAuth = (auth: AuthResponse) => {\n setOverride({\n user: auth.user,\n session: auth.session,\n status: 'authenticated',\n error: null,\n });\n };\n\n const clearAuth = () => {\n setOverride({\n user: null,\n session: null,\n status: 'unauthenticated',\n error: null,\n });\n };\n\n const refresh = async () => {\n setOverride(null);\n await refetch();\n };\n\n const signOut = async () => {\n try {\n await signOutMutation.mutateAsync({});\n } finally {\n clearAuth();\n }\n };\n\n return (\n <ConfigContext.Provider value={{ config, cookieName, t }}>\n <ApiContext.Provider value={{ hooks, setAuth, clearAuth, refresh }}>\n <SessionContext.Provider\n value={{\n user,\n session,\n status,\n error,\n isLoading: status === 'loading',\n isAuthenticated: status === 'authenticated',\n refresh,\n signOut,\n }}\n >\n {children}\n </SessionContext.Provider>\n </ApiContext.Provider>\n </ConfigContext.Provider>\n );\n}\n","import type { AuthClientConfig } from '../types';\n\nconst isProduction =\n typeof process !== 'undefined' && process.env.NODE_ENV === 'production';\n\nexport const getSessionCookieName = (config: AuthClientConfig): string => {\n const prefix = config.cookiePrefix || '';\n const baseName = 'session_token';\n if (prefix) {\n return `${prefix}_${baseName}`;\n }\n return isProduction ? '__Host-session_token' : baseName;\n};\n","import type { ReactNode } from 'react';\nimport { UserDetailLayoutContent } from './users/_components/user-detail-layout-content';\n\ntype UserDetailLayoutPageProps = {\n children: ReactNode;\n params: Promise<{ id: string }>;\n};\n\nexport default async function UserDetailLayoutPage({\n children,\n params,\n}: UserDetailLayoutPageProps) {\n const { id } = await params;\n\n return (\n <UserDetailLayoutContent userId={id}>{children}</UserDetailLayoutContent>\n );\n}\n"],"mappings":";AAEA,SAAS,mBAAmB;AAC5B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AACP,SAAS,gBAAgB;AACzB,SAAS,WAAAA,gBAAe;;;ACTxB,SAAS,aAAa,2BAA2B;AACjD,SAAS,iBAAiB;AAC1B,OAAO,uBAAuB;AAC9B,OAAO,kBAAkB;AAEzB,SAAS,eAAe,YAAY,SAAS,gBAAgB;;;ACL7D,IAAM,eACJ,OAAO,YAAY,eAAe,QAAQ,IAAI,aAAa;;;AD4JvD;AA1FN,IAAM,iBAAiB,cAA0C,IAAI;AACrE,IAAM,aAAa,cAAsC,IAAI;AAC7D,IAAM,gBAAgB,cAAyC,IAAI;AAEnE,IAAM,cAAc,IAAI,YAAY;AAAA,EAClC,gBAAgB;AAAA,IACd,SAAS;AAAA,MACP,sBAAsB;AAAA,IACxB;AAAA,EACF;AACF,CAAC;AAkBM,SAAS,SAA0B;AACxC,QAAM,UAAU,WAAW,UAAU;AACrC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,SAAO;AACT;;;AD3CI,SAGU,OAAAC,MAHV;AAzCG,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AACF,GAAiC;AAC/B,QAAM,EAAE,MAAM,IAAI,OAAO;AACzB,QAAM,EAAE,MAAM,UAAU,IAAI,MAAM;AAAA,IAChC;AAAA,IACA;AAAA,IACA,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,EAAE;AAAA,IACnC,EAAE,SAAS,CAAC,CAAC,OAAO;AAAA,EACtB;AACA,QAAM,OAAO,MAAM;AAEnB,QAAM,QAAQ,YAAY,MAAM,YAAY,UAAU,MAAM;AAE5D,iBAAe;AAAA,IACb,OAAO;AAAA,MACL,EAAE,OAAO,QAAQ,MAAM,aAAa;AAAA,MACpC,EAAE,OAAO,OAAO,MAAM,OAAO;AAAA,MAC7B,EAAE,OAAO,SAAS,MAAM,aAAa;AAAA,MACrC,EAAE,OAAO,MAAM;AAAA,IACjB;AAAA,EACF,CAAC;AAED,QAAM,OAAkBC;AAAA,IACtB,MAAM;AAAA,MACJ,EAAE,OAAO,UAAU,MAAM,UAAU,MAAM,cAAc,MAAM,GAAG;AAAA,MAChE;AAAA,QACE,OAAO;AAAA,QACP,MAAM;AAAA,QACN,MAAM,cAAc,MAAM;AAAA,MAC5B;AAAA,IACF;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,SACE,qBAAC,iBACC;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAM,gBAAAA,KAAC,YAAS;AAAA,QAChB;AAAA,QACA,SAAS;AAAA,QACT,SAAS,gBAAAA,KAAC,UAAO,yBAAW;AAAA;AAAA,IAC9B;AAAA,IACC;AAAA,KACH;AAEJ;;;AGxDI,gBAAAE,YAAA;AAPJ,eAAO,qBAA4C;AAAA,EACjD;AAAA,EACA;AACF,GAA8B;AAC5B,QAAM,EAAE,GAAG,IAAI,MAAM;AAErB,SACE,gBAAAA,KAAC,2BAAwB,QAAQ,IAAK,UAAS;AAEnD;","names":["useMemo","jsx","useMemo","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/pages/iam/user-detail-layout.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { UserDetailLayoutContent } from './users/_components/user-detail-layout-content';\n\ntype UserDetailLayoutPageProps = {\n children: ReactNode;\n params: Promise<{ id: string }>;\n};\n\nexport default async function UserDetailLayoutPage({\n children,\n params,\n}: UserDetailLayoutPageProps) {\n const { id } = await params;\n\n return (\n <UserDetailLayoutContent userId={id}>{children}</UserDetailLayoutContent>\n );\n}\n"],"mappings":";;;;;;AAeI;AAPJ,eAAO,qBAA4C;AAAA,EACjD;AAAA,EACA;AACF,GAA8B;AAC5B,QAAM,EAAE,GAAG,IAAI,MAAM;AAErB,SACE,oBAAC,2BAAwB,QAAQ,IAAK,UAAS;AAEnD;","names":[]}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
|
|
3
1
|
type UserDetailPageProps = {
|
|
4
2
|
params: Promise<{
|
|
5
3
|
id: string;
|
|
6
4
|
}>;
|
|
7
5
|
};
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export { UserDetailPage as default };
|
|
6
|
+
export default function UserDetailPage({ params }: UserDetailPageProps): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
7
|
+
export {};
|
|
@@ -1,100 +1,13 @@
|
|
|
1
|
-
// src/pages/iam/users/_components/user-detail-page-content.tsx
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
CardHeader,
|
|
7
|
-
CardTitle
|
|
8
|
-
} from "@mesob/ui/components";
|
|
9
|
-
|
|
10
|
-
// src/provider.tsx
|
|
11
|
-
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
12
|
-
import { deepmerge } from "deepmerge-ts";
|
|
13
|
-
import createFetchClient from "openapi-fetch";
|
|
14
|
-
import createClient from "openapi-react-query";
|
|
15
|
-
import { createContext, useContext, useMemo, useState } from "react";
|
|
16
|
-
|
|
17
|
-
// src/utils/cookie.ts
|
|
18
|
-
var isProduction = typeof process !== "undefined" && process.env.NODE_ENV === "production";
|
|
19
|
-
|
|
20
|
-
// src/provider.tsx
|
|
21
|
-
import { jsx } from "react/jsx-runtime";
|
|
22
|
-
var SessionContext = createContext(null);
|
|
23
|
-
var ApiContext = createContext(null);
|
|
24
|
-
var ConfigContext = createContext(null);
|
|
25
|
-
var queryClient = new QueryClient({
|
|
26
|
-
defaultOptions: {
|
|
27
|
-
queries: {
|
|
28
|
-
refetchOnWindowFocus: false
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
function useApi() {
|
|
33
|
-
const context = useContext(ApiContext);
|
|
34
|
-
if (!context) {
|
|
35
|
-
throw new Error("useApi must be used within MesobAuthProvider");
|
|
36
|
-
}
|
|
37
|
-
return context;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// src/pages/iam/users/_components/user-detail-page-content.tsx
|
|
41
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
42
|
-
function UserDetailPageContent({ userId }) {
|
|
43
|
-
const { hooks } = useApi();
|
|
44
|
-
const { data, isLoading } = hooks.useQuery(
|
|
45
|
-
"get",
|
|
46
|
-
"/users/{id}",
|
|
47
|
-
{ params: { path: { id: userId } } },
|
|
48
|
-
{ enabled: !!userId }
|
|
49
|
-
);
|
|
50
|
-
const user = data?.user;
|
|
51
|
-
if (!userId) {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
if (isLoading || !user) {
|
|
55
|
-
return /* @__PURE__ */ jsx2("div", { className: "h-32 animate-pulse rounded-xl bg-muted mt-4" });
|
|
56
|
-
}
|
|
57
|
-
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
58
|
-
/* @__PURE__ */ jsx2(CardHeader, { children: /* @__PURE__ */ jsx2(CardTitle, { children: "User details" }) }),
|
|
59
|
-
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-2 text-sm", children: [
|
|
60
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
61
|
-
/* @__PURE__ */ jsx2("span", { className: "text-muted-foreground", children: "Name:" }),
|
|
62
|
-
" ",
|
|
63
|
-
user.fullName || "\u2014"
|
|
64
|
-
] }),
|
|
65
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
66
|
-
/* @__PURE__ */ jsx2("span", { className: "text-muted-foreground", children: "Email:" }),
|
|
67
|
-
" ",
|
|
68
|
-
user.email ?? "\u2014",
|
|
69
|
-
" ",
|
|
70
|
-
user.emailVerified && /* @__PURE__ */ jsx2(Badge, { variant: "outline", className: "text-xs", children: "Verified" })
|
|
71
|
-
] }),
|
|
72
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
73
|
-
/* @__PURE__ */ jsx2("span", { className: "text-muted-foreground", children: "Phone:" }),
|
|
74
|
-
" ",
|
|
75
|
-
user.phone ?? "\u2014",
|
|
76
|
-
" ",
|
|
77
|
-
user.phoneVerified && /* @__PURE__ */ jsx2(Badge, { variant: "outline", className: "text-xs", children: "Verified" })
|
|
78
|
-
] }),
|
|
79
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
80
|
-
/* @__PURE__ */ jsx2("span", { className: "text-muted-foreground", children: "Last sign in:" }),
|
|
81
|
-
" ",
|
|
82
|
-
user.lastSignInAt ? new Date(user.lastSignInAt).toLocaleString() : "Never"
|
|
83
|
-
] }),
|
|
84
|
-
user.roleCodes?.length ? /* @__PURE__ */ jsxs("p", { children: [
|
|
85
|
-
/* @__PURE__ */ jsx2("span", { className: "text-muted-foreground", children: "Roles:" }),
|
|
86
|
-
" ",
|
|
87
|
-
user.roleCodes.join(", ")
|
|
88
|
-
] }) : null
|
|
89
|
-
] })
|
|
90
|
-
] });
|
|
91
|
-
}
|
|
2
|
+
UserDetailPageContent
|
|
3
|
+
} from "../../chunk-NJPNTAAT.js";
|
|
4
|
+
import "../../chunk-72YRO3A7.js";
|
|
92
5
|
|
|
93
6
|
// src/pages/iam/user-detail.tsx
|
|
94
|
-
import { jsx
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
95
8
|
async function UserDetailPage({ params }) {
|
|
96
9
|
const { id } = await params;
|
|
97
|
-
return /* @__PURE__ */
|
|
10
|
+
return /* @__PURE__ */ jsx(UserDetailPageContent, { userId: id });
|
|
98
11
|
}
|
|
99
12
|
export {
|
|
100
13
|
UserDetailPage as default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/pages/iam/users/_components/user-detail-page-content.tsx","../../../src/provider.tsx","../../../src/utils/cookie.ts","../../../src/pages/iam/user-detail.tsx"],"sourcesContent":["'use client';\n\nimport {\n Badge,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from '@mesob/ui/components';\nimport { useApi } from '../../../../provider';\n\ntype UserDetailPageContentProps = {\n userId: string;\n};\n\nexport function UserDetailPageContent({ userId }: UserDetailPageContentProps) {\n const { hooks } = useApi();\n const { data, isLoading } = hooks.useQuery(\n 'get',\n '/users/{id}',\n { params: { path: { id: userId } } },\n { enabled: !!userId },\n );\n const user = data?.user;\n\n if (!userId) {\n return null;\n }\n if (isLoading || !user) {\n return <div className=\"h-32 animate-pulse rounded-xl bg-muted mt-4\" />;\n }\n\n return (\n <Card>\n <CardHeader>\n <CardTitle>User details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2 text-sm\">\n <p>\n <span className=\"text-muted-foreground\">Name:</span>{' '}\n {user.fullName || '—'}\n </p>\n <p>\n <span className=\"text-muted-foreground\">Email:</span>{' '}\n {user.email ?? '—'}{' '}\n {user.emailVerified && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Verified\n </Badge>\n )}\n </p>\n <p>\n <span className=\"text-muted-foreground\">Phone:</span>{' '}\n {user.phone ?? '—'}{' '}\n {user.phoneVerified && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Verified\n </Badge>\n )}\n </p>\n <p>\n <span className=\"text-muted-foreground\">Last sign in:</span>{' '}\n {user.lastSignInAt\n ? new Date(user.lastSignInAt).toLocaleString()\n : 'Never'}\n </p>\n {user.roleCodes?.length ? (\n <p>\n <span className=\"text-muted-foreground\">Roles:</span>{' '}\n {user.roleCodes.join(', ')}\n </p>\n ) : null}\n </CardContent>\n </Card>\n );\n}\n","'use client';\n\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { deepmerge } from 'deepmerge-ts';\nimport createFetchClient from 'openapi-fetch';\nimport createClient from 'openapi-react-query';\nimport type { ReactNode } from 'react';\nimport { createContext, useContext, useMemo, useState } from 'react';\nimport type { paths } from './data/openapi';\nimport { createTranslator } from './lib/translations';\nimport {\n type AuthClientConfig,\n type AuthResponse,\n defaultAuthClientConfig,\n type Session,\n type User,\n} from './types';\nimport { getSessionCookieName } from './utils/cookie';\nimport { createCustomFetch } from './utils/custom-fetch';\n\n// biome-ignore lint/suspicious/noExplicitAny: OpenAPI hooks type\ntype OpenApiHooks = any;\n\n// --- Utility: Check if running on server ---\nfunction isServer(): boolean {\n return typeof document === 'undefined';\n}\n\n/**\n * @deprecated Cookie is httpOnly and cannot be read client-side.\n * Use `useSession().isAuthenticated` instead.\n * This function always returns false on client.\n */\nexport function hasAuthCookie(_cookieName: string): boolean {\n // Cookie is httpOnly, can't check client-side\n // Always return false - use useSession() for auth status\n return false;\n}\n\n// --- Types ---\nexport type AuthStatus = 'loading' | 'authenticated' | 'unauthenticated';\n\ntype AuthState = {\n user: User | null;\n session: Session | null;\n status: AuthStatus;\n error: Error | null;\n};\n\ntype SessionContextValue = AuthState & {\n isLoading: boolean;\n isAuthenticated: boolean;\n refresh: () => Promise<void>;\n signOut: () => Promise<void>;\n};\n\ntype ApiContextValue = {\n hooks: OpenApiHooks;\n setAuth: (auth: AuthResponse) => void;\n clearAuth: () => void;\n refresh: () => Promise<void>;\n};\n\ntype ConfigContextValue = {\n config: AuthClientConfig;\n cookieName: string;\n t: (key: string, params?: Record<string, string | number>) => string;\n};\n\nconst SessionContext = createContext<SessionContextValue | null>(null);\nconst ApiContext = createContext<ApiContextValue | null>(null);\nconst ConfigContext = createContext<ConfigContextValue | null>(null);\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n refetchOnWindowFocus: false,\n },\n },\n});\n\n// --- Hooks ---\n\n/**\n * Get session state including user, session, and auth status.\n * - `status`: 'loading' | 'authenticated' | 'unauthenticated'\n * - `isLoading`: true while fetching session\n * - `isAuthenticated`: true if user and session exist\n */\nexport function useSession(): SessionContextValue {\n const context = useContext(SessionContext);\n if (!context) {\n throw new Error('useSession must be used within MesobAuthProvider');\n }\n return context;\n}\n\nexport function useApi(): ApiContextValue {\n const context = useContext(ApiContext);\n if (!context) {\n throw new Error('useApi must be used within MesobAuthProvider');\n }\n return context;\n}\n\nexport function useConfig(): ConfigContextValue {\n const context = useContext(ConfigContext);\n if (!context) {\n throw new Error('useConfig must be used within MesobAuthProvider');\n }\n return context;\n}\n\n/**\n * @deprecated Cookie is httpOnly, can't be checked client-side.\n * Use `useSession().isAuthenticated` instead.\n */\nexport function useHasAuthCookie(): boolean {\n const { status } = useSession();\n return status === 'authenticated' || status === 'loading';\n}\n\n// --- Provider ---\n\ntype MesobAuthProviderProps = {\n config: AuthClientConfig;\n children: ReactNode;\n};\n\nexport function MesobAuthProvider({\n config,\n children,\n}: MesobAuthProviderProps) {\n const mergedConfig = useMemo(\n () =>\n deepmerge(\n { ...defaultAuthClientConfig } as Partial<AuthClientConfig>,\n config,\n ) as AuthClientConfig,\n [config],\n );\n\n const api = useMemo(\n () =>\n createFetchClient<paths>({\n baseUrl: mergedConfig.baseURL,\n fetch: createCustomFetch(mergedConfig),\n }),\n [mergedConfig],\n );\n\n const hooks = useMemo(() => createClient(api), [api]);\n const cookieName = useMemo(\n () => getSessionCookieName(mergedConfig),\n [mergedConfig],\n );\n\n return (\n <QueryClientProvider client={queryClient}>\n <AuthStateProvider\n config={mergedConfig}\n hooks={hooks}\n cookieName={cookieName}\n >\n {children}\n </AuthStateProvider>\n </QueryClientProvider>\n );\n}\n\ntype AuthStateProviderProps = {\n config: AuthClientConfig;\n hooks: OpenApiHooks;\n cookieName: string;\n children: ReactNode;\n};\n\nfunction AuthStateProvider({\n config,\n hooks,\n cookieName,\n children,\n}: AuthStateProviderProps) {\n // Manual override for sign-out / sign-in\n const [override, setOverride] = useState<AuthState | null>(null);\n\n // Always fetch session - cookie is httpOnly, can't check client-side\n // Server will read the cookie and return user/session if valid\n const {\n data: sessionData,\n isLoading,\n isFetched,\n error: sessionError,\n refetch,\n } = hooks.useQuery(\n 'get',\n '/session',\n {},\n {\n enabled: !(override || isServer()),\n refetchOnMount: false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n retry: false,\n gcTime: 0,\n staleTime: 0,\n },\n );\n\n // Derive state directly - no useEffect\n const user = override?.user ?? sessionData?.user ?? null;\n const session = override?.session ?? sessionData?.session ?? null;\n const error = override?.error ?? (sessionError as Error | null);\n\n // Check error status code\n const errorStatus = (() => {\n if (!sessionError) {\n return null;\n }\n const err = sessionError as { status?: number };\n return err.status ?? null;\n })();\n\n // Check if error is a network/connection error\n const isNetworkError = (() => {\n if (!sessionError) {\n return false;\n }\n const error = sessionError as Error & { cause?: unknown; data?: unknown };\n const errorMessage =\n error.message || String(error) || JSON.stringify(error);\n // Network errors: TypeError, DOMException, or fetch failures\n if (\n error instanceof TypeError ||\n error instanceof DOMException ||\n error.name === 'TypeError' ||\n errorMessage.includes('Failed to fetch') ||\n errorMessage.includes('ERR_CONNECTION_REFUSED') ||\n errorMessage.includes('NetworkError') ||\n errorMessage.includes('Network request failed') ||\n errorMessage.includes('fetch failed')\n ) {\n return true;\n }\n // Check error cause\n if (error.cause) {\n const causeStr = String(error.cause);\n if (\n causeStr.includes('Failed to fetch') ||\n causeStr.includes('ERR_CONNECTION_REFUSED') ||\n causeStr.includes('NetworkError')\n ) {\n return true;\n }\n }\n return false;\n })();\n\n // Compute status\n // biome-ignore lint: Status determination requires multiple checks\n const status: AuthStatus = (() => {\n if (override) {\n return override.status;\n }\n if (isServer()) {\n return 'loading';\n }\n if (user && session) {\n return 'authenticated';\n }\n // Check for network errors or auth errors first - allow auth page to show\n if (isNetworkError || errorStatus === 401) {\n return 'unauthenticated';\n }\n // If we have an error but it's not a network error, still check loading state\n if (sessionError && !isNetworkError && errorStatus !== 401) {\n if (errorStatus && errorStatus >= 500) {\n return 'authenticated';\n }\n // Other errors mean unauthenticated\n if (isFetched) {\n return 'unauthenticated';\n }\n }\n if (isLoading || !isFetched) {\n return 'loading';\n }\n if (isFetched && !user && !session) {\n return 'unauthenticated';\n }\n return 'unauthenticated';\n })();\n\n const signOutMutation = hooks.useMutation('post', '/sign-out');\n const t = createTranslator(config.messages || {});\n\n const setAuth = (auth: AuthResponse) => {\n setOverride({\n user: auth.user,\n session: auth.session,\n status: 'authenticated',\n error: null,\n });\n };\n\n const clearAuth = () => {\n setOverride({\n user: null,\n session: null,\n status: 'unauthenticated',\n error: null,\n });\n };\n\n const refresh = async () => {\n setOverride(null);\n await refetch();\n };\n\n const signOut = async () => {\n try {\n await signOutMutation.mutateAsync({});\n } finally {\n clearAuth();\n }\n };\n\n return (\n <ConfigContext.Provider value={{ config, cookieName, t }}>\n <ApiContext.Provider value={{ hooks, setAuth, clearAuth, refresh }}>\n <SessionContext.Provider\n value={{\n user,\n session,\n status,\n error,\n isLoading: status === 'loading',\n isAuthenticated: status === 'authenticated',\n refresh,\n signOut,\n }}\n >\n {children}\n </SessionContext.Provider>\n </ApiContext.Provider>\n </ConfigContext.Provider>\n );\n}\n","import type { AuthClientConfig } from '../types';\n\nconst isProduction =\n typeof process !== 'undefined' && process.env.NODE_ENV === 'production';\n\nexport const getSessionCookieName = (config: AuthClientConfig): string => {\n const prefix = config.cookiePrefix || '';\n const baseName = 'session_token';\n if (prefix) {\n return `${prefix}_${baseName}`;\n }\n return isProduction ? '__Host-session_token' : baseName;\n};\n","import { UserDetailPageContent } from './users/_components/user-detail-page-content';\n\ntype UserDetailPageProps = {\n params: Promise<{ id: string }>;\n};\n\nexport default async function UserDetailPage({ params }: UserDetailPageProps) {\n const { id } = await params;\n\n return <UserDetailPageContent userId={id} />;\n}\n"],"mappings":";AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACNP,SAAS,aAAa,2BAA2B;AACjD,SAAS,iBAAiB;AAC1B,OAAO,uBAAuB;AAC9B,OAAO,kBAAkB;AAEzB,SAAS,eAAe,YAAY,SAAS,gBAAgB;;;ACL7D,IAAM,eACJ,OAAO,YAAY,eAAe,QAAQ,IAAI,aAAa;;;AD4JvD;AA1FN,IAAM,iBAAiB,cAA0C,IAAI;AACrE,IAAM,aAAa,cAAsC,IAAI;AAC7D,IAAM,gBAAgB,cAAyC,IAAI;AAEnE,IAAM,cAAc,IAAI,YAAY;AAAA,EAClC,gBAAgB;AAAA,IACd,SAAS;AAAA,MACP,sBAAsB;AAAA,IACxB;AAAA,EACF;AACF,CAAC;AAkBM,SAAS,SAA0B;AACxC,QAAM,UAAU,WAAW,UAAU;AACrC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,SAAO;AACT;;;AD1EW,gBAAAA,MASH,YATG;AAdJ,SAAS,sBAAsB,EAAE,OAAO,GAA+B;AAC5E,QAAM,EAAE,MAAM,IAAI,OAAO;AACzB,QAAM,EAAE,MAAM,UAAU,IAAI,MAAM;AAAA,IAChC;AAAA,IACA;AAAA,IACA,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,EAAE;AAAA,IACnC,EAAE,SAAS,CAAC,CAAC,OAAO;AAAA,EACtB;AACA,QAAM,OAAO,MAAM;AAEnB,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,MAAI,aAAa,CAAC,MAAM;AACtB,WAAO,gBAAAA,KAAC,SAAI,WAAU,+CAA8C;AAAA,EACtE;AAEA,SACE,qBAAC,QACC;AAAA,oBAAAA,KAAC,cACC,0BAAAA,KAAC,aAAU,0BAAY,GACzB;AAAA,IACA,qBAAC,eAAY,WAAU,qBACrB;AAAA,2BAAC,OACC;AAAA,wBAAAA,KAAC,UAAK,WAAU,yBAAwB,mBAAK;AAAA,QAAQ;AAAA,QACpD,KAAK,YAAY;AAAA,SACpB;AAAA,MACA,qBAAC,OACC;AAAA,wBAAAA,KAAC,UAAK,WAAU,yBAAwB,oBAAM;AAAA,QAAQ;AAAA,QACrD,KAAK,SAAS;AAAA,QAAK;AAAA,QACnB,KAAK,iBACJ,gBAAAA,KAAC,SAAM,SAAQ,WAAU,WAAU,WAAU,sBAE7C;AAAA,SAEJ;AAAA,MACA,qBAAC,OACC;AAAA,wBAAAA,KAAC,UAAK,WAAU,yBAAwB,oBAAM;AAAA,QAAQ;AAAA,QACrD,KAAK,SAAS;AAAA,QAAK;AAAA,QACnB,KAAK,iBACJ,gBAAAA,KAAC,SAAM,SAAQ,WAAU,WAAU,WAAU,sBAE7C;AAAA,SAEJ;AAAA,MACA,qBAAC,OACC;AAAA,wBAAAA,KAAC,UAAK,WAAU,yBAAwB,2BAAa;AAAA,QAAQ;AAAA,QAC5D,KAAK,eACF,IAAI,KAAK,KAAK,YAAY,EAAE,eAAe,IAC3C;AAAA,SACN;AAAA,MACC,KAAK,WAAW,SACf,qBAAC,OACC;AAAA,wBAAAA,KAAC,UAAK,WAAU,yBAAwB,oBAAM;AAAA,QAAQ;AAAA,QACrD,KAAK,UAAU,KAAK,IAAI;AAAA,SAC3B,IACE;AAAA,OACN;AAAA,KACF;AAEJ;;;AGlES,gBAAAC,YAAA;AAHT,eAAO,eAAsC,EAAE,OAAO,GAAwB;AAC5E,QAAM,EAAE,GAAG,IAAI,MAAM;AAErB,SAAO,gBAAAA,KAAC,yBAAsB,QAAQ,IAAI;AAC5C;","names":["jsx","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/pages/iam/user-detail.tsx"],"sourcesContent":["import { UserDetailPageContent } from './users/_components/user-detail-page-content';\n\ntype UserDetailPageProps = {\n params: Promise<{ id: string }>;\n};\n\nexport default async function UserDetailPage({ params }: UserDetailPageProps) {\n const { id } = await params;\n\n return <UserDetailPageContent userId={id} />;\n}\n"],"mappings":";;;;;;AASS;AAHT,eAAO,eAAsC,EAAE,OAAO,GAAwB;AAC5E,QAAM,EAAE,GAAG,IAAI,MAAM;AAErB,SAAO,oBAAC,yBAAsB,QAAQ,IAAI;AAC5C;","names":[]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { paths } from '../../../../data/openapi';
|
|
2
|
+
type InviteUserPayload = NonNullable<NonNullable<paths['/users/invite']['post']['requestBody']>['content']['application/json']>;
|
|
3
|
+
type InviteResult = paths['/users/invite']['post']['responses'][201]['content']['application/json'];
|
|
4
|
+
type BulkInviteResponse = paths['/users/invite/bulk']['post']['responses'][200]['content']['application/json'];
|
|
5
|
+
type BulkInviteFailure = BulkInviteResponse['failed'][number];
|
|
6
|
+
declare const inviteTemplateCsv = "fullName,email,phone,emailVerified,phoneVerified,sendVia,password\nLulit Demo,lulit@example.com,,true,false,email,\nAbel Demo,,+251911223344,false,true,sms|email,TempPass123!\nMarta Demo,marta@example.com,+251922334455,true,true,email|sms,";
|
|
7
|
+
declare const defaultInviteUserValues: {
|
|
8
|
+
fullName: string;
|
|
9
|
+
email: string;
|
|
10
|
+
phone: string;
|
|
11
|
+
password: string;
|
|
12
|
+
emailVerified: boolean;
|
|
13
|
+
phoneVerified: boolean;
|
|
14
|
+
viaEmail: boolean;
|
|
15
|
+
viaSms: boolean;
|
|
16
|
+
};
|
|
17
|
+
declare function buildInviteUserPayload(values: typeof defaultInviteUserValues): InviteUserPayload;
|
|
18
|
+
declare function parseBulkInviteCsv(text: string): InviteUserPayload[];
|
|
19
|
+
declare function downloadInviteTemplate(): void;
|
|
20
|
+
declare function InviteResultCard({ result, index, }: {
|
|
21
|
+
result: InviteResult;
|
|
22
|
+
index?: number;
|
|
23
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export { buildInviteUserPayload, defaultInviteUserValues, downloadInviteTemplate, inviteTemplateCsv, InviteResultCard, parseBulkInviteCsv, };
|
|
25
|
+
export type { BulkInviteFailure, BulkInviteResponse, InviteResult };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type UserFormProps = {
|
|
2
|
+
mode: 'new' | 'edit';
|
|
3
|
+
userId?: string;
|
|
4
|
+
open: boolean;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
onSuccess?: () => void;
|
|
7
|
+
};
|
|
8
|
+
export declare function UserForm({ mode, userId, open, onClose, onSuccess, }: UserFormProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { User } from './users-data';
|
|
3
|
+
type UserSelectorProps = {
|
|
4
|
+
trigger: ReactNode;
|
|
5
|
+
multiple?: boolean;
|
|
6
|
+
onSelect: (users: User[]) => void;
|
|
7
|
+
excludeIds?: string[];
|
|
8
|
+
modalSize?: 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
|
9
|
+
contentClassName?: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function UserSelector({ trigger, multiple, onSelect, excludeIds, modalSize, contentClassName, }: UserSelectorProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type User = {
|
|
2
|
+
id: string;
|
|
3
|
+
tenantId: string;
|
|
4
|
+
fullName: string;
|
|
5
|
+
email: string | null;
|
|
6
|
+
phone: string | null;
|
|
7
|
+
handle: string;
|
|
8
|
+
image: string | null;
|
|
9
|
+
emailVerified: boolean;
|
|
10
|
+
phoneVerified: boolean;
|
|
11
|
+
lastSignInAt: string | null;
|
|
12
|
+
roles?: string[] | null;
|
|
13
|
+
roleCodes?: string[] | null;
|
|
14
|
+
permissions?: string[] | null;
|
|
15
|
+
userRoles?: {
|
|
16
|
+
id: string;
|
|
17
|
+
roleId: string;
|
|
18
|
+
code: string;
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
}[] | null;
|
|
22
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { User } from './users-data';
|
|
2
|
+
type UsersListProps = {
|
|
3
|
+
data: User[];
|
|
4
|
+
isLoading?: boolean;
|
|
5
|
+
view: 'table' | 'card';
|
|
6
|
+
pageIndex: number;
|
|
7
|
+
pageSize: number;
|
|
8
|
+
pageCount: number;
|
|
9
|
+
totalRows: number;
|
|
10
|
+
onPageChange: (page: number) => void;
|
|
11
|
+
onPageSizeChange: (size: number) => void;
|
|
12
|
+
onCreateNew?: () => void;
|
|
13
|
+
};
|
|
14
|
+
export declare function UsersList({ data, isLoading, view, pageIndex, pageSize, pageCount, totalRows, onPageChange, onPageSizeChange, onCreateNew, }: UsersListProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export {};
|