@mesob/auth-react 0.5.0 → 0.5.3
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-DG6GRTPG.js → chunk-4LHFPVAY.js} +2 -2
- package/dist/{chunk-H5PUZDNU.js → chunk-57L345IN.js} +4 -4
- package/dist/{chunk-CP4TTRV4.js → chunk-5B6GREDA.js} +2 -2
- package/dist/{chunk-TEHMLZFI.js → chunk-5XCUGCW7.js} +4 -4
- package/dist/{chunk-5AEV7RAN.js → chunk-6AV6I5B4.js} +3 -3
- package/dist/{chunk-SGDXNT7M.js → chunk-7VWWIN6Q.js} +3 -3
- package/dist/{chunk-AWSAC7RT.js → chunk-A5ON3RKH.js} +6 -3
- package/dist/chunk-A5ON3RKH.js.map +1 -0
- package/dist/{chunk-V6ZHX4LT.js → chunk-BM3YKYGC.js} +2 -2
- package/dist/{chunk-TLQMK2QF.js → chunk-BX75EFF3.js} +4 -4
- package/dist/{chunk-OXUOGOG3.js → chunk-DCWKYK3D.js} +88 -21
- package/dist/chunk-DCWKYK3D.js.map +1 -0
- package/dist/{chunk-W3D4HG5W.js → chunk-DRM44QBR.js} +3 -3
- package/dist/{chunk-Z34NJZRL.js → chunk-EIJFTUTM.js} +3 -3
- package/dist/{chunk-5E3XN6SW.js → chunk-FCPN2FD7.js} +5 -5
- package/dist/{chunk-VVKXFEAN.js → chunk-FLGP4ROM.js} +5 -5
- package/dist/{chunk-5SDS2E3F.js → chunk-FU4K62DS.js} +2 -2
- package/dist/chunk-G2XRGSQE.js +22 -0
- package/dist/chunk-G2XRGSQE.js.map +1 -0
- package/dist/{chunk-X2BHF4KC.js → chunk-G4VPR4UC.js} +2 -2
- package/dist/{chunk-MQI6Q2S4.js → chunk-GGBS64Z5.js} +147 -4
- package/dist/chunk-GGBS64Z5.js.map +1 -0
- package/dist/{chunk-2PV7RYNK.js → chunk-GQFTH5DQ.js} +95 -20
- package/dist/chunk-GQFTH5DQ.js.map +1 -0
- package/dist/{chunk-UY55LEIG.js → chunk-H2W42KYL.js} +2 -2
- package/dist/{chunk-EPEXIGKB.js → chunk-HBQK5PAH.js} +2 -2
- package/dist/{chunk-4ABXALRN.js → chunk-IBRB7ABJ.js} +2 -2
- package/dist/{chunk-RMJNENJB.js → chunk-IFFWIROT.js} +2 -2
- package/dist/{chunk-WY2JJNZW.js → chunk-IK7V3PT3.js} +2 -2
- package/dist/{chunk-N4JFMKGK.js → chunk-JKUKCVY7.js} +5 -5
- package/dist/{chunk-MWMSZVH3.js → chunk-K6ACPILA.js} +4 -4
- package/dist/{chunk-5BFG47VF.js → chunk-PUOQX6DR.js} +4 -4
- package/dist/{chunk-EQWOGD4F.js → chunk-SA6HTWCL.js} +2 -2
- package/dist/{chunk-73ZNGEWU.js → chunk-SX6WAVQS.js} +5 -5
- package/dist/{chunk-5HAABEAS.js → chunk-TAJQ7O3U.js} +2 -2
- package/dist/{chunk-MVVAPYUD.js → chunk-TPG4RW7H.js} +2 -2
- package/dist/{chunk-ECF6S2Y2.js → chunk-USVJBAWJ.js} +2 -2
- package/dist/{chunk-T34HJRUW.js → chunk-VMAGFUOK.js} +3 -3
- package/dist/{chunk-ZZ6D4KE4.js → chunk-VS5FEGMX.js} +2 -2
- package/dist/{chunk-IQNQGPIT.js → chunk-VWYJI2FU.js} +4 -4
- package/dist/{chunk-H7JRQFFI.js → chunk-W2HMARW4.js} +4 -4
- package/dist/{chunk-RRLFPSSM.js → chunk-W7UHDTBI.js} +33 -2
- package/dist/chunk-W7UHDTBI.js.map +1 -0
- package/dist/{chunk-4X3CJHKR.js → chunk-XLPPZKU2.js} +4 -4
- package/dist/{chunk-YFQNNSSC.js → chunk-XO5LLEGV.js} +2 -2
- package/dist/{chunk-4NUO6F3J.js → chunk-XZAYLXLS.js} +2 -2
- package/dist/{chunk-7CLKBH5Z.js → chunk-YCVDEX5U.js} +3 -3
- package/dist/{chunk-6THPM5LB.js → chunk-YQU3KG74.js} +4 -4
- package/dist/{chunk-GVEBIL3O.js → chunk-YVHMCTLM.js} +2 -2
- package/dist/{chunk-6IEX2RLA.js → chunk-Z4FXOZEJ.js} +3 -3
- package/dist/{chunk-UGQP733V.js → chunk-ZOKBN5H4.js} +2 -2
- package/dist/components/auth/countdown.js +3 -3
- package/dist/components/auth/forgot-password.js +4 -4
- package/dist/components/auth/reset-password-form.js +4 -4
- package/dist/components/auth/set-password.js +4 -4
- package/dist/components/auth/sign-in.js +4 -4
- package/dist/components/auth/sign-up.js +4 -4
- package/dist/components/auth/verification-form.js +4 -4
- package/dist/components/auth/verify-email.js +6 -6
- package/dist/components/auth/verify-phone.js +6 -6
- package/dist/components/authorization/deny.js +2 -2
- package/dist/components/authorization/grant.js +2 -2
- package/dist/components/error-boundary.d.ts +1 -1
- package/dist/components/iam/domains-page.js +6 -6
- package/dist/components/iam/iam-guard.js +3 -3
- package/dist/components/iam/permission-selector.js +2 -2
- package/dist/components/iam/permissions-page.js +4 -4
- package/dist/components/iam/permissions.js +2 -2
- package/dist/components/iam/role-detail-layout.js +2 -2
- package/dist/components/iam/role-detail-page.js +4 -4
- package/dist/components/iam/role-permissions-page.js +5 -5
- package/dist/components/iam/roles-page.js +6 -7
- package/dist/components/iam/roles.js +2 -2
- package/dist/components/iam/sessions-page.js +6 -6
- package/dist/components/iam/sessions.js +2 -2
- package/dist/components/iam/tenants-page.js +6 -6
- package/dist/components/iam/tenants.js +2 -2
- package/dist/components/iam/users-page.js +7 -7
- package/dist/components/iam/users.js +2 -2
- package/dist/components/profile/account.js +2 -2
- package/dist/components/profile/change-email-form.js +8 -8
- package/dist/components/profile/change-password-form.js +2 -2
- package/dist/components/profile/change-phone-form.js +8 -8
- package/dist/components/profile/otp-verification-modal.js +5 -5
- package/dist/components/profile/profile-layout.js +3 -3
- package/dist/components/profile/request-change-email-form.js +2 -2
- package/dist/components/profile/request-change-phone-form.js +2 -2
- package/dist/components/profile/security.js +13 -13
- package/dist/components/profile/verify-change-email-form.js +6 -6
- package/dist/components/profile/verify-change-phone-form.js +6 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.js +976 -64
- package/dist/index.js.map +1 -1
- package/dist/pages/__import_guard_probe.d.ts +4 -0
- package/dist/pages/auth/forgot-password.js +1 -8
- package/dist/pages/auth/forgot-password.js.map +1 -1
- package/dist/pages/auth/layout.js +6 -4
- package/dist/pages/auth/layout.js.map +1 -1
- package/dist/pages/auth/reset-password.js +1 -8
- package/dist/pages/auth/reset-password.js.map +1 -1
- package/dist/pages/auth/set-password.js +1 -9
- package/dist/pages/auth/set-password.js.map +1 -1
- package/dist/pages/auth/sign-in.js +1 -9
- package/dist/pages/auth/sign-in.js.map +1 -1
- package/dist/pages/auth/sign-up.js +1 -8
- package/dist/pages/auth/sign-up.js.map +1 -1
- package/dist/pages/auth/verify-email.js +1 -10
- package/dist/pages/auth/verify-email.js.map +1 -1
- package/dist/pages/auth/verify-phone.js +1 -10
- package/dist/pages/auth/verify-phone.js.map +1 -1
- package/dist/pages/iam/domains.d.ts +1 -1
- package/dist/pages/iam/permissions.d.ts +1 -1
- package/dist/pages/iam/permissions.js +3 -7
- package/dist/pages/iam/permissions.js.map +1 -1
- package/dist/pages/iam/role-detail-layout.js +1 -5
- package/dist/pages/iam/role-detail-layout.js.map +1 -1
- package/dist/pages/iam/role-detail.js +1 -7
- package/dist/pages/iam/role-detail.js.map +1 -1
- package/dist/pages/iam/role-permissions.js +1 -8
- package/dist/pages/iam/role-permissions.js.map +1 -1
- package/dist/pages/iam/role-users.js +1 -13
- package/dist/pages/iam/role-users.js.map +1 -1
- package/dist/pages/iam/roles.d.ts +1 -1
- package/dist/pages/iam/roles.js +3 -11
- package/dist/pages/iam/roles.js.map +1 -1
- package/dist/pages/iam/sessions.d.ts +1 -1
- package/dist/pages/iam/sessions.js +3 -9
- package/dist/pages/iam/sessions.js.map +1 -1
- package/dist/pages/iam/tenant-detail.js +1 -8
- package/dist/pages/iam/tenant-detail.js.map +1 -1
- package/dist/pages/iam/tenants/tenant-selector.js +3 -3
- package/dist/pages/iam/tenants.d.ts +1 -1
- package/dist/pages/iam/tenants.js +3 -10
- package/dist/pages/iam/tenants.js.map +1 -1
- package/dist/pages/iam/user-activity.js +1 -12
- package/dist/pages/iam/user-activity.js.map +1 -1
- package/dist/pages/iam/user-detail-layout.js +1 -7
- package/dist/pages/iam/user-detail-layout.js.map +1 -1
- package/dist/pages/iam/user-detail.js +1 -7
- package/dist/pages/iam/user-detail.js.map +1 -1
- package/dist/pages/iam/users/user-selector.js +149 -7
- package/dist/pages/iam/users/user-selector.js.map +1 -1
- package/dist/pages/iam/users.d.ts +1 -1
- package/dist/pages/iam/users.js +3 -11
- package/dist/pages/iam/users.js.map +1 -1
- package/dist/pages/profile/account.js +2 -5
- package/dist/pages/profile/account.js.map +1 -1
- package/dist/pages/profile/layout.d.ts +1 -1
- package/dist/pages/profile/layout.js +3 -5
- package/dist/pages/profile/layout.js.map +1 -1
- package/dist/pages/profile/security.js +2 -16
- package/dist/pages/profile/security.js.map +1 -1
- package/dist/types.d.ts +11 -2
- package/dist/utils/handle-error.d.ts +3 -1
- package/dist/utils/safe-redirect.d.ts +2 -0
- package/package.json +3 -3
- package/dist/chunk-2PV7RYNK.js.map +0 -1
- package/dist/chunk-AWSAC7RT.js.map +0 -1
- package/dist/chunk-GBDNBY6K.js +0 -153
- package/dist/chunk-GBDNBY6K.js.map +0 -1
- package/dist/chunk-MQI6Q2S4.js.map +0 -1
- package/dist/chunk-NFGFJPCX.js +0 -313
- package/dist/chunk-NFGFJPCX.js.map +0 -1
- package/dist/chunk-NJMNRSJH.js +0 -83
- package/dist/chunk-NJMNRSJH.js.map +0 -1
- package/dist/chunk-OXUOGOG3.js.map +0 -1
- package/dist/chunk-QPEUVMSP.js +0 -149
- package/dist/chunk-QPEUVMSP.js.map +0 -1
- package/dist/chunk-RCQTWNAG.js +0 -150
- package/dist/chunk-RCQTWNAG.js.map +0 -1
- package/dist/chunk-RRLFPSSM.js.map +0 -1
- package/dist/chunk-SGUROG23.js +0 -356
- package/dist/chunk-SGUROG23.js.map +0 -1
- package/dist/chunk-X6EUQZSZ.js +0 -81
- package/dist/chunk-X6EUQZSZ.js.map +0 -1
- /package/dist/{chunk-DG6GRTPG.js.map → chunk-4LHFPVAY.js.map} +0 -0
- /package/dist/{chunk-H5PUZDNU.js.map → chunk-57L345IN.js.map} +0 -0
- /package/dist/{chunk-CP4TTRV4.js.map → chunk-5B6GREDA.js.map} +0 -0
- /package/dist/{chunk-TEHMLZFI.js.map → chunk-5XCUGCW7.js.map} +0 -0
- /package/dist/{chunk-5AEV7RAN.js.map → chunk-6AV6I5B4.js.map} +0 -0
- /package/dist/{chunk-SGDXNT7M.js.map → chunk-7VWWIN6Q.js.map} +0 -0
- /package/dist/{chunk-V6ZHX4LT.js.map → chunk-BM3YKYGC.js.map} +0 -0
- /package/dist/{chunk-TLQMK2QF.js.map → chunk-BX75EFF3.js.map} +0 -0
- /package/dist/{chunk-W3D4HG5W.js.map → chunk-DRM44QBR.js.map} +0 -0
- /package/dist/{chunk-Z34NJZRL.js.map → chunk-EIJFTUTM.js.map} +0 -0
- /package/dist/{chunk-5E3XN6SW.js.map → chunk-FCPN2FD7.js.map} +0 -0
- /package/dist/{chunk-VVKXFEAN.js.map → chunk-FLGP4ROM.js.map} +0 -0
- /package/dist/{chunk-5SDS2E3F.js.map → chunk-FU4K62DS.js.map} +0 -0
- /package/dist/{chunk-X2BHF4KC.js.map → chunk-G4VPR4UC.js.map} +0 -0
- /package/dist/{chunk-UY55LEIG.js.map → chunk-H2W42KYL.js.map} +0 -0
- /package/dist/{chunk-EPEXIGKB.js.map → chunk-HBQK5PAH.js.map} +0 -0
- /package/dist/{chunk-4ABXALRN.js.map → chunk-IBRB7ABJ.js.map} +0 -0
- /package/dist/{chunk-RMJNENJB.js.map → chunk-IFFWIROT.js.map} +0 -0
- /package/dist/{chunk-WY2JJNZW.js.map → chunk-IK7V3PT3.js.map} +0 -0
- /package/dist/{chunk-N4JFMKGK.js.map → chunk-JKUKCVY7.js.map} +0 -0
- /package/dist/{chunk-MWMSZVH3.js.map → chunk-K6ACPILA.js.map} +0 -0
- /package/dist/{chunk-5BFG47VF.js.map → chunk-PUOQX6DR.js.map} +0 -0
- /package/dist/{chunk-EQWOGD4F.js.map → chunk-SA6HTWCL.js.map} +0 -0
- /package/dist/{chunk-73ZNGEWU.js.map → chunk-SX6WAVQS.js.map} +0 -0
- /package/dist/{chunk-5HAABEAS.js.map → chunk-TAJQ7O3U.js.map} +0 -0
- /package/dist/{chunk-MVVAPYUD.js.map → chunk-TPG4RW7H.js.map} +0 -0
- /package/dist/{chunk-ECF6S2Y2.js.map → chunk-USVJBAWJ.js.map} +0 -0
- /package/dist/{chunk-T34HJRUW.js.map → chunk-VMAGFUOK.js.map} +0 -0
- /package/dist/{chunk-ZZ6D4KE4.js.map → chunk-VS5FEGMX.js.map} +0 -0
- /package/dist/{chunk-IQNQGPIT.js.map → chunk-VWYJI2FU.js.map} +0 -0
- /package/dist/{chunk-H7JRQFFI.js.map → chunk-W2HMARW4.js.map} +0 -0
- /package/dist/{chunk-4X3CJHKR.js.map → chunk-XLPPZKU2.js.map} +0 -0
- /package/dist/{chunk-YFQNNSSC.js.map → chunk-XO5LLEGV.js.map} +0 -0
- /package/dist/{chunk-4NUO6F3J.js.map → chunk-XZAYLXLS.js.map} +0 -0
- /package/dist/{chunk-7CLKBH5Z.js.map → chunk-YCVDEX5U.js.map} +0 -0
- /package/dist/{chunk-6THPM5LB.js.map → chunk-YQU3KG74.js.map} +0 -0
- /package/dist/{chunk-GVEBIL3O.js.map → chunk-YVHMCTLM.js.map} +0 -0
- /package/dist/{chunk-6IEX2RLA.js.map → chunk-Z4FXOZEJ.js.map} +0 -0
- /package/dist/{chunk-UGQP733V.js.map → chunk-ZOKBN5H4.js.map} +0 -0
package/dist/chunk-NJMNRSJH.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
IAMGuard
|
|
3
|
-
} from "./chunk-V6ZHX4LT.js";
|
|
4
|
-
import {
|
|
5
|
-
useApi
|
|
6
|
-
} from "./chunk-AWSAC7RT.js";
|
|
7
|
-
|
|
8
|
-
// src/pages/iam/users/_components/user-detail-page-content.tsx
|
|
9
|
-
import {
|
|
10
|
-
Card,
|
|
11
|
-
CardContent,
|
|
12
|
-
CardHeader,
|
|
13
|
-
CardTitle,
|
|
14
|
-
Tooltip,
|
|
15
|
-
TooltipContent,
|
|
16
|
-
TooltipTrigger
|
|
17
|
-
} from "@mesob/ui/components";
|
|
18
|
-
import { IconCircleCheck } from "@tabler/icons-react";
|
|
19
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
20
|
-
function UserDetailPageContent({ userId }) {
|
|
21
|
-
return /* @__PURE__ */ jsx(IAMGuard, { children: /* @__PURE__ */ jsx(UserDetailPageContentInner, { userId }) });
|
|
22
|
-
}
|
|
23
|
-
function UserDetailPageContentInner({ userId }) {
|
|
24
|
-
const { hooks } = useApi();
|
|
25
|
-
const { data, isLoading } = hooks.useQuery(
|
|
26
|
-
"get",
|
|
27
|
-
"/users/{id}",
|
|
28
|
-
{ params: { path: { id: userId } } },
|
|
29
|
-
{ enabled: !!userId }
|
|
30
|
-
);
|
|
31
|
-
const user = data?.user;
|
|
32
|
-
if (!userId) {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
if (isLoading || !user) {
|
|
36
|
-
return /* @__PURE__ */ jsx("div", { className: "h-32 animate-pulse rounded-xl bg-muted mt-4" });
|
|
37
|
-
}
|
|
38
|
-
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
39
|
-
/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { children: "User details" }) }),
|
|
40
|
-
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-2 text-sm", children: [
|
|
41
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
42
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Name:" }),
|
|
43
|
-
" ",
|
|
44
|
-
user.fullName || "\u2014"
|
|
45
|
-
] }),
|
|
46
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
47
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Email:" }),
|
|
48
|
-
" ",
|
|
49
|
-
user.email ?? "\u2014",
|
|
50
|
-
" ",
|
|
51
|
-
user.emailVerified && /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
52
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { children: /* @__PURE__ */ jsx(IconCircleCheck, { className: "inline size-4 text-muted-foreground" }) }),
|
|
53
|
-
/* @__PURE__ */ jsx(TooltipContent, { children: "Email verified" })
|
|
54
|
-
] })
|
|
55
|
-
] }),
|
|
56
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
57
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Phone:" }),
|
|
58
|
-
" ",
|
|
59
|
-
user.phone ?? "\u2014",
|
|
60
|
-
" ",
|
|
61
|
-
user.phoneVerified && /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
62
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { children: /* @__PURE__ */ jsx(IconCircleCheck, { className: "inline size-4 text-muted-foreground" }) }),
|
|
63
|
-
/* @__PURE__ */ jsx(TooltipContent, { children: "Phone verified" })
|
|
64
|
-
] })
|
|
65
|
-
] }),
|
|
66
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
67
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Last sign in:" }),
|
|
68
|
-
" ",
|
|
69
|
-
user.lastSignInAt ? new Date(user.lastSignInAt).toLocaleString() : "Never"
|
|
70
|
-
] }),
|
|
71
|
-
user.roleCodes?.length ? /* @__PURE__ */ jsxs("p", { children: [
|
|
72
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Roles:" }),
|
|
73
|
-
" ",
|
|
74
|
-
user.roleCodes.join(", ")
|
|
75
|
-
] }) : null
|
|
76
|
-
] })
|
|
77
|
-
] });
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export {
|
|
81
|
-
UserDetailPageContent
|
|
82
|
-
};
|
|
83
|
-
//# sourceMappingURL=chunk-NJMNRSJH.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pages/iam/users/_components/user-detail-page-content.tsx"],"sourcesContent":["'use client';\n\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@mesob/ui/components';\nimport { IconCircleCheck } from '@tabler/icons-react';\nimport { IAMGuard } from '../../../../components/iam/iam-guard';\nimport { useApi } from '../../../../provider';\n\ntype UserDetailPageContentProps = {\n userId: string;\n};\n\nexport function UserDetailPageContent({ userId }: UserDetailPageContentProps) {\n return (\n <IAMGuard>\n <UserDetailPageContentInner userId={userId} />\n </IAMGuard>\n );\n}\n\nfunction UserDetailPageContentInner({ 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 <Tooltip>\n <TooltipTrigger>\n <IconCircleCheck className=\"inline size-4 text-muted-foreground\" />\n </TooltipTrigger>\n <TooltipContent>Email verified</TooltipContent>\n </Tooltip>\n )}\n </p>\n <p>\n <span className=\"text-muted-foreground\">Phone:</span>{' '}\n {user.phone ?? '—'}{' '}\n {user.phoneVerified && (\n <Tooltip>\n <TooltipTrigger>\n <IconCircleCheck className=\"inline size-4 text-muted-foreground\" />\n </TooltipTrigger>\n <TooltipContent>Phone verified</TooltipContent>\n </Tooltip>\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"],"mappings":";;;;;;;;AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,uBAAuB;AAW1B,cA4BE,YA5BF;AAHC,SAAS,sBAAsB,EAAE,OAAO,GAA+B;AAC5E,SACE,oBAAC,YACC,8BAAC,8BAA2B,QAAgB,GAC9C;AAEJ;AAEA,SAAS,2BAA2B,EAAE,OAAO,GAA+B;AAC1E,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,oBAAC,SAAI,WAAU,+CAA8C;AAAA,EACtE;AAEA,SACE,qBAAC,QACC;AAAA,wBAAC,cACC,8BAAC,aAAU,0BAAY,GACzB;AAAA,IACA,qBAAC,eAAY,WAAU,qBACrB;AAAA,2BAAC,OACC;AAAA,4BAAC,UAAK,WAAU,yBAAwB,mBAAK;AAAA,QAAQ;AAAA,QACpD,KAAK,YAAY;AAAA,SACpB;AAAA,MACA,qBAAC,OACC;AAAA,4BAAC,UAAK,WAAU,yBAAwB,oBAAM;AAAA,QAAQ;AAAA,QACrD,KAAK,SAAS;AAAA,QAAK;AAAA,QACnB,KAAK,iBACJ,qBAAC,WACC;AAAA,8BAAC,kBACC,8BAAC,mBAAgB,WAAU,uCAAsC,GACnE;AAAA,UACA,oBAAC,kBAAe,4BAAc;AAAA,WAChC;AAAA,SAEJ;AAAA,MACA,qBAAC,OACC;AAAA,4BAAC,UAAK,WAAU,yBAAwB,oBAAM;AAAA,QAAQ;AAAA,QACrD,KAAK,SAAS;AAAA,QAAK;AAAA,QACnB,KAAK,iBACJ,qBAAC,WACC;AAAA,8BAAC,kBACC,8BAAC,mBAAgB,WAAU,uCAAsC,GACnE;AAAA,UACA,oBAAC,kBAAe,4BAAc;AAAA,WAChC;AAAA,SAEJ;AAAA,MACA,qBAAC,OACC;AAAA,4BAAC,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,4BAAC,UAAK,WAAU,yBAAwB,oBAAM;AAAA,QAAQ;AAAA,QACrD,KAAK,UAAU,KAAK,IAAI;AAAA,SAC3B,IACE;AAAA,OACN;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/auth/sign-up.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n Alert,\n AlertDescription,\n AlertTitle,\n Button,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n useFormField,\n} from '@mesob/ui/components';\nimport { useMesob } from '@mesob/ui/providers';\nimport { IconAlertCircle, IconEye, IconEyeOff } from '@tabler/icons-react';\nimport type { ChangeEvent, ComponentProps } from 'react';\nimport { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useTranslator } from '../../hooks/use-translator';\nimport { useApi, useConfig } from '../../provider';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport { handleError } from '../../utils/handle-error';\nimport { AuthLayout } from './auth-layout';\n\nconst isPhone = (s: string) => /^\\+?[0-9()[\\]\\s-]{6,}$/.test(s);\n\ntype PasswordInputProps = {\n field: ComponentProps<'input'> & {\n value: string;\n onChange: (e: ChangeEvent<HTMLInputElement>) => void;\n onBlur: () => void;\n };\n show: boolean;\n onToggle: () => void;\n autoComplete?: 'current-password' | 'new-password';\n};\n\nfunction PasswordInput({\n field,\n show,\n onToggle,\n autoComplete = 'current-password',\n}: PasswordInputProps) {\n const { formItemId, error } = useFormField();\n return (\n <div className=\"relative\">\n <Input\n {...field}\n id={formItemId}\n type={show ? 'text' : 'password'}\n autoComplete={autoComplete}\n aria-invalid={!!error}\n className=\"pr-10\"\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-0 top-0 h-full px-3 text-muted-foreground hover:text-foreground\"\n onClick={onToggle}\n aria-label={show ? 'Hide password' : 'Show password'}\n >\n {show ? (\n <IconEyeOff className=\"h-4 w-4\" />\n ) : (\n <IconEye className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n );\n}\n\ntype SignUpFormValues = {\n fullName: string;\n identifier: string;\n password: string;\n confirmPassword: string;\n};\n\ntype SignUpProps = {\n redirectUrl?: string;\n initialIdentifier?: string;\n};\n\nconst signUpSchema = (t: (key: string) => string) =>\n z\n .object({\n fullName: z.string().min(1, t('errors.fullNameRequired')),\n identifier: z\n .string()\n .min(1, t('errors.contactRequired'))\n .refine(\n (val) => {\n if (!val) {\n return false;\n }\n return val.includes('@') || isPhone(val);\n },\n {\n message: t('errors.invalidEmailOrPhone'),\n },\n ),\n password: z\n .string()\n .min(8, t('errors.passwordLength'))\n .max(128, t('errors.longPasswordError')),\n confirmPassword: z.string(),\n })\n .refine((data) => data.password === data.confirmPassword, {\n message: t('errors.passwordsMismatch'),\n path: ['confirmPassword'],\n });\n\nexport const SignUp = ({\n redirectUrl,\n initialIdentifier,\n}: SignUpProps = {}) => {\n const { hooks, setAuth } = useApi();\n const { config } = useConfig();\n const mesob = useMesob();\n const t = useTranslator('Auth.signUp');\n const Link = mesob?.navigation?.Link;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthErrorContent | null>(null);\n const [showPassword, setShowPassword] = useState(false);\n const [showConfirmPassword, setShowConfirmPassword] = useState(false);\n\n const signUpMutation = hooks.useMutation('post', '/sign-up');\n\n const signInLink = config.navigation?.links?.signIn || '/auth/sign-in';\n const onNavigate =\n config.navigation?.onNavigate ||\n ((path: string) => {\n if (typeof window !== 'undefined') {\n window.location.href = path;\n }\n });\n const logoImage = config.ui.logoImage;\n const defaultRedirect =\n redirectUrl || config.navigation?.defaultRedirectUrl || '/';\n\n const hasInitialIdentifier = !!initialIdentifier;\n\n const form = useForm<SignUpFormValues>({\n resolver: zodResolver(signUpSchema(t)),\n defaultValues: {\n fullName: '',\n identifier: initialIdentifier || '',\n password: '',\n confirmPassword: '',\n },\n mode: 'onSubmit',\n reValidateMode: 'onSubmit',\n });\n\n useEffect(() => {\n if (initialIdentifier) {\n form.setValue('identifier', initialIdentifier);\n }\n }, [initialIdentifier, form]);\n\n useEffect(() => {\n if (error) {\n toast.error(error.title || 'Error', {\n description: error.description,\n });\n }\n }, [error]);\n\n const handleSubmit = form.handleSubmit(async (values) => {\n setIsLoading(true);\n setError(null);\n\n try {\n const identifier = values.identifier;\n const usingPhone = isPhone(identifier);\n\n const res = await signUpMutation.mutateAsync({\n body: usingPhone\n ? {\n phone: identifier,\n password: values.password,\n fullName: values.fullName,\n }\n : {\n email: identifier,\n password: values.password,\n fullName: values.fullName,\n },\n });\n\n if ('verificationId' in res && res.verificationId) {\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n if (usingPhone) {\n onNavigate(\n `/auth/verify-phone?context=sign-up&verificationId=${res.verificationId}&phone=${encodeURIComponent(identifier)}${redirectParam}`,\n );\n } else {\n onNavigate(\n `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(identifier)}${redirectParam}`,\n );\n }\n return;\n }\n\n if ('user' in res && 'session' in res) {\n setAuth(res);\n }\n onNavigate(defaultRedirect);\n } catch (err) {\n handleError(err, setError, t);\n } finally {\n setIsLoading(false);\n }\n });\n\n const getIdentifierLabel = () => {\n if (!hasInitialIdentifier) {\n return t('form.accountLabel') || 'Email/Phone';\n }\n if (initialIdentifier?.includes('@')) {\n return t('form.emailLabel');\n }\n return t('form.phoneLabel');\n };\n const identifierLabel = getIdentifierLabel();\n\n let errorContent: AuthErrorContent | null = null;\n if (error) {\n if (typeof error === 'string') {\n errorContent = { title: 'Error', description: error };\n } else {\n errorContent = error;\n }\n }\n\n return (\n <AuthLayout\n title={config.ui.name}\n description={t('description')}\n logoImage={logoImage}\n footer={\n <p>\n {t('footer.hasAccount')}{' '}\n {Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {t('footer.signInCta')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {t('footer.signInCta')}\n </a>\n )}\n </p>\n }\n >\n <Form {...form}>\n <form\n id=\"sign-up-form\"\n autoComplete=\"on\"\n onSubmit={handleSubmit}\n className=\"space-y-4\"\n >\n <FormField\n control={form.control}\n name=\"fullName\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.fullNameLabel')}</FormLabel>\n <FormControl>\n <Input {...field} autoComplete=\"name\" />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <FormField\n control={form.control}\n name=\"identifier\"\n render={({ field }) => (\n <FormItem>\n <FormLabel\n className={hasInitialIdentifier ? 'block' : undefined}\n >\n {identifierLabel}\n </FormLabel>\n <FormControl>\n <Input\n {...field}\n type={field.value.includes('@') ? 'email' : 'tel'}\n autoComplete={field.value.includes('@') ? 'email' : 'tel'}\n disabled={hasInitialIdentifier}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <FormField\n control={form.control}\n name=\"password\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.passwordLabel')}</FormLabel>\n <PasswordInput\n field={field}\n show={showPassword}\n onToggle={() => setShowPassword(!showPassword)}\n autoComplete=\"new-password\"\n />\n <FormMessage />\n </FormItem>\n )}\n />\n <FormField\n control={form.control}\n name=\"confirmPassword\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.confirmPasswordLabel')}</FormLabel>\n <PasswordInput\n field={field}\n show={showConfirmPassword}\n onToggle={() => setShowConfirmPassword(!showConfirmPassword)}\n autoComplete=\"new-password\"\n />\n <FormMessage />\n </FormItem>\n )}\n />\n <Button\n type=\"submit\"\n form=\"sign-up-form\"\n className=\"w-full\"\n disabled={isLoading || signUpMutation.isPending}\n >\n {isLoading || signUpMutation.isPending\n ? t('form.submitting')\n : t('form.submit')}\n </Button>\n </form>\n </Form>\n {errorContent && (\n <Alert variant=\"destructive\" className=\"mt-4\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>{errorContent.title}</AlertTitle>\n <AlertDescription>{errorContent.description}</AlertDescription>\n </Alert>\n )}\n </AuthLayout>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;AAEA,SAAS,mBAAmB;AAC5B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,gBAAgB;AACzB,SAAS,iBAAiB,SAAS,kBAAkB;AAErD,SAAS,WAAW,gBAAgB;AACpC,SAAS,eAAe;AACxB,SAAS,aAAa;AACtB,SAAS,SAAS;AA4Bd,SACE,KADF;AArBJ,IAAM,UAAU,CAAC,MAAc,yBAAyB,KAAK,CAAC;AAa9D,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AACjB,GAAuB;AACrB,QAAM,EAAE,YAAY,MAAM,IAAI,aAAa;AAC3C,SACE,qBAAC,SAAI,WAAU,YACb;AAAA;AAAA,MAAC;AAAA;AAAA,QACE,GAAG;AAAA,QACJ,IAAI;AAAA,QACJ,MAAM,OAAO,SAAS;AAAA,QACtB;AAAA,QACA,gBAAc,CAAC,CAAC;AAAA,QAChB,WAAU;AAAA;AAAA,IACZ;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,WAAU;AAAA,QACV,SAAS;AAAA,QACT,cAAY,OAAO,kBAAkB;AAAA,QAEpC,iBACC,oBAAC,cAAW,WAAU,WAAU,IAEhC,oBAAC,WAAQ,WAAU,WAAU;AAAA;AAAA,IAEjC;AAAA,KACF;AAEJ;AAcA,IAAM,eAAe,CAAC,MACpB,EACG,OAAO;AAAA,EACN,UAAU,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,yBAAyB,CAAC;AAAA,EACxD,YAAY,EACT,OAAO,EACP,IAAI,GAAG,EAAE,wBAAwB,CAAC,EAClC;AAAA,IACC,CAAC,QAAQ;AACP,UAAI,CAAC,KAAK;AACR,eAAO;AAAA,MACT;AACA,aAAO,IAAI,SAAS,GAAG,KAAK,QAAQ,GAAG;AAAA,IACzC;AAAA,IACA;AAAA,MACE,SAAS,EAAE,4BAA4B;AAAA,IACzC;AAAA,EACF;AAAA,EACF,UAAU,EACP,OAAO,EACP,IAAI,GAAG,EAAE,uBAAuB,CAAC,EACjC,IAAI,KAAK,EAAE,0BAA0B,CAAC;AAAA,EACzC,iBAAiB,EAAE,OAAO;AAC5B,CAAC,EACA,OAAO,CAAC,SAAS,KAAK,aAAa,KAAK,iBAAiB;AAAA,EACxD,SAAS,EAAE,0BAA0B;AAAA,EACrC,MAAM,CAAC,iBAAiB;AAC1B,CAAC;AAEE,IAAM,SAAS,CAAC;AAAA,EACrB;AAAA,EACA;AACF,IAAiB,CAAC,MAAM;AACtB,QAAM,EAAE,OAAO,QAAQ,IAAI,OAAO;AAClC,QAAM,EAAE,OAAO,IAAI,UAAU;AAC7B,QAAM,QAAQ,SAAS;AACvB,QAAM,IAAI,cAAc,aAAa;AACrC,QAAM,OAAO,OAAO,YAAY;AAChC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAkC,IAAI;AAChE,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,CAAC,qBAAqB,sBAAsB,IAAI,SAAS,KAAK;AAEpE,QAAM,iBAAiB,MAAM,YAAY,QAAQ,UAAU;AAE3D,QAAM,aAAa,OAAO,YAAY,OAAO,UAAU;AACvD,QAAM,aACJ,OAAO,YAAY,eAClB,CAAC,SAAiB;AACjB,QAAI,OAAO,WAAW,aAAa;AACjC,aAAO,SAAS,OAAO;AAAA,IACzB;AAAA,EACF;AACF,QAAM,YAAY,OAAO,GAAG;AAC5B,QAAM,kBACJ,eAAe,OAAO,YAAY,sBAAsB;AAE1D,QAAM,uBAAuB,CAAC,CAAC;AAE/B,QAAM,OAAO,QAA0B;AAAA,IACrC,UAAU,YAAY,aAAa,CAAC,CAAC;AAAA,IACrC,eAAe;AAAA,MACb,UAAU;AAAA,MACV,YAAY,qBAAqB;AAAA,MACjC,UAAU;AAAA,MACV,iBAAiB;AAAA,IACnB;AAAA,IACA,MAAM;AAAA,IACN,gBAAgB;AAAA,EAClB,CAAC;AAED,YAAU,MAAM;AACd,QAAI,mBAAmB;AACrB,WAAK,SAAS,cAAc,iBAAiB;AAAA,IAC/C;AAAA,EACF,GAAG,CAAC,mBAAmB,IAAI,CAAC;AAE5B,YAAU,MAAM;AACd,QAAI,OAAO;AACT,YAAM,MAAM,MAAM,SAAS,SAAS;AAAA,QAClC,aAAa,MAAM;AAAA,MACrB,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,eAAe,KAAK,aAAa,OAAO,WAAW;AACvD,iBAAa,IAAI;AACjB,aAAS,IAAI;AAEb,QAAI;AACF,YAAM,aAAa,OAAO;AAC1B,YAAM,aAAa,QAAQ,UAAU;AAErC,YAAM,MAAM,MAAM,eAAe,YAAY;AAAA,QAC3C,MAAM,aACF;AAAA,UACE,OAAO;AAAA,UACP,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO;AAAA,QACnB,IACA;AAAA,UACE,OAAO;AAAA,UACP,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO;AAAA,QACnB;AAAA,MACN,CAAC;AAED,UAAI,oBAAoB,OAAO,IAAI,gBAAgB;AACjD,cAAM,gBAAgB,kBAClB,aAAa,mBAAmB,eAAe,CAAC,KAChD;AACJ,YAAI,YAAY;AACd;AAAA,YACE,qDAAqD,IAAI,cAAc,UAAU,mBAAmB,UAAU,CAAC,GAAG,aAAa;AAAA,UACjI;AAAA,QACF,OAAO;AACL;AAAA,YACE,qCAAqC,IAAI,cAAc,UAAU,mBAAmB,UAAU,CAAC,GAAG,aAAa;AAAA,UACjH;AAAA,QACF;AACA;AAAA,MACF;AAEA,UAAI,UAAU,OAAO,aAAa,KAAK;AACrC,gBAAQ,GAAG;AAAA,MACb;AACA,iBAAW,eAAe;AAAA,IAC5B,SAAS,KAAK;AACZ,kBAAY,KAAK,UAAU,CAAC;AAAA,IAC9B,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,CAAC;AAED,QAAM,qBAAqB,MAAM;AAC/B,QAAI,CAAC,sBAAsB;AACzB,aAAO,EAAE,mBAAmB,KAAK;AAAA,IACnC;AACA,QAAI,mBAAmB,SAAS,GAAG,GAAG;AACpC,aAAO,EAAE,iBAAiB;AAAA,IAC5B;AACA,WAAO,EAAE,iBAAiB;AAAA,EAC5B;AACA,QAAM,kBAAkB,mBAAmB;AAE3C,MAAI,eAAwC;AAC5C,MAAI,OAAO;AACT,QAAI,OAAO,UAAU,UAAU;AAC7B,qBAAe,EAAE,OAAO,SAAS,aAAa,MAAM;AAAA,IACtD,OAAO;AACL,qBAAe;AAAA,IACjB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,OAAO,GAAG;AAAA,MACjB,aAAa,EAAE,aAAa;AAAA,MAC5B;AAAA,MACA,QACE,qBAAC,OACE;AAAA,UAAE,mBAAmB;AAAA,QAAG;AAAA,QACxB,OACC,oBAAC,QAAK,MAAM,YAAY,WAAU,gCAC/B,YAAE,kBAAkB,GACvB,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,SAAS,CAAC,MAAM;AACd,gBAAE,eAAe;AACjB,yBAAW,UAAU;AAAA,YACvB;AAAA,YACA,WAAU;AAAA,YAET,YAAE,kBAAkB;AAAA;AAAA,QACvB;AAAA,SAEJ;AAAA,MAGF;AAAA,4BAAC,QAAM,GAAG,MACR;AAAA,UAAC;AAAA;AAAA,YACC,IAAG;AAAA,YACH,cAAa;AAAA,YACb,UAAU;AAAA,YACV,WAAU;AAAA,YAEV;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAS,KAAK;AAAA,kBACd,MAAK;AAAA,kBACL,QAAQ,CAAC,EAAE,MAAM,MACf,qBAAC,YACC;AAAA,wCAAC,aAAW,YAAE,oBAAoB,GAAE;AAAA,oBACpC,oBAAC,eACC,8BAAC,SAAO,GAAG,OAAO,cAAa,QAAO,GACxC;AAAA,oBACA,oBAAC,eAAY;AAAA,qBACf;AAAA;AAAA,cAEJ;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAS,KAAK;AAAA,kBACd,MAAK;AAAA,kBACL,QAAQ,CAAC,EAAE,MAAM,MACf,qBAAC,YACC;AAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,WAAW,uBAAuB,UAAU;AAAA,wBAE3C;AAAA;AAAA,oBACH;AAAA,oBACA,oBAAC,eACC;AAAA,sBAAC;AAAA;AAAA,wBACE,GAAG;AAAA,wBACJ,MAAM,MAAM,MAAM,SAAS,GAAG,IAAI,UAAU;AAAA,wBAC5C,cAAc,MAAM,MAAM,SAAS,GAAG,IAAI,UAAU;AAAA,wBACpD,UAAU;AAAA;AAAA,oBACZ,GACF;AAAA,oBACA,oBAAC,eAAY;AAAA,qBACf;AAAA;AAAA,cAEJ;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAS,KAAK;AAAA,kBACd,MAAK;AAAA,kBACL,QAAQ,CAAC,EAAE,MAAM,MACf,qBAAC,YACC;AAAA,wCAAC,aAAW,YAAE,oBAAoB,GAAE;AAAA,oBACpC;AAAA,sBAAC;AAAA;AAAA,wBACC;AAAA,wBACA,MAAM;AAAA,wBACN,UAAU,MAAM,gBAAgB,CAAC,YAAY;AAAA,wBAC7C,cAAa;AAAA;AAAA,oBACf;AAAA,oBACA,oBAAC,eAAY;AAAA,qBACf;AAAA;AAAA,cAEJ;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAS,KAAK;AAAA,kBACd,MAAK;AAAA,kBACL,QAAQ,CAAC,EAAE,MAAM,MACf,qBAAC,YACC;AAAA,wCAAC,aAAW,YAAE,2BAA2B,GAAE;AAAA,oBAC3C;AAAA,sBAAC;AAAA;AAAA,wBACC;AAAA,wBACA,MAAM;AAAA,wBACN,UAAU,MAAM,uBAAuB,CAAC,mBAAmB;AAAA,wBAC3D,cAAa;AAAA;AAAA,oBACf;AAAA,oBACA,oBAAC,eAAY;AAAA,qBACf;AAAA;AAAA,cAEJ;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,MAAK;AAAA,kBACL,WAAU;AAAA,kBACV,UAAU,aAAa,eAAe;AAAA,kBAErC,uBAAa,eAAe,YACzB,EAAE,iBAAiB,IACnB,EAAE,aAAa;AAAA;AAAA,cACrB;AAAA;AAAA;AAAA,QACF,GACF;AAAA,QACC,gBACC,qBAAC,SAAM,SAAQ,eAAc,WAAU,QACrC;AAAA,8BAAC,mBAAgB,WAAU,WAAU;AAAA,UACrC,oBAAC,cAAY,uBAAa,OAAM;AAAA,UAChC,oBAAC,oBAAkB,uBAAa,aAAY;AAAA,WAC9C;AAAA;AAAA;AAAA,EAEJ;AAEJ;","names":[]}
|
package/dist/chunk-QPEUVMSP.js
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
str
|
|
3
|
-
} from "./chunk-EWXK56WQ.js";
|
|
4
|
-
import {
|
|
5
|
-
IAMGuard
|
|
6
|
-
} from "./chunk-V6ZHX4LT.js";
|
|
7
|
-
import {
|
|
8
|
-
useApi,
|
|
9
|
-
useConfig
|
|
10
|
-
} from "./chunk-AWSAC7RT.js";
|
|
11
|
-
|
|
12
|
-
// src/pages/iam/tenants/tenant-detail-page-content.tsx
|
|
13
|
-
import {
|
|
14
|
-
Button,
|
|
15
|
-
Card,
|
|
16
|
-
CardContent,
|
|
17
|
-
CardHeader,
|
|
18
|
-
CardTitle,
|
|
19
|
-
EntityDetailHeader,
|
|
20
|
-
PageContainer,
|
|
21
|
-
useBreadcrumbs
|
|
22
|
-
} from "@mesob/ui/components";
|
|
23
|
-
import { IconBuilding } from "@tabler/icons-react";
|
|
24
|
-
import { useQueryClient } from "@tanstack/react-query";
|
|
25
|
-
import { useMemo } from "react";
|
|
26
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
27
|
-
function TenantDetailPageContent({
|
|
28
|
-
tenantId
|
|
29
|
-
}) {
|
|
30
|
-
return /* @__PURE__ */ jsx(IAMGuard, { children: /* @__PURE__ */ jsx(TenantDetailPageContentInner, { tenantId }) });
|
|
31
|
-
}
|
|
32
|
-
function TenantDetailPageContentInner({
|
|
33
|
-
tenantId
|
|
34
|
-
}) {
|
|
35
|
-
const { hooks } = useApi();
|
|
36
|
-
const { config } = useConfig();
|
|
37
|
-
const homeHref = config.navigation?.defaultRedirectUrl || "/";
|
|
38
|
-
const qc = useQueryClient();
|
|
39
|
-
const { data, isLoading } = hooks.useQuery(
|
|
40
|
-
"get",
|
|
41
|
-
"/tenants/{id}",
|
|
42
|
-
{ params: { path: { id: tenantId } } },
|
|
43
|
-
{ enabled: !!tenantId }
|
|
44
|
-
);
|
|
45
|
-
const tenant = data?.tenant;
|
|
46
|
-
const toggleActive = hooks.useMutation("put", "/tenants/{id}", {
|
|
47
|
-
onSuccess: () => {
|
|
48
|
-
qc.invalidateQueries({ queryKey: ["get", "/tenants/{id}"] });
|
|
49
|
-
qc.invalidateQueries({ queryKey: ["get", "/tenants"] });
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
const title = tenant ? str(tenant.name) || tenant.id : tenantId ?? "Tenant";
|
|
53
|
-
useBreadcrumbs({
|
|
54
|
-
items: [
|
|
55
|
-
{ label: "Home", href: homeHref },
|
|
56
|
-
{ label: "IAM", href: "/iam" },
|
|
57
|
-
{ label: "Tenants", href: "/iam/tenants" },
|
|
58
|
-
{ label: title }
|
|
59
|
-
]
|
|
60
|
-
});
|
|
61
|
-
const tabs = useMemo(
|
|
62
|
-
() => [
|
|
63
|
-
{
|
|
64
|
-
value: "detail",
|
|
65
|
-
name: "Detail",
|
|
66
|
-
content: /* @__PURE__ */ jsxs(Card, { className: "mt-4", children: [
|
|
67
|
-
/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { children: "Tenant details" }) }),
|
|
68
|
-
/* @__PURE__ */ jsx(CardContent, { className: "space-y-2 text-sm", children: tenant && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
69
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
70
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Name:" }),
|
|
71
|
-
" ",
|
|
72
|
-
str(tenant.name) || "\u2014"
|
|
73
|
-
] }),
|
|
74
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
75
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Description:" }),
|
|
76
|
-
" ",
|
|
77
|
-
str(tenant.description) || "\u2014"
|
|
78
|
-
] }),
|
|
79
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
80
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Language:" }),
|
|
81
|
-
" ",
|
|
82
|
-
tenant.defaultLanguage ?? "\u2014"
|
|
83
|
-
] }),
|
|
84
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
85
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Currency:" }),
|
|
86
|
-
" ",
|
|
87
|
-
tenant.defaultCurrency ?? "\u2014"
|
|
88
|
-
] }),
|
|
89
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
90
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Timezone:" }),
|
|
91
|
-
" ",
|
|
92
|
-
tenant.timezone ?? "\u2014"
|
|
93
|
-
] })
|
|
94
|
-
] }) })
|
|
95
|
-
] })
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
value: "theme",
|
|
99
|
-
name: "Theme",
|
|
100
|
-
content: /* @__PURE__ */ jsxs(Card, { className: "mt-4", children: [
|
|
101
|
-
/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { children: "Theme" }) }),
|
|
102
|
-
/* @__PURE__ */ jsx(CardContent, { className: "text-muted-foreground text-sm", children: "Theme settings (placeholder)" })
|
|
103
|
-
] })
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
value: "settings",
|
|
107
|
-
name: "Settings",
|
|
108
|
-
content: /* @__PURE__ */ jsxs(Card, { className: "mt-4", children: [
|
|
109
|
-
/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { children: "Settings" }) }),
|
|
110
|
-
/* @__PURE__ */ jsx(CardContent, { className: "text-muted-foreground text-sm", children: "Tenant settings (placeholder)" })
|
|
111
|
-
] })
|
|
112
|
-
}
|
|
113
|
-
],
|
|
114
|
-
[tenant]
|
|
115
|
-
);
|
|
116
|
-
const actions = tenant && /* @__PURE__ */ jsx(
|
|
117
|
-
Button,
|
|
118
|
-
{
|
|
119
|
-
variant: tenant.isActive ? "secondary" : "default",
|
|
120
|
-
size: "sm",
|
|
121
|
-
onClick: () => toggleActive.mutate({
|
|
122
|
-
params: { path: { id: tenantId } },
|
|
123
|
-
body: { isActive: !tenant.isActive }
|
|
124
|
-
}),
|
|
125
|
-
disabled: toggleActive.isPending,
|
|
126
|
-
children: tenant.isActive ? "Deactivate" : "Activate"
|
|
127
|
-
}
|
|
128
|
-
);
|
|
129
|
-
if (!tenantId) {
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
if (isLoading || !tenant) {
|
|
133
|
-
return /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col gap-4 p-4 pt-0", children: /* @__PURE__ */ jsx("div", { className: "h-24 animate-pulse rounded-xl bg-muted" }) });
|
|
134
|
-
}
|
|
135
|
-
return /* @__PURE__ */ jsx(PageContainer, { className: "flex flex-1 flex-col gap-4 p-4 pt-0", children: /* @__PURE__ */ jsx(
|
|
136
|
-
EntityDetailHeader,
|
|
137
|
-
{
|
|
138
|
-
title,
|
|
139
|
-
icon: /* @__PURE__ */ jsx(IconBuilding, { className: "h-5 w-5 text-muted-foreground" }),
|
|
140
|
-
actions,
|
|
141
|
-
tabs
|
|
142
|
-
}
|
|
143
|
-
) });
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export {
|
|
147
|
-
TenantDetailPageContent
|
|
148
|
-
};
|
|
149
|
-
//# sourceMappingURL=chunk-QPEUVMSP.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pages/iam/tenants/tenant-detail-page-content.tsx"],"sourcesContent":["'use client';\n\nimport {\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n EntityDetailHeader,\n PageContainer,\n type TabItem,\n useBreadcrumbs,\n} from '@mesob/ui/components';\nimport { IconBuilding } from '@tabler/icons-react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useMemo } from 'react';\nimport { IAMGuard } from '../../../components/iam/iam-guard';\nimport { useApi, useConfig } from '../../../provider';\nimport { str } from './_components/tenants-data';\n\ntype TenantDetailPageContentProps = {\n tenantId: string;\n};\n\nexport function TenantDetailPageContent({\n tenantId,\n}: TenantDetailPageContentProps) {\n return (\n <IAMGuard>\n <TenantDetailPageContentInner tenantId={tenantId} />\n </IAMGuard>\n );\n}\n\nfunction TenantDetailPageContentInner({\n tenantId,\n}: TenantDetailPageContentProps) {\n const { hooks } = useApi();\n const { config } = useConfig();\n const homeHref = config.navigation?.defaultRedirectUrl || '/';\n const qc = useQueryClient();\n\n const { data, isLoading } = hooks.useQuery(\n 'get',\n '/tenants/{id}',\n { params: { path: { id: tenantId } } },\n { enabled: !!tenantId },\n );\n const tenant = data?.tenant;\n\n const toggleActive = hooks.useMutation('put', '/tenants/{id}', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/tenants/{id}'] });\n qc.invalidateQueries({ queryKey: ['get', '/tenants'] });\n },\n });\n\n const title = tenant ? str(tenant.name) || tenant.id : (tenantId ?? 'Tenant');\n useBreadcrumbs({\n items: [\n { label: 'Home', href: homeHref },\n { label: 'IAM', href: '/iam' },\n { label: 'Tenants', href: '/iam/tenants' },\n { label: title },\n ],\n });\n\n const tabs: TabItem[] = useMemo(\n () => [\n {\n value: 'detail',\n name: 'Detail',\n content: (\n <Card className=\"mt-4\">\n <CardHeader>\n <CardTitle>Tenant details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2 text-sm\">\n {tenant && (\n <>\n <p>\n <span className=\"text-muted-foreground\">Name:</span>{' '}\n {str(tenant.name) || '—'}\n </p>\n <p>\n <span className=\"text-muted-foreground\">Description:</span>{' '}\n {str(tenant.description) || '—'}\n </p>\n <p>\n <span className=\"text-muted-foreground\">Language:</span>{' '}\n {tenant.defaultLanguage ?? '—'}\n </p>\n <p>\n <span className=\"text-muted-foreground\">Currency:</span>{' '}\n {tenant.defaultCurrency ?? '—'}\n </p>\n <p>\n <span className=\"text-muted-foreground\">Timezone:</span>{' '}\n {tenant.timezone ?? '—'}\n </p>\n </>\n )}\n </CardContent>\n </Card>\n ),\n },\n {\n value: 'theme',\n name: 'Theme',\n content: (\n <Card className=\"mt-4\">\n <CardHeader>\n <CardTitle>Theme</CardTitle>\n </CardHeader>\n <CardContent className=\"text-muted-foreground text-sm\">\n Theme settings (placeholder)\n </CardContent>\n </Card>\n ),\n },\n {\n value: 'settings',\n name: 'Settings',\n content: (\n <Card className=\"mt-4\">\n <CardHeader>\n <CardTitle>Settings</CardTitle>\n </CardHeader>\n <CardContent className=\"text-muted-foreground text-sm\">\n Tenant settings (placeholder)\n </CardContent>\n </Card>\n ),\n },\n ],\n [tenant],\n );\n\n const actions = tenant && (\n <Button\n variant={tenant.isActive ? 'secondary' : 'default'}\n size=\"sm\"\n onClick={() =>\n toggleActive.mutate({\n params: { path: { id: tenantId } },\n body: { isActive: !tenant.isActive },\n })\n }\n disabled={toggleActive.isPending}\n >\n {tenant.isActive ? 'Deactivate' : 'Activate'}\n </Button>\n );\n\n if (!tenantId) {\n return null;\n }\n if (isLoading || !tenant) {\n return (\n <div className=\"flex flex-1 flex-col gap-4 p-4 pt-0\">\n <div className=\"h-24 animate-pulse rounded-xl bg-muted\" />\n </div>\n );\n }\n\n return (\n <PageContainer className=\"flex flex-1 flex-col gap-4 p-4 pt-0\">\n <EntityDetailHeader\n title={title}\n icon={<IconBuilding className=\"h-5 w-5 text-muted-foreground\" />}\n actions={actions}\n tabs={tabs}\n />\n </PageContainer>\n );\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-RCQTWNAG.js
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
RoleForm,
|
|
3
|
-
RolesList
|
|
4
|
-
} from "./chunk-MQI6Q2S4.js";
|
|
5
|
-
import {
|
|
6
|
-
defaultEntityQueryOptions
|
|
7
|
-
} from "./chunk-NPW7D2HZ.js";
|
|
8
|
-
import {
|
|
9
|
-
IAMGuard
|
|
10
|
-
} from "./chunk-V6ZHX4LT.js";
|
|
11
|
-
import {
|
|
12
|
-
useApi,
|
|
13
|
-
useConfig
|
|
14
|
-
} from "./chunk-AWSAC7RT.js";
|
|
15
|
-
|
|
16
|
-
// src/components/iam/roles-page.tsx
|
|
17
|
-
import {
|
|
18
|
-
Button,
|
|
19
|
-
EntityDrawerTrigger,
|
|
20
|
-
EntityFilter,
|
|
21
|
-
EntityHeader,
|
|
22
|
-
EntitySearch,
|
|
23
|
-
EntitySort,
|
|
24
|
-
EntityViewToggle,
|
|
25
|
-
PageBody,
|
|
26
|
-
PageContainer,
|
|
27
|
-
useBreadcrumbs,
|
|
28
|
-
useEntityPagination,
|
|
29
|
-
useEntityParams
|
|
30
|
-
} from "@mesob/ui/components";
|
|
31
|
-
import { IconShield } from "@tabler/icons-react";
|
|
32
|
-
import { useQueryClient } from "@tanstack/react-query";
|
|
33
|
-
import { useState } from "react";
|
|
34
|
-
import { toast } from "sonner";
|
|
35
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
36
|
-
function RolesPage() {
|
|
37
|
-
return /* @__PURE__ */ jsx(IAMGuard, { children: /* @__PURE__ */ jsx(RolesPageContent, {}) });
|
|
38
|
-
}
|
|
39
|
-
function RolesPageContent() {
|
|
40
|
-
const { hooks } = useApi();
|
|
41
|
-
const { config } = useConfig();
|
|
42
|
-
const homeHref = config.navigation?.defaultRedirectUrl || "/";
|
|
43
|
-
const qc = useQueryClient();
|
|
44
|
-
useBreadcrumbs({
|
|
45
|
-
items: [
|
|
46
|
-
{ label: "Home", href: homeHref },
|
|
47
|
-
{ label: "IAM", href: "/iam/roles" },
|
|
48
|
-
{ label: "Roles" }
|
|
49
|
-
]
|
|
50
|
-
});
|
|
51
|
-
const [createOpen, setCreateOpen] = useState(false);
|
|
52
|
-
const { queryConfig, params, setParams } = useEntityParams({
|
|
53
|
-
searchKey: "search"
|
|
54
|
-
});
|
|
55
|
-
const rolesQuery = queryConfig;
|
|
56
|
-
const { data, isPending, isFetching } = hooks.useQuery(
|
|
57
|
-
"get",
|
|
58
|
-
"/roles",
|
|
59
|
-
rolesQuery,
|
|
60
|
-
defaultEntityQueryOptions
|
|
61
|
-
);
|
|
62
|
-
const seedRoles = hooks.useMutation("post", "/roles/seed", {
|
|
63
|
-
onSuccess: () => {
|
|
64
|
-
qc.invalidateQueries({ queryKey: ["get", "/roles"] });
|
|
65
|
-
toast.success("Roles seeded");
|
|
66
|
-
},
|
|
67
|
-
onError: () => {
|
|
68
|
-
toast.error("Failed to seed roles");
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
const isLoading = isPending || isFetching;
|
|
72
|
-
const roles = data?.roles ?? [];
|
|
73
|
-
const { total, pageCount } = useEntityPagination({
|
|
74
|
-
items: roles,
|
|
75
|
-
total: data?.total,
|
|
76
|
-
pageSize: params.pageSize
|
|
77
|
-
});
|
|
78
|
-
return /* @__PURE__ */ jsx(PageContainer, { className: "flex flex-1 flex-col gap-4 p-4 pt-0", children: /* @__PURE__ */ jsxs(PageBody, { className: "px-0", children: [
|
|
79
|
-
/* @__PURE__ */ jsx(
|
|
80
|
-
EntityHeader,
|
|
81
|
-
{
|
|
82
|
-
icon: /* @__PURE__ */ jsx(IconShield, { className: "h-5 w-5" }),
|
|
83
|
-
title: "Roles",
|
|
84
|
-
actions: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
85
|
-
/* @__PURE__ */ jsx(
|
|
86
|
-
Button,
|
|
87
|
-
{
|
|
88
|
-
variant: "outline",
|
|
89
|
-
onClick: () => seedRoles.mutate({}),
|
|
90
|
-
loading: seedRoles.isPending,
|
|
91
|
-
children: "Seed Roles"
|
|
92
|
-
}
|
|
93
|
-
),
|
|
94
|
-
/* @__PURE__ */ jsx(
|
|
95
|
-
EntityDrawerTrigger,
|
|
96
|
-
{
|
|
97
|
-
mode: "new",
|
|
98
|
-
entity: "Role",
|
|
99
|
-
open: createOpen,
|
|
100
|
-
onOpenChange: setCreateOpen,
|
|
101
|
-
children: (open, onClose) => /* @__PURE__ */ jsx(RoleForm, { mode: "new", open, onClose })
|
|
102
|
-
}
|
|
103
|
-
)
|
|
104
|
-
] }),
|
|
105
|
-
search: /* @__PURE__ */ jsx(EntitySearch, { paramKey: "search", placeholder: "Search roles..." }),
|
|
106
|
-
filter: /* @__PURE__ */ jsx(
|
|
107
|
-
EntityFilter,
|
|
108
|
-
{
|
|
109
|
-
options: [
|
|
110
|
-
{ label: "All", value: "" },
|
|
111
|
-
{ label: "By Code", value: "code" }
|
|
112
|
-
],
|
|
113
|
-
placeholder: "Filter"
|
|
114
|
-
}
|
|
115
|
-
),
|
|
116
|
-
sort: /* @__PURE__ */ jsx(
|
|
117
|
-
EntitySort,
|
|
118
|
-
{
|
|
119
|
-
options: [
|
|
120
|
-
{ label: "Created", value: "createdAt" },
|
|
121
|
-
{ label: "Updated", value: "updatedAt" },
|
|
122
|
-
{ label: "Code", value: "code" }
|
|
123
|
-
]
|
|
124
|
-
}
|
|
125
|
-
),
|
|
126
|
-
view: /* @__PURE__ */ jsx(EntityViewToggle, { views: ["table", "card"] })
|
|
127
|
-
}
|
|
128
|
-
),
|
|
129
|
-
/* @__PURE__ */ jsx(
|
|
130
|
-
RolesList,
|
|
131
|
-
{
|
|
132
|
-
data: roles,
|
|
133
|
-
isLoading,
|
|
134
|
-
view: params.view || "table",
|
|
135
|
-
pageIndex: params.page - 1,
|
|
136
|
-
pageSize: params.pageSize,
|
|
137
|
-
pageCount,
|
|
138
|
-
totalRows: total,
|
|
139
|
-
onCreateNew: () => setCreateOpen(true),
|
|
140
|
-
onPageChange: (p) => setParams({ page: p + 1 }),
|
|
141
|
-
onPageSizeChange: (size) => setParams({ pageSize: size, page: 1 })
|
|
142
|
-
}
|
|
143
|
-
)
|
|
144
|
-
] }) });
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
export {
|
|
148
|
-
RolesPage
|
|
149
|
-
};
|
|
150
|
-
//# sourceMappingURL=chunk-RCQTWNAG.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/iam/roles-page.tsx"],"sourcesContent":["'use client';\n\nimport {\n Button,\n EntityDrawerTrigger,\n EntityFilter,\n EntityHeader,\n EntitySearch,\n EntitySort,\n EntityViewToggle,\n PageBody,\n PageContainer,\n useBreadcrumbs,\n useEntityPagination,\n useEntityParams,\n} from '@mesob/ui/components';\nimport { IconShield } from '@tabler/icons-react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useState } from 'react';\nimport { toast } from 'sonner';\nimport type { paths } from '../../data/openapi';\nimport { defaultEntityQueryOptions } from '../../lib/query-options';\nimport { RoleForm } from '../../pages/iam/roles/_components/role-form';\nimport { RolesList } from '../../pages/iam/roles/_components/roles-list';\nimport { useApi, useConfig } from '../../provider';\nimport { IAMGuard } from './iam-guard';\n\nexport function RolesPage() {\n return (\n <IAMGuard>\n <RolesPageContent />\n </IAMGuard>\n );\n}\n\nfunction RolesPageContent() {\n const { hooks } = useApi();\n const { config } = useConfig();\n const homeHref = config.navigation?.defaultRedirectUrl || '/';\n const qc = useQueryClient();\n useBreadcrumbs({\n items: [\n { label: 'Home', href: homeHref },\n { label: 'IAM', href: '/iam/roles' },\n { label: 'Roles' },\n ],\n });\n\n const [createOpen, setCreateOpen] = useState(false);\n const { queryConfig, params, setParams } = useEntityParams({\n searchKey: 'search',\n });\n const rolesQuery = queryConfig as {\n params: {\n query: NonNullable<paths['/roles']['get']['parameters']['query']>;\n };\n };\n\n const { data, isPending, isFetching } = hooks.useQuery(\n 'get',\n '/roles',\n rolesQuery,\n defaultEntityQueryOptions,\n );\n\n const seedRoles = hooks.useMutation('post', '/roles/seed', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/roles'] });\n toast.success('Roles seeded');\n },\n onError: () => {\n toast.error('Failed to seed roles');\n },\n });\n\n const isLoading = isPending || isFetching;\n const roles = data?.roles ?? [];\n const { total, pageCount } = useEntityPagination({\n items: roles,\n total: data?.total,\n pageSize: params.pageSize,\n });\n\n return (\n <PageContainer className=\"flex flex-1 flex-col gap-4 p-4 pt-0\">\n <PageBody className=\"px-0\">\n <EntityHeader\n icon={<IconShield className=\"h-5 w-5\" />}\n title=\"Roles\"\n actions={\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"outline\"\n onClick={() => seedRoles.mutate({})}\n loading={seedRoles.isPending}\n >\n Seed Roles\n </Button>\n <EntityDrawerTrigger\n mode=\"new\"\n entity=\"Role\"\n open={createOpen}\n onOpenChange={setCreateOpen}\n >\n {(open, onClose) => (\n <RoleForm mode=\"new\" open={open} onClose={onClose} />\n )}\n </EntityDrawerTrigger>\n </div>\n }\n search={\n <EntitySearch paramKey=\"search\" placeholder=\"Search roles...\" />\n }\n filter={\n <EntityFilter\n options={[\n { label: 'All', value: '' },\n { label: 'By Code', value: 'code' },\n ]}\n placeholder=\"Filter\"\n />\n }\n sort={\n <EntitySort\n options={[\n { label: 'Created', value: 'createdAt' },\n { label: 'Updated', value: 'updatedAt' },\n { label: 'Code', value: 'code' },\n ]}\n />\n }\n view={<EntityViewToggle views={['table', 'card']} />}\n />\n <RolesList\n data={roles}\n isLoading={isLoading}\n view={(params.view || 'table') as 'table' | 'card'}\n pageIndex={params.page - 1}\n pageSize={params.pageSize}\n pageCount={pageCount}\n totalRows={total}\n onCreateNew={() => setCreateOpen(true)}\n onPageChange={(p) => setParams({ page: p + 1 })}\n onPageSizeChange={(size) => setParams({ pageSize: size, page: 1 })}\n />\n </PageBody>\n </PageContainer>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants/auth.error.codes.ts","../src/utils/handle-error.ts"],"sourcesContent":["export const AUTH_ERROR_MAPPING: Record<\n string,\n { title: string; description: string }\n> = {\n USER_NOT_FOUND: {\n title: 'Account Not Found',\n description:\n 'We could not find an account with that identifier. Please check your spelling or sign up.',\n },\n INVALID_PASSWORD: {\n title: 'Invalid Password',\n description: 'The password you entered is incorrect. Please try again.',\n },\n USER_EXISTS: {\n title: 'Account Already Exists',\n description:\n 'An account with this identifier already exists. Please sign in instead.',\n },\n VERIFICATION_EXPIRED: {\n title: 'Verification Expired',\n description:\n 'The verification code or link has expired. Please request a new one.',\n },\n VERIFICATION_MISMATCH: {\n title: 'Invalid Code',\n description:\n 'The verification code you entered is invalid. Please double-check and try again.',\n },\n VERIFICATION_NOT_FOUND: {\n title: 'Verification Not Found',\n description:\n 'We could not find a pending verification request. Please restart the process.',\n },\n TOO_MANY_ATTEMPTS: {\n title: 'Too Many Attempts',\n description:\n 'You have made too many requests recently. Please wait a moment before trying again.',\n },\n REQUIRES_VERIFICATION: {\n title: 'Verification Required',\n description:\n 'You need to verify your account before you can continue. Please check your email or phone.',\n },\n UNAUTHORIZED: {\n title: 'Unauthorized',\n description:\n 'You are not authorized to perform this action. Please sign in again.',\n },\n ACCESS_DENIED: {\n title: 'Access Denied',\n description:\n 'You do not have permission to access this resource. Please contact support if you believe this is an error.',\n },\n HAS_NO_PASSWORD: {\n title: 'No Password Set',\n description:\n 'Your account does not have a password yet. Continue to set a password before signing in.',\n },\n PASSWORD_ALREADY_SET: {\n title: 'Password Already Set',\n description:\n 'This account already has a password. Use the normal sign-in form instead.',\n },\n};\n\nexport const validCodes = Object.keys(AUTH_ERROR_MAPPING);\n","import { AUTH_ERROR_MAPPING, validCodes } from '../constants/auth.error.codes';\nimport type { AuthError } from '../types';\n\nexport type AuthErrorContent = {\n title: string;\n description: string;\n};\n\ntype TranslatorFunction = (\n key: string,\n params?: Record<string, string | number>,\n) => string;\n\n// Type guard to check if error is an AuthError\nfunction isAuthError(err: unknown): err is AuthError {\n return (\n typeof err === 'object' &&\n err !== null &&\n 'message' in err &&\n typeof (err as { message: unknown }).message === 'string'\n );\n}\n\nfunction extractErrorCode(err: AuthError): string {\n if (err.code && validCodes.includes(err.code)) {\n return err.code;\n }\n if (err.message) {\n const messageUpper = err.message.toUpperCase().trim();\n if (validCodes.includes(messageUpper)) {\n return messageUpper;\n }\n }\n return '';\n}\n\nconst GENERIC_ERROR = 'An error occurred while processing your request';\n\nfunction sanitizeErrorMessage(message: string): string {\n const lowerMessage = message.toLowerCase();\n const isUnsafe =\n lowerMessage.includes('failed query') ||\n lowerMessage.includes('select') ||\n lowerMessage.includes('insert') ||\n lowerMessage.includes('update') ||\n lowerMessage.includes('delete') ||\n lowerMessage.includes('from') ||\n lowerMessage.includes('where') ||\n lowerMessage.includes('limit') ||\n lowerMessage.includes('params:') ||\n lowerMessage.includes('query') ||\n message.includes('\"iam\".') ||\n message.includes('\"tenants\"') ||\n message.includes('\"users\"') ||\n message.includes('\"sessions\"') ||\n message.includes('\"accounts\"') ||\n lowerMessage.includes('relation') ||\n lowerMessage.includes('column') ||\n lowerMessage.includes('syntax error') ||\n lowerMessage.includes('database') ||\n lowerMessage.includes('postgres') ||\n lowerMessage.includes('sql') ||\n lowerMessage.includes(' at ') ||\n lowerMessage.includes('exception') ||\n /\\bstack\\b/.test(lowerMessage) ||\n /\\.(ts|js|mjs|cjs):\\d+/.test(message);\n\n return isUnsafe ? GENERIC_ERROR : message;\n}\n\n// On sign-in, only these codes get a specific message; all others → generic (no enumeration)\nconst SIGNIN_SAFE_CODES = ['TOO_MANY_ATTEMPTS'];\n\nfunction handleAuthError(\n err: AuthError,\n setError: (error: AuthErrorContent | null) => void,\n t: TranslatorFunction,\n options?: { signIn?: boolean },\n) {\n const errorCode = extractErrorCode(err);\n const isCredentialFailure =\n options?.signIn && !(errorCode && SIGNIN_SAFE_CODES.includes(errorCode));\n\n if (isCredentialFailure) {\n setError({\n title: t('errors.error'),\n description: t('errors.invalidCredentials'),\n });\n return;\n }\n\n if (errorCode && AUTH_ERROR_MAPPING[errorCode]) {\n const mapping = AUTH_ERROR_MAPPING[errorCode];\n setError({\n title: mapping.title,\n description: mapping.description,\n });\n return;\n }\n\n const sanitizedMessage = sanitizeErrorMessage(\n err.message || t('errors.fallback'),\n );\n setError({\n title: t('errors.fallback'),\n description: sanitizedMessage,\n });\n}\n\nfunction handleGenericError(\n err: unknown,\n setError: (error: AuthErrorContent | null) => void,\n t: TranslatorFunction,\n options?: { signIn?: boolean },\n) {\n if (options?.signIn) {\n setError({\n title: t('errors.error'),\n description: t('errors.invalidCredentials'),\n });\n return;\n }\n const rawMessage = err instanceof Error ? err.message : t('errors.fallback');\n const sanitizedMessage = sanitizeErrorMessage(rawMessage);\n setError({\n title: 'Error',\n description: sanitizedMessage,\n });\n}\n\nexport type HandleErrorOptions = { signIn?: boolean };\n\nexport const handleError = (\n err: unknown,\n setError: (error: AuthErrorContent | null) => void,\n t: TranslatorFunction,\n options?: HandleErrorOptions,\n) => {\n if (isAuthError(err)) {\n handleAuthError(err, setError, t, options);\n } else {\n handleGenericError(err, setError, t, options);\n }\n};\n"],"mappings":"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","names":[]}
|