@better-auth-ui/heroui 1.6.8 → 1.6.9
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/components/auth/additional-field.d.ts +2 -2
- package/dist/components/auth/additional-field.js +133 -266
- package/dist/components/auth/api-key/api-key-skeleton.js +4 -20
- package/dist/components/auth/api-key/api-key.d.ts +6 -2
- package/dist/components/auth/api-key/api-key.js +16 -54
- package/dist/components/auth/api-key/api-keys-empty.d.ts +3 -1
- package/dist/components/auth/api-key/api-keys-empty.js +8 -34
- package/dist/components/auth/api-key/api-keys.d.ts +10 -2
- package/dist/components/auth/api-key/api-keys.js +21 -40
- package/dist/components/auth/api-key/create-api-key-dialog.d.ts +3 -1
- package/dist/components/auth/api-key/create-api-key-dialog.js +43 -73
- package/dist/components/auth/api-key/delete-api-key-dialog.d.ts +4 -2
- package/dist/components/auth/api-key/delete-api-key-dialog.js +16 -50
- package/dist/components/auth/api-key/new-api-key-dialog.js +23 -59
- package/dist/components/auth/api-key/organization-api-keys.d.ts +14 -0
- package/dist/components/auth/api-key/organization-api-keys.js +22 -0
- package/dist/components/auth/auth-provider.d.ts +1 -1
- package/dist/components/auth/auth-provider.js +10 -16
- package/dist/components/auth/auth.d.ts +3 -3
- package/dist/components/auth/auth.js +86 -61
- package/dist/components/auth/delete-user/danger-zone.d.ts +3 -3
- package/dist/components/auth/delete-user/danger-zone.js +11 -17
- package/dist/components/auth/delete-user/delete-account.d.ts +9 -0
- package/dist/components/auth/delete-user/delete-account.js +50 -0
- package/dist/components/auth/email/email-changed-email.d.ts +2 -2
- package/dist/components/auth/email/email-changed-email.js +22 -29
- package/dist/components/auth/email/email-verification-email.d.ts +2 -2
- package/dist/components/auth/email/email-verification-email.js +22 -29
- package/dist/components/auth/email/magic-link-email.d.ts +2 -2
- package/dist/components/auth/email/magic-link-email.js +22 -29
- package/dist/components/auth/email/new-device-email.d.ts +2 -2
- package/dist/components/auth/email/new-device-email.js +22 -29
- package/dist/components/auth/email/organization-invitation-email.d.ts +3 -0
- package/dist/components/auth/email/organization-invitation-email.js +23 -0
- package/dist/components/auth/email/otp-email.d.ts +2 -2
- package/dist/components/auth/email/otp-email.js +21 -28
- package/dist/components/auth/email/password-changed-email.d.ts +2 -2
- package/dist/components/auth/email/password-changed-email.js +22 -29
- package/dist/components/auth/email/reset-password-email.d.ts +2 -2
- package/dist/components/auth/email/reset-password-email.js +22 -29
- package/dist/components/auth/error-toaster.js +32 -16
- package/dist/components/auth/field-separator.d.ts +1 -1
- package/dist/components/auth/field-separator.js +4 -17
- package/dist/components/auth/forgot-password.d.ts +1 -1
- package/dist/components/auth/forgot-password.js +36 -88
- package/dist/components/auth/magic-link/magic-link-button.d.ts +1 -1
- package/dist/components/auth/magic-link/magic-link-button.js +33 -19
- package/dist/components/auth/magic-link/magic-link.d.ts +2 -2
- package/dist/components/auth/magic-link/magic-link.js +39 -86
- package/dist/components/auth/multi-session/manage-account.d.ts +1 -1
- package/dist/components/auth/multi-session/manage-account.js +32 -48
- package/dist/components/auth/multi-session/manage-accounts.d.ts +1 -1
- package/dist/components/auth/multi-session/manage-accounts.js +32 -33
- package/dist/components/auth/multi-session/switch-account-submenu-content.d.ts +3 -1
- package/dist/components/auth/multi-session/switch-account-submenu-content.js +24 -27
- package/dist/components/auth/multi-session/switch-account-submenu-item.d.ts +3 -2
- package/dist/components/auth/multi-session/switch-account-submenu-item.js +16 -19
- package/dist/components/auth/multi-session/switch-account-submenu.d.ts +2 -1
- package/dist/components/auth/multi-session/switch-account-submenu.js +23 -23
- package/dist/components/auth/organization/change-organization-logo.d.ts +4 -0
- package/dist/components/auth/organization/change-organization-logo.js +69 -0
- package/dist/components/auth/organization/create-organization-dialog.d.ts +13 -0
- package/dist/components/auth/organization/create-organization-dialog.js +37 -0
- package/dist/components/auth/organization/delete-organization-dialog.d.ts +7 -0
- package/dist/components/auth/organization/delete-organization-dialog.js +25 -0
- package/dist/components/auth/organization/delete-organization-skeleton.d.ts +4 -0
- package/dist/components/auth/organization/delete-organization-skeleton.js +8 -0
- package/dist/components/auth/organization/delete-organization.d.ts +5 -0
- package/dist/components/auth/organization/delete-organization.js +27 -0
- package/dist/components/auth/organization/invite-member-dialog.d.ts +13 -0
- package/dist/components/auth/organization/invite-member-dialog.js +47 -0
- package/dist/components/auth/organization/leave-organization-dialog.d.ts +7 -0
- package/dist/components/auth/organization/leave-organization-dialog.js +21 -0
- package/dist/components/auth/organization/leave-organization.d.ts +4 -0
- package/dist/components/auth/organization/leave-organization.js +16 -0
- package/dist/components/auth/organization/organization-danger-zone.d.ts +16 -0
- package/dist/components/auth/organization/organization-danger-zone.js +23 -0
- package/dist/components/auth/organization/organization-invitation-row-skeleton.d.ts +5 -0
- package/dist/components/auth/organization/organization-invitation-row-skeleton.js +9 -0
- package/dist/components/auth/organization/organization-invitation-row.d.ts +5 -0
- package/dist/components/auth/organization/organization-invitation-row.js +31 -0
- package/dist/components/auth/organization/organization-invitations-empty.d.ts +8 -0
- package/dist/components/auth/organization/organization-invitations-empty.js +13 -0
- package/dist/components/auth/organization/organization-invitations.d.ts +9 -0
- package/dist/components/auth/organization/organization-invitations.js +66 -0
- package/dist/components/auth/organization/organization-logo.d.ts +15 -0
- package/dist/components/auth/organization/organization-logo.js +14 -0
- package/dist/components/auth/organization/organization-member-row-skeleton.d.ts +4 -0
- package/dist/components/auth/organization/organization-member-row-skeleton.js +9 -0
- package/dist/components/auth/organization/organization-member-row.d.ts +9 -0
- package/dist/components/auth/organization/organization-member-row.js +34 -0
- package/dist/components/auth/organization/organization-members.d.ts +9 -0
- package/dist/components/auth/organization/organization-members.js +67 -0
- package/dist/components/auth/organization/organization-people.d.ts +10 -0
- package/dist/components/auth/organization/organization-people.js +11 -0
- package/dist/components/auth/organization/organization-profile.d.ts +9 -0
- package/dist/components/auth/organization/organization-profile.js +34 -0
- package/dist/components/auth/organization/organization-row.d.ts +8 -0
- package/dist/components/auth/organization/organization-row.js +31 -0
- package/dist/components/auth/organization/organization-settings.d.ts +12 -0
- package/dist/components/auth/organization/organization-settings.js +13 -0
- package/dist/components/auth/organization/organization-switcher.d.ts +20 -0
- package/dist/components/auth/organization/organization-switcher.js +48 -0
- package/dist/components/auth/organization/organization-view-skeleton.d.ts +6 -0
- package/dist/components/auth/organization/organization-view-skeleton.js +9 -0
- package/dist/components/auth/organization/organization-view.d.ts +15 -0
- package/dist/components/auth/organization/organization-view.js +31 -0
- package/dist/components/auth/organization/organization.d.ts +17 -0
- package/dist/components/auth/organization/organization.js +60 -0
- package/dist/components/auth/organization/organizations-empty.d.ts +4 -0
- package/dist/components/auth/organization/organizations-empty.js +9 -0
- package/dist/components/auth/organization/organizations-settings.d.ts +17 -0
- package/dist/components/auth/organization/organizations-settings.js +17 -0
- package/dist/components/auth/organization/organizations.d.ts +10 -0
- package/dist/components/auth/organization/organizations.js +21 -0
- package/dist/components/auth/organization/remove-member-dialog.d.ts +9 -0
- package/dist/components/auth/organization/remove-member-dialog.js +20 -0
- package/dist/components/auth/organization/slug-field.d.ts +19 -0
- package/dist/components/auth/organization/slug-field.js +38 -0
- package/dist/components/auth/organization/user-invitation-row-skeleton.d.ts +4 -0
- package/dist/components/auth/organization/user-invitation-row-skeleton.js +8 -0
- package/dist/components/auth/organization/user-invitation-row.d.ts +10 -0
- package/dist/components/auth/organization/user-invitation-row.js +22 -0
- package/dist/components/auth/organization/user-invitations-empty.d.ts +4 -0
- package/dist/components/auth/organization/user-invitations-empty.js +12 -0
- package/dist/components/auth/organization/user-invitations.d.ts +10 -0
- package/dist/components/auth/organization/user-invitations.js +18 -0
- package/dist/components/auth/passkey/add-passkey-dialog.js +21 -64
- package/dist/components/auth/passkey/delete-passkey-dialog.js +13 -46
- package/dist/components/auth/passkey/passkey-button.d.ts +1 -1
- package/dist/components/auth/passkey/passkey-button.js +24 -23
- package/dist/components/auth/passkey/passkey-skeleton.js +4 -16
- package/dist/components/auth/passkey/passkey.d.ts +1 -1
- package/dist/components/auth/passkey/passkey.js +16 -47
- package/dist/components/auth/passkey/passkeys-empty.js +8 -34
- package/dist/components/auth/passkey/passkeys.d.ts +1 -1
- package/dist/components/auth/passkey/passkeys.js +15 -41
- package/dist/components/auth/provider-button.d.ts +2 -2
- package/dist/components/auth/provider-button.js +28 -24
- package/dist/components/auth/provider-buttons.js +28 -18
- package/dist/components/auth/reset-password.d.ts +1 -1
- package/dist/components/auth/reset-password.js +56 -146
- package/dist/components/auth/settings/account/account-settings.d.ts +2 -2
- package/dist/components/auth/settings/account/account-settings.js +21 -19
- package/dist/components/auth/settings/account/change-avatar.js +53 -88
- package/dist/components/auth/settings/account/change-email.d.ts +1 -1
- package/dist/components/auth/settings/account/change-email.js +27 -53
- package/dist/components/auth/settings/account/user-profile.d.ts +1 -1
- package/dist/components/auth/settings/account/user-profile.js +64 -85
- package/dist/components/auth/settings/security/active-session.d.ts +1 -1
- package/dist/components/auth/settings/security/active-session.js +50 -57
- package/dist/components/auth/settings/security/active-sessions.d.ts +1 -1
- package/dist/components/auth/settings/security/active-sessions.js +21 -32
- package/dist/components/auth/settings/security/change-password.d.ts +1 -1
- package/dist/components/auth/settings/security/change-password.js +76 -186
- package/dist/components/auth/settings/security/linked-account.d.ts +1 -1
- package/dist/components/auth/settings/security/linked-account.js +37 -55
- package/dist/components/auth/settings/security/linked-accounts.d.ts +1 -1
- package/dist/components/auth/settings/security/linked-accounts.js +34 -43
- package/dist/components/auth/settings/security/security-settings.d.ts +2 -2
- package/dist/components/auth/settings/security/security-settings.js +19 -21
- package/dist/components/auth/settings/settings.d.ts +4 -4
- package/dist/components/auth/settings/settings.js +52 -44
- package/dist/components/auth/sign-in.d.ts +2 -2
- package/dist/components/auth/sign-in.js +63 -132
- package/dist/components/auth/sign-out.js +32 -26
- package/dist/components/auth/sign-up.d.ts +2 -2
- package/dist/components/auth/sign-up.js +97 -211
- package/dist/components/auth/theme/appearance.d.ts +1 -1
- package/dist/components/auth/theme/appearance.js +23 -71
- package/dist/components/auth/theme/theme-toggle-item.js +56 -61
- package/dist/components/auth/user/user-avatar.d.ts +4 -4
- package/dist/components/auth/user/user-avatar.js +31 -28
- package/dist/components/auth/user/user-button.d.ts +6 -7
- package/dist/components/auth/user/user-button.js +38 -72
- package/dist/components/auth/user/user-view.d.ts +13 -7
- package/dist/components/auth/user/user-view.js +26 -36
- package/dist/components/auth/username/sign-in-username.d.ts +2 -2
- package/dist/components/auth/username/sign-in-username.js +87 -147
- package/dist/components/auth/username/username-field.d.ts +1 -1
- package/dist/components/auth/username/username-field.js +44 -52
- package/dist/email.d.ts +8 -7
- package/dist/email.js +8 -8
- package/dist/index.d.ts +21 -21
- package/dist/index.js +21 -22
- package/dist/lib/auth/api-key-plugin.d.ts +7 -4
- package/dist/lib/auth/api-key-plugin.js +12 -10
- package/dist/lib/auth/auth-plugin.d.ts +10 -6
- package/dist/lib/auth/auth-plugin.js +1 -0
- package/dist/lib/auth/delete-user-plugin.d.ts +6 -6
- package/dist/lib/auth/delete-user-plugin.js +6 -9
- package/dist/lib/auth/magic-link-plugin.d.ts +5 -5
- package/dist/lib/auth/magic-link-plugin.js +17 -12
- package/dist/lib/auth/multi-session-plugin.d.ts +5 -5
- package/dist/lib/auth/multi-session-plugin.js +8 -11
- package/dist/lib/auth/organization-plugin.d.ts +37 -0
- package/dist/lib/auth/organization-plugin.js +19 -0
- package/dist/lib/auth/passkey-plugin.d.ts +5 -5
- package/dist/lib/auth/passkey-plugin.js +8 -11
- package/dist/lib/auth/theme-plugin.d.ts +6 -6
- package/dist/lib/auth/theme-plugin.js +25 -22
- package/dist/lib/auth/username-plugin.d.ts +11 -11
- package/dist/lib/auth/username-plugin.js +18 -17
- package/dist/plugins.d.ts +46 -22
- package/dist/plugins.js +47 -22
- package/package.json +25 -19
- package/src/components/auth/api-key/api-key.tsx +25 -16
- package/src/components/auth/api-key/api-keys-empty.tsx +8 -4
- package/src/components/auth/api-key/api-keys.tsx +52 -14
- package/src/components/auth/api-key/create-api-key-dialog.tsx +15 -2
- package/src/components/auth/api-key/delete-api-key-dialog.tsx +10 -2
- package/src/components/auth/api-key/organization-api-keys.tsx +55 -0
- package/src/components/auth/delete-user/danger-zone.tsx +3 -3
- package/src/components/auth/delete-user/{delete-user.tsx → delete-account.tsx} +9 -9
- package/src/components/auth/email/organization-invitation-email.tsx +38 -0
- package/src/components/auth/error-toaster.tsx +28 -10
- package/src/components/auth/forgot-password.tsx +10 -2
- package/src/components/auth/multi-session/manage-accounts.tsx +1 -1
- package/src/components/auth/multi-session/switch-account-submenu-content.tsx +7 -2
- package/src/components/auth/multi-session/switch-account-submenu-item.tsx +4 -2
- package/src/components/auth/multi-session/switch-account-submenu.tsx +8 -4
- package/src/components/auth/organization/change-organization-logo.tsx +171 -0
- package/src/components/auth/organization/create-organization-dialog.tsx +133 -0
- package/src/components/auth/organization/delete-organization-dialog.tsx +97 -0
- package/src/components/auth/organization/delete-organization-skeleton.tsx +17 -0
- package/src/components/auth/organization/delete-organization.tsx +77 -0
- package/src/components/auth/organization/invite-member-dialog.tsx +177 -0
- package/src/components/auth/organization/leave-organization-dialog.tsx +95 -0
- package/src/components/auth/organization/leave-organization.tsx +59 -0
- package/src/components/auth/organization/organization-danger-zone.tsx +68 -0
- package/src/components/auth/organization/organization-invitation-row-skeleton.tsx +29 -0
- package/src/components/auth/organization/organization-invitation-row.tsx +97 -0
- package/src/components/auth/organization/organization-invitations-empty.tsx +39 -0
- package/src/components/auth/organization/organization-invitations.tsx +351 -0
- package/src/components/auth/organization/organization-logo.tsx +64 -0
- package/src/components/auth/organization/organization-member-row-skeleton.tsx +24 -0
- package/src/components/auth/organization/organization-member-row.tsx +157 -0
- package/src/components/auth/organization/organization-members.tsx +284 -0
- package/src/components/auth/organization/organization-people.tsx +26 -0
- package/src/components/auth/organization/organization-profile.tsx +141 -0
- package/src/components/auth/organization/organization-row.tsx +66 -0
- package/src/components/auth/organization/organization-settings.tsx +38 -0
- package/src/components/auth/organization/organization-switcher.tsx +233 -0
- package/src/components/auth/organization/organization-view-skeleton.tsx +36 -0
- package/src/components/auth/organization/organization-view.tsx +109 -0
- package/src/components/auth/organization/organization.tsx +162 -0
- package/src/components/auth/organization/organizations-empty.tsx +35 -0
- package/src/components/auth/organization/organizations-settings.tsx +36 -0
- package/src/components/auth/organization/organizations.tsx +80 -0
- package/src/components/auth/organization/remove-member-dialog.tsx +95 -0
- package/src/components/auth/organization/slug-field.tsx +111 -0
- package/src/components/auth/organization/user-invitation-row-skeleton.tsx +17 -0
- package/src/components/auth/organization/user-invitation-row.tsx +90 -0
- package/src/components/auth/organization/user-invitations-empty.tsx +30 -0
- package/src/components/auth/organization/user-invitations.tsx +59 -0
- package/src/components/auth/settings/account/change-email.tsx +1 -1
- package/src/components/auth/settings/account/user-profile.tsx +5 -5
- package/src/components/auth/settings/security/active-sessions.tsx +6 -4
- package/src/components/auth/settings/security/linked-accounts.tsx +2 -2
- package/src/components/auth/settings/settings.tsx +77 -14
- package/src/components/auth/user/user-avatar.tsx +4 -1
- package/src/components/auth/user/user-button.tsx +14 -11
- package/src/components/auth/user/user-view.tsx +32 -12
- package/src/email.ts +1 -0
- package/src/lib/auth/api-key-plugin.ts +10 -4
- package/src/lib/auth/auth-plugin.ts +6 -1
- package/src/lib/auth/organization-plugin.tsx +32 -0
- package/src/plugins.ts +25 -1
- package/dist/components/auth/delete-user/delete-user.d.ts +0 -9
- package/dist/components/auth/delete-user/delete-user.js +0 -95
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type OrganizationAuthClient,
|
|
3
|
+
useActiveOrganization,
|
|
4
|
+
useAuth,
|
|
5
|
+
useListOrganizationMembers,
|
|
6
|
+
useSession
|
|
7
|
+
} from "@better-auth-ui/react"
|
|
8
|
+
import type { CardProps } from "@heroui/react"
|
|
9
|
+
|
|
10
|
+
import { ApiKeys } from "./api-keys"
|
|
11
|
+
|
|
12
|
+
export type OrganizationApiKeysProps = {
|
|
13
|
+
className?: string
|
|
14
|
+
variant?: CardProps["variant"]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* {@link ApiKeys} scoped to the active organization.
|
|
19
|
+
*
|
|
20
|
+
* Hidden for members whose role isn't `owner`. Better Auth's
|
|
21
|
+
* `/organization/has-permission` endpoint isn't usable for `apiKey:*` checks
|
|
22
|
+
* (it doesn't pass `allowCreatorAllPermissions` and the default org AC has no
|
|
23
|
+
* `apiKey` statements), so we gate on role directly.
|
|
24
|
+
*/
|
|
25
|
+
export function OrganizationApiKeys({
|
|
26
|
+
className,
|
|
27
|
+
variant
|
|
28
|
+
}: OrganizationApiKeysProps) {
|
|
29
|
+
const { authClient } = useAuth()
|
|
30
|
+
const { data: session } = useSession(authClient)
|
|
31
|
+
|
|
32
|
+
const { data: activeOrganization, isPending: activeOrganizationPending } =
|
|
33
|
+
useActiveOrganization(authClient as OrganizationAuthClient)
|
|
34
|
+
|
|
35
|
+
const { data: membersData } = useListOrganizationMembers(
|
|
36
|
+
authClient as OrganizationAuthClient
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
const canManageApiKeys = membersData?.members.some(
|
|
40
|
+
(member) => member.role === "owner" && member.userId === session?.user.id
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if (!canManageApiKeys) {
|
|
44
|
+
return null
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<ApiKeys
|
|
49
|
+
className={className}
|
|
50
|
+
variant={variant}
|
|
51
|
+
organizationId={activeOrganization?.id}
|
|
52
|
+
isPending={activeOrganizationPending}
|
|
53
|
+
/>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
@@ -2,7 +2,7 @@ import { useAuth } from "@better-auth-ui/react"
|
|
|
2
2
|
import { type CardProps, cn } from "@heroui/react"
|
|
3
3
|
import type { ComponentProps } from "react"
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { DeleteAccount } from "./delete-account"
|
|
6
6
|
|
|
7
7
|
export type DangerZoneProps = {
|
|
8
8
|
className?: string
|
|
@@ -10,7 +10,7 @@ export type DangerZoneProps = {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Renders the danger zone heading and {@link
|
|
13
|
+
* Renders the danger zone heading and {@link DeleteAccount}.
|
|
14
14
|
* Registered as a `securityCard` by `deleteUserPlugin()`; gate by registering the plugin.
|
|
15
15
|
*/
|
|
16
16
|
export function DangerZone({
|
|
@@ -26,7 +26,7 @@ export function DangerZone({
|
|
|
26
26
|
{localization.settings.dangerZone}
|
|
27
27
|
</h2>
|
|
28
28
|
|
|
29
|
-
<
|
|
29
|
+
<DeleteAccount variant={variant} />
|
|
30
30
|
</div>
|
|
31
31
|
)
|
|
32
32
|
}
|
|
@@ -24,7 +24,7 @@ import { type SyntheticEvent, useState } from "react"
|
|
|
24
24
|
|
|
25
25
|
import { deleteUserPlugin } from "../../../lib/auth/delete-user-plugin"
|
|
26
26
|
|
|
27
|
-
export type
|
|
27
|
+
export type DeleteAccountProps = {
|
|
28
28
|
className?: string
|
|
29
29
|
variant?: CardProps["variant"]
|
|
30
30
|
}
|
|
@@ -32,11 +32,11 @@ export type DeleteUserProps = {
|
|
|
32
32
|
/**
|
|
33
33
|
* Danger-zone card to delete the authenticated account, with a confirmation dialog and toasts.
|
|
34
34
|
*/
|
|
35
|
-
export function
|
|
35
|
+
export function DeleteAccount({
|
|
36
36
|
className,
|
|
37
37
|
variant,
|
|
38
38
|
...props
|
|
39
|
-
}:
|
|
39
|
+
}: DeleteAccountProps & Omit<CardProps, "children">) {
|
|
40
40
|
const { authClient, basePaths, localization, navigate, viewPaths } = useAuth()
|
|
41
41
|
|
|
42
42
|
const {
|
|
@@ -94,11 +94,11 @@ export function DeleteUser({
|
|
|
94
94
|
<Card.Content className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
|
95
95
|
<div>
|
|
96
96
|
<p className="text-sm font-medium leading-tight">
|
|
97
|
-
{deleteUserLocalization.
|
|
97
|
+
{deleteUserLocalization.deleteAccount}
|
|
98
98
|
</p>
|
|
99
99
|
|
|
100
100
|
<p className="text-muted text-xs mt-0.5">
|
|
101
|
-
{deleteUserLocalization.
|
|
101
|
+
{deleteUserLocalization.deleteAccountDescription}
|
|
102
102
|
</p>
|
|
103
103
|
</div>
|
|
104
104
|
|
|
@@ -109,7 +109,7 @@ export function DeleteUser({
|
|
|
109
109
|
variant="danger-soft"
|
|
110
110
|
onPress={() => setConfirmOpen(true)}
|
|
111
111
|
>
|
|
112
|
-
{deleteUserLocalization.
|
|
112
|
+
{deleteUserLocalization.deleteAccount}
|
|
113
113
|
</Button>
|
|
114
114
|
|
|
115
115
|
<AlertDialog.Backdrop
|
|
@@ -127,13 +127,13 @@ export function DeleteUser({
|
|
|
127
127
|
</AlertDialog.Icon>
|
|
128
128
|
|
|
129
129
|
<AlertDialog.Heading>
|
|
130
|
-
{deleteUserLocalization.
|
|
130
|
+
{deleteUserLocalization.deleteAccount}
|
|
131
131
|
</AlertDialog.Heading>
|
|
132
132
|
</AlertDialog.Header>
|
|
133
133
|
|
|
134
134
|
<AlertDialog.Body className="overflow-visible">
|
|
135
135
|
<p className="text-muted text-sm">
|
|
136
|
-
{deleteUserLocalization.
|
|
136
|
+
{deleteUserLocalization.deleteAccountDescription}
|
|
137
137
|
</p>
|
|
138
138
|
|
|
139
139
|
{needsPassword && (
|
|
@@ -175,7 +175,7 @@ export function DeleteUser({
|
|
|
175
175
|
>
|
|
176
176
|
{isPending && <Spinner color="current" size="sm" />}
|
|
177
177
|
|
|
178
|
-
{deleteUserLocalization.
|
|
178
|
+
{deleteUserLocalization.deleteAccount}
|
|
179
179
|
</Button>
|
|
180
180
|
</AlertDialog.Footer>
|
|
181
181
|
</Form>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OrganizationInvitationEmail as OrganizationInvitationEmailPrimitive,
|
|
3
|
+
type OrganizationInvitationEmailProps
|
|
4
|
+
} from "@better-auth-ui/react/email"
|
|
5
|
+
import { cn } from "@heroui/react"
|
|
6
|
+
|
|
7
|
+
export type { OrganizationInvitationEmailProps } from "@better-auth-ui/react/email"
|
|
8
|
+
|
|
9
|
+
export function OrganizationInvitationEmail({
|
|
10
|
+
colors,
|
|
11
|
+
classNames,
|
|
12
|
+
...props
|
|
13
|
+
}: OrganizationInvitationEmailProps) {
|
|
14
|
+
return (
|
|
15
|
+
<OrganizationInvitationEmailPrimitive
|
|
16
|
+
colors={{
|
|
17
|
+
light: {
|
|
18
|
+
background: "#F5F5F5",
|
|
19
|
+
primary: "#0285F7",
|
|
20
|
+
primaryForeground: "#FCFCFC",
|
|
21
|
+
...colors?.light
|
|
22
|
+
},
|
|
23
|
+
dark: {
|
|
24
|
+
background: "#060607",
|
|
25
|
+
primary: "#0584F6",
|
|
26
|
+
primaryForeground: "#FCFCFC",
|
|
27
|
+
...colors?.dark
|
|
28
|
+
}
|
|
29
|
+
}}
|
|
30
|
+
classNames={{
|
|
31
|
+
...classNames,
|
|
32
|
+
card: cn("border-none rounded-3xl", classNames?.card),
|
|
33
|
+
button: cn("rounded-full", classNames?.button)
|
|
34
|
+
}}
|
|
35
|
+
{...props}
|
|
36
|
+
/>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import { authMutationKeys, authQueryKeys } from "@better-auth-ui/core"
|
|
1
2
|
import { toast } from "@heroui/react"
|
|
2
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
matchMutation,
|
|
5
|
+
matchQuery,
|
|
6
|
+
useQueryClient
|
|
7
|
+
} from "@tanstack/react-query"
|
|
3
8
|
import type { BetterFetchError } from "better-auth/react"
|
|
4
9
|
import { useEffect } from "react"
|
|
5
10
|
|
|
@@ -7,18 +12,31 @@ export function ErrorToaster() {
|
|
|
7
12
|
const queryClient = useQueryClient()
|
|
8
13
|
|
|
9
14
|
useEffect(() => {
|
|
10
|
-
queryClient.getQueryCache().
|
|
11
|
-
|
|
15
|
+
const unsubscribeQuery = queryClient.getQueryCache().subscribe((event) => {
|
|
16
|
+
if (event.type !== "updated" || event.action.type !== "error") return
|
|
17
|
+
if (!matchQuery({ queryKey: authQueryKeys.all }, event.query)) return
|
|
18
|
+
|
|
19
|
+
const err = event.action.error as BetterFetchError
|
|
12
20
|
if (err?.error) toast.danger(err.error.message)
|
|
13
|
-
}
|
|
21
|
+
})
|
|
14
22
|
|
|
15
|
-
queryClient
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
const unsubscribeMutation = queryClient
|
|
24
|
+
.getMutationCache()
|
|
25
|
+
.subscribe((event) => {
|
|
26
|
+
if (event.type !== "updated" || event.action.type !== "error") return
|
|
27
|
+
if (
|
|
28
|
+
!matchMutation({ mutationKey: authMutationKeys.all }, event.mutation)
|
|
19
29
|
)
|
|
20
|
-
|
|
21
|
-
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
const err = event.action.error as BetterFetchError
|
|
33
|
+
toast.danger(err.error?.message || err.message)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
return () => {
|
|
37
|
+
unsubscribeQuery()
|
|
38
|
+
unsubscribeMutation()
|
|
39
|
+
}
|
|
22
40
|
}, [queryClient])
|
|
23
41
|
|
|
24
42
|
return null
|
|
@@ -39,8 +39,15 @@ export function ForgotPassword({
|
|
|
39
39
|
variant,
|
|
40
40
|
...props
|
|
41
41
|
}: ForgotPasswordProps & Omit<CardProps, "children">) {
|
|
42
|
-
const {
|
|
43
|
-
|
|
42
|
+
const {
|
|
43
|
+
authClient,
|
|
44
|
+
baseURL,
|
|
45
|
+
basePaths,
|
|
46
|
+
localization,
|
|
47
|
+
viewPaths,
|
|
48
|
+
navigate,
|
|
49
|
+
plugins
|
|
50
|
+
} = useAuth()
|
|
44
51
|
|
|
45
52
|
const { fetchOptions, resetFetchOptions } = useFetchOptions()
|
|
46
53
|
|
|
@@ -64,6 +71,7 @@ export function ForgotPassword({
|
|
|
64
71
|
const formData = new FormData(e.currentTarget)
|
|
65
72
|
requestPasswordReset({
|
|
66
73
|
email: formData.get("email") as string,
|
|
74
|
+
redirectTo: `${baseURL}${basePaths.auth}/${viewPaths.auth.resetPassword}`,
|
|
67
75
|
fetchOptions
|
|
68
76
|
})
|
|
69
77
|
}
|
|
@@ -21,7 +21,11 @@ import { SwitchAccountSubmenuItem } from "./switch-account-submenu-item"
|
|
|
21
21
|
*
|
|
22
22
|
* @returns The switch account submenu content as a JSX element
|
|
23
23
|
*/
|
|
24
|
-
export function SwitchAccountSubmenuContent(
|
|
24
|
+
export function SwitchAccountSubmenuContent({
|
|
25
|
+
hideSubtitle
|
|
26
|
+
}: {
|
|
27
|
+
hideSubtitle?: boolean
|
|
28
|
+
}) {
|
|
25
29
|
const { authClient, basePaths, viewPaths } = useAuth()
|
|
26
30
|
const { localization: multiSessionLocalization } =
|
|
27
31
|
useAuthPlugin(multiSessionPlugin)
|
|
@@ -34,7 +38,7 @@ export function SwitchAccountSubmenuContent() {
|
|
|
34
38
|
<Dropdown.Popover className="min-w-40 md:min-w-56 max-w-[48svw]">
|
|
35
39
|
<Dropdown.Menu>
|
|
36
40
|
<Dropdown.Item className="px-2">
|
|
37
|
-
<UserView isPending={isPending} />
|
|
41
|
+
<UserView isPending={isPending} hideSubtitle={hideSubtitle} />
|
|
38
42
|
|
|
39
43
|
{!isPending && <Check className="ml-auto" />}
|
|
40
44
|
</Dropdown.Item>
|
|
@@ -47,6 +51,7 @@ export function SwitchAccountSubmenuContent() {
|
|
|
47
51
|
<SwitchAccountSubmenuItem
|
|
48
52
|
key={deviceSession.session.id}
|
|
49
53
|
deviceSession={deviceSession}
|
|
54
|
+
hideSubtitle={hideSubtitle}
|
|
50
55
|
/>
|
|
51
56
|
))}
|
|
52
57
|
|
|
@@ -14,6 +14,7 @@ type DeviceSession = {
|
|
|
14
14
|
|
|
15
15
|
export type SwitchAccountSubmenuItemProps = {
|
|
16
16
|
deviceSession: DeviceSession
|
|
17
|
+
hideSubtitle?: boolean
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
/**
|
|
@@ -23,7 +24,8 @@ export type SwitchAccountSubmenuItemProps = {
|
|
|
23
24
|
* @returns The switch account dropdown item as a JSX element
|
|
24
25
|
*/
|
|
25
26
|
export function SwitchAccountSubmenuItem({
|
|
26
|
-
deviceSession
|
|
27
|
+
deviceSession,
|
|
28
|
+
hideSubtitle
|
|
27
29
|
}: SwitchAccountSubmenuItemProps) {
|
|
28
30
|
const { authClient } = useAuth()
|
|
29
31
|
const { mutate: setActiveSession, isPending } = useSetActiveSession(
|
|
@@ -41,7 +43,7 @@ export function SwitchAccountSubmenuItem({
|
|
|
41
43
|
setActiveSession({ sessionToken: deviceSession.session.token })
|
|
42
44
|
}
|
|
43
45
|
>
|
|
44
|
-
<UserView user={deviceSession.user} />
|
|
46
|
+
<UserView user={deviceSession.user} hideSubtitle={hideSubtitle} />
|
|
45
47
|
|
|
46
48
|
{isPending && <Spinner color="current" size="sm" className="ml-auto" />}
|
|
47
49
|
</Dropdown.Item>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useAuth, useAuthPlugin, useSession } from "@better-auth-ui/react"
|
|
2
|
-
import {
|
|
2
|
+
import { ArrowRightArrowLeft } from "@gravity-ui/icons"
|
|
3
3
|
import { Dropdown, Label } from "@heroui/react"
|
|
4
4
|
|
|
5
5
|
import { multiSessionPlugin } from "../../../lib/auth/multi-session-plugin"
|
|
@@ -8,6 +8,7 @@ import { SwitchAccountSubmenuContent } from "./switch-account-submenu-content"
|
|
|
8
8
|
|
|
9
9
|
export type SwitchAccountSubmenuProps = {
|
|
10
10
|
className?: string
|
|
11
|
+
hideSubtitle?: boolean
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -19,7 +20,10 @@ export type SwitchAccountSubmenuProps = {
|
|
|
19
20
|
* @param className - Optional additional CSS class names
|
|
20
21
|
* @returns The switch account submenu as a JSX element
|
|
21
22
|
*/
|
|
22
|
-
export function SwitchAccountSubmenu({
|
|
23
|
+
export function SwitchAccountSubmenu({
|
|
24
|
+
className,
|
|
25
|
+
hideSubtitle
|
|
26
|
+
}: SwitchAccountSubmenuProps) {
|
|
23
27
|
const { authClient } = useAuth()
|
|
24
28
|
const { data: session } = useSession(authClient)
|
|
25
29
|
const { localization: multiSessionLocalization } =
|
|
@@ -35,7 +39,7 @@ export function SwitchAccountSubmenu({ className }: SwitchAccountSubmenuProps) {
|
|
|
35
39
|
className={className}
|
|
36
40
|
textValue={multiSessionLocalization.switchAccount}
|
|
37
41
|
>
|
|
38
|
-
<
|
|
42
|
+
<ArrowRightArrowLeft className="text-muted" />
|
|
39
43
|
|
|
40
44
|
<Label>{multiSessionLocalization.switchAccount}</Label>
|
|
41
45
|
|
|
@@ -43,7 +47,7 @@ export function SwitchAccountSubmenu({ className }: SwitchAccountSubmenuProps) {
|
|
|
43
47
|
</Dropdown.Item>
|
|
44
48
|
|
|
45
49
|
<Dropdown.Popover className="min-w-40 md:min-w-56 max-w-[48svw]">
|
|
46
|
-
<SwitchAccountSubmenuContent />
|
|
50
|
+
<SwitchAccountSubmenuContent hideSubtitle={hideSubtitle} />
|
|
47
51
|
</Dropdown.Popover>
|
|
48
52
|
</Dropdown.SubmenuTrigger>
|
|
49
53
|
)
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { fileToBase64 } from "@better-auth-ui/core"
|
|
2
|
+
import {
|
|
3
|
+
type OrganizationAuthClient,
|
|
4
|
+
useActiveOrganization,
|
|
5
|
+
useAuth,
|
|
6
|
+
useAuthPlugin,
|
|
7
|
+
useUpdateOrganization
|
|
8
|
+
} from "@better-auth-ui/react"
|
|
9
|
+
import { CloudArrowUpIn, TrashBin } from "@gravity-ui/icons"
|
|
10
|
+
import { Button, cn, Dropdown, Label, Spinner, toast } from "@heroui/react"
|
|
11
|
+
import { type ChangeEvent, useRef, useState } from "react"
|
|
12
|
+
import { organizationPlugin } from "../../../lib/auth/organization-plugin"
|
|
13
|
+
import { OrganizationLogo } from "./organization-logo"
|
|
14
|
+
|
|
15
|
+
export type ChangeOrganizationLogoProps = {
|
|
16
|
+
className?: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function ChangeOrganizationLogo({
|
|
20
|
+
className
|
|
21
|
+
}: ChangeOrganizationLogoProps) {
|
|
22
|
+
const { authClient } = useAuth()
|
|
23
|
+
const { logo, localization: organizationLocalization } =
|
|
24
|
+
useAuthPlugin(organizationPlugin)
|
|
25
|
+
|
|
26
|
+
const { data: activeOrganization, isPending: activeOrganizationPending } =
|
|
27
|
+
useActiveOrganization(authClient as OrganizationAuthClient)
|
|
28
|
+
|
|
29
|
+
const { mutate: updateOrganization, isPending: updatePending } =
|
|
30
|
+
useUpdateOrganization(authClient as OrganizationAuthClient)
|
|
31
|
+
|
|
32
|
+
const fileInputRef = useRef<HTMLInputElement>(null)
|
|
33
|
+
const [isUploading, setIsUploading] = useState(false)
|
|
34
|
+
const [isDeleting, setIsDeleting] = useState(false)
|
|
35
|
+
|
|
36
|
+
const isPending = updatePending || isUploading || isDeleting
|
|
37
|
+
|
|
38
|
+
async function handleFileChange(e: ChangeEvent<HTMLInputElement>) {
|
|
39
|
+
const file = e.target.files?.[0]
|
|
40
|
+
if (!file || !activeOrganization) return
|
|
41
|
+
|
|
42
|
+
e.target.value = ""
|
|
43
|
+
|
|
44
|
+
setIsUploading(true)
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const resized =
|
|
48
|
+
(await logo.resize?.(file, logo.size, logo.extension)) || file
|
|
49
|
+
|
|
50
|
+
const image =
|
|
51
|
+
(await logo.upload?.(resized)) || (await fileToBase64(resized))
|
|
52
|
+
|
|
53
|
+
updateOrganization(
|
|
54
|
+
{ data: { logo: image } },
|
|
55
|
+
{
|
|
56
|
+
onSuccess: () =>
|
|
57
|
+
toast.success(organizationLocalization.logoChangedSuccess),
|
|
58
|
+
onSettled: () => setIsUploading(false)
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
} catch (error) {
|
|
62
|
+
setIsUploading(false)
|
|
63
|
+
if (error instanceof Error) {
|
|
64
|
+
toast.danger(error.message)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function handleDelete() {
|
|
70
|
+
const currentLogo = activeOrganization?.logo
|
|
71
|
+
|
|
72
|
+
updateOrganization(
|
|
73
|
+
{
|
|
74
|
+
data: { logo: "" }
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
onSuccess: async () => {
|
|
78
|
+
if (!currentLogo) {
|
|
79
|
+
toast.success(organizationLocalization.logoDeletedSuccess)
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
setIsDeleting(true)
|
|
84
|
+
try {
|
|
85
|
+
await logo.delete?.(currentLogo)
|
|
86
|
+
toast.success(organizationLocalization.logoDeletedSuccess)
|
|
87
|
+
} catch (error) {
|
|
88
|
+
if (error instanceof Error) {
|
|
89
|
+
toast.danger(error.message)
|
|
90
|
+
}
|
|
91
|
+
} finally {
|
|
92
|
+
setIsDeleting(false)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!logo.enabled) {
|
|
100
|
+
return null
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<div className={cn("flex flex-col gap-1", className)}>
|
|
105
|
+
<Label isDisabled={!activeOrganization}>
|
|
106
|
+
{organizationLocalization.logo}
|
|
107
|
+
</Label>
|
|
108
|
+
|
|
109
|
+
<input
|
|
110
|
+
ref={fileInputRef}
|
|
111
|
+
type="file"
|
|
112
|
+
accept="image/*"
|
|
113
|
+
className="hidden"
|
|
114
|
+
onChange={handleFileChange}
|
|
115
|
+
/>
|
|
116
|
+
|
|
117
|
+
<div className="flex items-center gap-4">
|
|
118
|
+
<Button
|
|
119
|
+
type="button"
|
|
120
|
+
isIconOnly
|
|
121
|
+
variant="ghost"
|
|
122
|
+
className="p-0 h-auto w-auto rounded-full"
|
|
123
|
+
isDisabled={!activeOrganization || isPending}
|
|
124
|
+
onPress={() => fileInputRef.current?.click()}
|
|
125
|
+
>
|
|
126
|
+
<OrganizationLogo
|
|
127
|
+
size="lg"
|
|
128
|
+
isPending={activeOrganizationPending}
|
|
129
|
+
organization={activeOrganization}
|
|
130
|
+
/>
|
|
131
|
+
</Button>
|
|
132
|
+
|
|
133
|
+
<Dropdown>
|
|
134
|
+
<Button
|
|
135
|
+
isDisabled={!activeOrganization || isPending}
|
|
136
|
+
size="sm"
|
|
137
|
+
variant="secondary"
|
|
138
|
+
>
|
|
139
|
+
{isPending && <Spinner size="sm" />}
|
|
140
|
+
|
|
141
|
+
{organizationLocalization.changeLogo}
|
|
142
|
+
</Button>
|
|
143
|
+
|
|
144
|
+
<Dropdown.Popover className="min-w-fit">
|
|
145
|
+
<Dropdown.Menu>
|
|
146
|
+
<Dropdown.Item
|
|
147
|
+
textValue={organizationLocalization.uploadLogo}
|
|
148
|
+
onAction={() => fileInputRef.current?.click()}
|
|
149
|
+
>
|
|
150
|
+
<CloudArrowUpIn className="text-muted" />
|
|
151
|
+
|
|
152
|
+
<Label>{organizationLocalization.uploadLogo}</Label>
|
|
153
|
+
</Dropdown.Item>
|
|
154
|
+
|
|
155
|
+
<Dropdown.Item
|
|
156
|
+
textValue={organizationLocalization.deleteLogo}
|
|
157
|
+
isDisabled={!activeOrganization?.logo}
|
|
158
|
+
onAction={handleDelete}
|
|
159
|
+
variant="danger"
|
|
160
|
+
>
|
|
161
|
+
<TrashBin className="text-danger" />
|
|
162
|
+
|
|
163
|
+
<Label>{organizationLocalization.deleteLogo}</Label>
|
|
164
|
+
</Dropdown.Item>
|
|
165
|
+
</Dropdown.Menu>
|
|
166
|
+
</Dropdown.Popover>
|
|
167
|
+
</Dropdown>
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
)
|
|
171
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type OrganizationAuthClient,
|
|
3
|
+
useAuth,
|
|
4
|
+
useAuthPlugin,
|
|
5
|
+
useCreateOrganization
|
|
6
|
+
} from "@better-auth-ui/react"
|
|
7
|
+
import { Briefcase } from "@gravity-ui/icons"
|
|
8
|
+
import {
|
|
9
|
+
AlertDialog,
|
|
10
|
+
Button,
|
|
11
|
+
FieldError,
|
|
12
|
+
Form,
|
|
13
|
+
Input,
|
|
14
|
+
Label,
|
|
15
|
+
Spinner,
|
|
16
|
+
TextField
|
|
17
|
+
} from "@heroui/react"
|
|
18
|
+
import { type SyntheticEvent, useEffect, useState } from "react"
|
|
19
|
+
|
|
20
|
+
import { organizationPlugin } from "../../../lib/auth/organization-plugin"
|
|
21
|
+
import { SlugField, sanitizeSlug } from "./slug-field"
|
|
22
|
+
|
|
23
|
+
/** Props for the {@link CreateOrganizationDialog} component. */
|
|
24
|
+
export type CreateOrganizationDialogProps = {
|
|
25
|
+
isOpen: boolean
|
|
26
|
+
onOpenChange: (open: boolean) => void
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Render a dialog for creating a new organization.
|
|
31
|
+
*
|
|
32
|
+
* @param isOpen - Whether the dialog is open
|
|
33
|
+
* @param onOpenChange - Callback for when the dialog open state changes
|
|
34
|
+
* @returns The create organization dialog as a JSX element
|
|
35
|
+
*/
|
|
36
|
+
export function CreateOrganizationDialog({
|
|
37
|
+
isOpen,
|
|
38
|
+
onOpenChange
|
|
39
|
+
}: CreateOrganizationDialogProps) {
|
|
40
|
+
const { authClient, localization } = useAuth()
|
|
41
|
+
const { localization: organizationLocalization } =
|
|
42
|
+
useAuthPlugin(organizationPlugin)
|
|
43
|
+
|
|
44
|
+
const [name, setName] = useState("")
|
|
45
|
+
const [slug, setSlug] = useState("")
|
|
46
|
+
|
|
47
|
+
const { mutate: createOrganization, isPending: isCreating } =
|
|
48
|
+
useCreateOrganization(authClient as OrganizationAuthClient, {
|
|
49
|
+
onSuccess: () => onOpenChange(false)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const handleSubmit = (e: SyntheticEvent<HTMLFormElement>) => {
|
|
53
|
+
e.preventDefault()
|
|
54
|
+
createOrganization({ name, slug })
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (!isOpen) {
|
|
59
|
+
setSlug("")
|
|
60
|
+
setName("")
|
|
61
|
+
}
|
|
62
|
+
}, [isOpen])
|
|
63
|
+
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
setSlug(sanitizeSlug(name))
|
|
66
|
+
}, [name])
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<AlertDialog.Backdrop isOpen={isOpen} onOpenChange={onOpenChange}>
|
|
70
|
+
<AlertDialog.Container>
|
|
71
|
+
<AlertDialog.Dialog>
|
|
72
|
+
<Form onSubmit={handleSubmit}>
|
|
73
|
+
<AlertDialog.CloseTrigger />
|
|
74
|
+
|
|
75
|
+
<AlertDialog.Header>
|
|
76
|
+
<AlertDialog.Icon status="default">
|
|
77
|
+
<Briefcase />
|
|
78
|
+
</AlertDialog.Icon>
|
|
79
|
+
|
|
80
|
+
<AlertDialog.Heading>
|
|
81
|
+
{organizationLocalization.createOrganization}
|
|
82
|
+
</AlertDialog.Heading>
|
|
83
|
+
</AlertDialog.Header>
|
|
84
|
+
|
|
85
|
+
<AlertDialog.Body className="flex flex-col gap-4 overflow-visible">
|
|
86
|
+
<p className="text-muted text-sm">
|
|
87
|
+
{organizationLocalization.organizationsDescription}
|
|
88
|
+
</p>
|
|
89
|
+
|
|
90
|
+
<TextField
|
|
91
|
+
id="name"
|
|
92
|
+
name="name"
|
|
93
|
+
isDisabled={isCreating}
|
|
94
|
+
value={name}
|
|
95
|
+
onChange={setName}
|
|
96
|
+
>
|
|
97
|
+
<Label>{organizationLocalization.name}</Label>
|
|
98
|
+
|
|
99
|
+
<Input
|
|
100
|
+
required
|
|
101
|
+
autoFocus
|
|
102
|
+
placeholder={organizationLocalization.namePlaceholder}
|
|
103
|
+
variant="secondary"
|
|
104
|
+
/>
|
|
105
|
+
|
|
106
|
+
<FieldError />
|
|
107
|
+
</TextField>
|
|
108
|
+
|
|
109
|
+
<SlugField
|
|
110
|
+
value={slug}
|
|
111
|
+
onChange={setSlug}
|
|
112
|
+
isDisabled={isCreating}
|
|
113
|
+
variant="secondary"
|
|
114
|
+
/>
|
|
115
|
+
</AlertDialog.Body>
|
|
116
|
+
|
|
117
|
+
<AlertDialog.Footer>
|
|
118
|
+
<Button slot="close" variant="tertiary" isDisabled={isCreating}>
|
|
119
|
+
{localization.settings.cancel}
|
|
120
|
+
</Button>
|
|
121
|
+
|
|
122
|
+
<Button type="submit" isPending={isCreating}>
|
|
123
|
+
{isCreating && <Spinner color="current" size="sm" />}
|
|
124
|
+
|
|
125
|
+
{organizationLocalization.createOrganization}
|
|
126
|
+
</Button>
|
|
127
|
+
</AlertDialog.Footer>
|
|
128
|
+
</Form>
|
|
129
|
+
</AlertDialog.Dialog>
|
|
130
|
+
</AlertDialog.Container>
|
|
131
|
+
</AlertDialog.Backdrop>
|
|
132
|
+
)
|
|
133
|
+
}
|