diff --git a/packages/console/src/components/Topbar/TenantSelector/TenantInvitationDropdownItem/index.module.scss b/packages/console/src/components/Topbar/TenantSelector/TenantInvitationDropdownItem/index.module.scss new file mode 100644 index 000000000..fa2a78575 --- /dev/null +++ b/packages/console/src/components/Topbar/TenantSelector/TenantInvitationDropdownItem/index.module.scss @@ -0,0 +1,26 @@ +@use '@/scss/underscore' as _; + +.item { + display: flex; + align-items: center; + padding: _.unit(2.5) _.unit(4); + margin: _.unit(1); + border-radius: 6px; + transition: background-color 0.2s ease-in-out; + justify-content: space-between; + + &:hover { + background: var(--color-hover); + } + + .meta { + display: flex; + align-items: center; + gap: _.unit(2); + + .name { + font: var(--font-body-2); + @include _.text-ellipsis; + } + } +} diff --git a/packages/console/src/components/Topbar/TenantSelector/TenantInvitationDropdownItem/index.tsx b/packages/console/src/components/Topbar/TenantSelector/TenantInvitationDropdownItem/index.tsx new file mode 100644 index 000000000..0a067beda --- /dev/null +++ b/packages/console/src/components/Topbar/TenantSelector/TenantInvitationDropdownItem/index.tsx @@ -0,0 +1,50 @@ +import { OrganizationInvitationStatus, type TenantTag } from '@logto/schemas'; +import { useContext } from 'react'; + +import { useCloudApi } from '@/cloud/hooks/use-cloud-api'; +import TenantEnvTag from '@/components/TenantEnvTag'; +import { TenantsContext } from '@/contexts/TenantsProvider'; +import Button from '@/ds-components/Button'; + +import * as styles from './index.module.scss'; + +type Props = { + data: { + id: string; + organizationId: string; + tenantName: string; + tenantTag: TenantTag; + }; +}; + +function TenantInvitationDropdownItem({ data }: Props) { + const cloudApi = useCloudApi(); + const { navigateTenant, resetTenants } = useContext(TenantsContext); + const { id, organizationId, tenantName, tenantTag } = data; + + return ( +
+
+
{tenantName}
+ +
+
+ ); +} + +export default TenantInvitationDropdownItem; diff --git a/packages/console/src/components/Topbar/TenantSelector/index.tsx b/packages/console/src/components/Topbar/TenantSelector/index.tsx index 274500ae1..99e4eee98 100644 --- a/packages/console/src/components/Topbar/TenantSelector/index.tsx +++ b/packages/console/src/components/Topbar/TenantSelector/index.tsx @@ -1,3 +1,4 @@ +import { OrganizationInvitationStatus } from '@logto/schemas'; import { useContext, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -11,9 +12,11 @@ import Divider from '@/ds-components/Divider'; import Dropdown from '@/ds-components/Dropdown'; import OverlayScrollbar from '@/ds-components/OverlayScrollbar'; import useUserDefaultTenantId from '@/hooks/use-user-default-tenant-id'; +import useUserInvitations from '@/hooks/use-user-invitations'; import { onKeyDownHandler } from '@/utils/a11y'; import TenantDropdownItem from './TenantDropdownItem'; +import TenantInvitationDropdownItem from './TenantInvitationDropdownItem'; import * as styles from './index.module.scss'; export default function TenantSelector() { @@ -25,6 +28,7 @@ export default function TenantSelector() { currentTenantId, navigateTenant, } = useContext(TenantsContext); + const { data: pendingInvitations } = useUserInvitations(OrganizationInvitationStatus.Pending); const anchorRef = useRef(null); const [showDropdown, setShowDropdown] = useState(false); @@ -76,6 +80,9 @@ export default function TenantSelector() { }} /> ))} + {pendingInvitations?.map((invitation) => ( + + ))}